项目搭建
原创大约 10 分钟
项目搭建
接下来搭建javaweb的项目
本次教程主要使用idea进行开发,eclipse也是可以的,只要对eclipse的基本使用熟悉就好!
我也会演示一下怎么用eclipse创建项目!
提示:
如果文档里面有错误或者疑问,可以通过B站提醒我~
前端模板下载
我这里使用的是笔下光年这款前端模板,可以直接通过gitee下载:
登录页面
- 在做页面之前,把资源文件粘贴进我们自己的项目
- 新建login.jsp, 挑选一个笔下光年现成的登录页面,粘贴进login.jsp
注意点:粘贴后,注意修改资源路径!资源路径强烈建议使用绝对路径,而不是相对路径
${pageContext.request.contextPath}
首页制作
- 搞懂笔下光年index.html的代码结构,仿造一个自己想要的首页,并且整合到自己的系统中
- 分析代码结构,分离出公共代码部分!
接下来我们逐步完成登录功能、验证码功能、然后增删改查功能,在此之前需要先创建实体类、连接数据库
创建实体类
管理员实体类
public class Admin {
private String username;//用户名
private String password;//密码
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
学生实体类
import java.util.Date;
public class Student {
private String sno;//学号
private String password;//密码
private String name;//姓名
private String tele;//电话
private Date enterdate;//入学时间
private Integer age;//年龄
private String gender;//性别 m 男 w 女
private String address;//详细地址
private String clazzno;//班级
public String getSno() {
return sno;
}
public void setSno(String sno) {
this.sno = sno;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTele() {
return tele;
}
public void setTele(String tele) {
this.tele = tele;
}
public Date getEnterdate() {
return enterdate;
}
public void setEnterdate(Date enterdate) {
this.enterdate = enterdate;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getClazzno() {
return clazzno;
}
public void setClazzno(String clazzno) {
this.clazzno = clazzno;
}
}
班级
public class Clazz {
private String clazzno;//班级编号
private String name;//班级名
public String getClazzno() {
return clazzno;
}
public void setClazzno(String clazzno) {
this.clazzno = clazzno;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
引入jar包
将jar包粘贴到创建的lib文件夹下,并且将它配置到项目依赖下
jar包解释,大概了解一下,后面会用到:
- mysql-connector-java-8.0.20.jar 连接mysql用的
- fastjson-1.2.47.jar 将对象序列化成json字符串
- javax.servlet-api-3.1.0.jar servlet 相关依赖
- jstl-1.2.jar jstl相关包,在jsp中可以使用if等逻辑判断、时间格式化
创建JdbcHelper
数据库操作工具类
import java.sql.*;
/**
* 数据库操作公共类
*/
public class JdbcHelper {
private static final String className = "com.mysql.cj.jdbc.Driver";
private static final String url = "jdbc:mysql://localhost:3306/stu_manage?serverTimezone=GMT%2B8&characterEncoding=utf-8&allowPublicKeyRetrieval=true&useSSL=false";
private static final String user = "root";
private static final String pass = "123456";// 自行修改密码
//测试
public static void main(String[] args) throws SQLException {
JdbcHelper jdbcHelper = new JdbcHelper();
ResultSet rs = jdbcHelper.executeQuery("select * from tb_student");
while (rs.next()){
String sno = rs.getString("sno");
String name = rs.getString("name");
Integer age = rs.getInt("age");
Date enterdate = rs.getDate("enterdate");
System.out.println(sno);
System.out.println(name);
System.out.println(age);
System.out.println(enterdate);
System.out.println();
}
jdbcHelper.closeDB();
}
private Connection conn = null;
private PreparedStatement pstmt = null;
private ResultSet rs = null;
//JdbcHelper类加载的时候,加载数据库驱动程序
static {
try {
Class.forName(className);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public JdbcHelper(){
try {
conn = DriverManager.getConnection(url,user,pass);
} catch (SQLException e) {
e.printStackTrace();
}
}
//执行查询
public ResultSet executeQuery(String sql, Object... params){
try {
pstmt = conn.prepareStatement(sql);
if (params != null) {
for (int i = 0; i < params.length; i++) {
pstmt.setObject(i + 1, params[i]);
}
}
rs = pstmt.executeQuery();
} catch (SQLException e) {
e.printStackTrace();
}
return rs;
}
//执行增删改
public int executeUpdate(String sql, Object... params){
int row = -1;
try {
pstmt = conn.prepareStatement(sql);
if (params != null) {
for (int i = 0; i < params.length; i++) {
pstmt.setObject(i + 1, params[i]);
}
}
row = pstmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
return row;
}
public void closeDB(){
try{
if(rs != null){
rs.close();
}
if(pstmt != null){
pstmt.close();
}
if(conn != null){
conn.close();
}
}catch(SQLException e){
e.printStackTrace();
}
}
}
mysql5注意点
如果是你mysql5的话!需要替换成mysql5的jar包,代码有两处需要修改
//mysql5的驱动
private static final String className = "com.mysql.jdbc.Driver";
//mysql5的url
private static final String url="jdbc:mysql://localhost:3306/stu_manage?characterEncoding=utf8&useSSL=false";
登录功能
登录流程:
- 1 前端点击登录按钮,发送ajax请求给后端。
- 2 后端收到请求,根据账号密码、用户类型去数据库里面查询账号信息比对
- 3 保存用户Session信息,返回登录结果
ApiResult.java
首先创建ApiResult.java 用于给前端ajax请求返回信息
package com.hello.utils;
import com.alibaba.fastjson.JSON;
import java.io.Serializable;
/**
* ajax请求返回内容
* success表示成功与否
* message是提示消息
* data是数据
*/
public class ApiResult implements Serializable {
private Boolean success;
private String message;
private Object data;
public ApiResult(Boolean success, String message, Object data) {
this.success = success;
this.message = message;
this.data = data;
}
public static String json(Boolean success, String message, Object data) {
return JSON.toJSONString(new ApiResult(success,message,data));
}
public static String json(Boolean success, String message) {
return JSON.toJSONString(new ApiResult(success,message,null));
}
public Boolean getSuccess() {
return success;
}
public void setSuccess(Boolean success) {
this.success = success;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
AdminDao、AdminService
AdminDao
package com.hello.dao;
import com.hello.entity.Admin;
import com.hello.utils.JdbcHelper;
import java.sql.ResultSet;
public class AdminDao {
public Admin getByUsername(String username){
JdbcHelper helper = new JdbcHelper();
ResultSet resultSet = helper.executeQuery("select * from tb_admin where username = ?",username);
try {
if(resultSet.next()){
Admin admin = new Admin();
admin.setUsername( resultSet.getString("username"));
admin.setPassword( resultSet.getString("password"));
return admin;
}
}catch (Exception e){
e.printStackTrace();
}finally {
helper.closeDB();
}
return null;
}
}
AdminService
package com.hello.service;
import com.hello.dao.AdminDao;
import com.hello.entity.Admin;
public class AdminService {
AdminDao adminDao = new AdminDao();
public Admin getByUsername(String username){
return adminDao.getByUsername(username);
}
}
StudentDao、StudentService
StudentDao
package com.hello.dao;
import com.hello.entity.Student;
import com.hello.utils.JdbcHelper;
import java.sql.ResultSet;
public class StudentDao {
public Student getBySno(String sno){
JdbcHelper helper = new JdbcHelper();
ResultSet resultSet = helper.executeQuery("select * from tb_student where sno = ?",sno);
try {
if(resultSet.next()){
Student student = new Student();
student.setSno(resultSet.getString("sno"));
student.setPassword(resultSet.getString("password"));
student.setName(resultSet.getString("name"));
student.setTele(resultSet.getString("tele"));
student.setEnterdate(resultSet.getDate("enterdate"));
student.setAge(resultSet.getInt("age"));
student.setGender(resultSet.getString("gender"));
student.setAddress(resultSet.getString("address"));
student.setClazzno(resultSet.getString("clazzno"));
return student;
}
}catch (Exception e){
e.printStackTrace();
}finally {
helper.closeDB();
}
return null;
}
}
StudentService
package com.hello.service;
import com.hello.dao.StudentDao;
import com.hello.entity.Student;
public class StudentService {
StudentDao dao = new StudentDao();
public Student getBySno(String sno) {
Student student = dao.getBySno(sno);
return student;
}
}
LoginServlet
import com.hello.entity.*;
import com.hello.service.*;
import com.hello.utils.ApiResult;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
/**
* 用于登录的Servlet
*/
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
AdminService adminService = new AdminService();
StudentService studentService = new StudentService();
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");// 设置编码,否则从前端获取参数乱码
resp.setContentType("application/json; charset=utf-8");
//获取请求参数
String username = req.getParameter("username");
String password = req.getParameter("password");
String usertype = req.getParameter("usertype");
//判断角色
if (usertype.equals("admin")) {
//根据账号获取数据库信息
Admin admin = adminService.getByUsername(username);
if(admin == null){
resp.getWriter().print(ApiResult.json(false,"用户不存在"));
return;
}
if(admin.getPassword().equals(password)){
req.getSession().setAttribute("role","admin");
req.getSession().setAttribute("user",admin);
resp.getWriter().print(ApiResult.json(true,"登录成功"));
return;
}else{
resp.getWriter().print(ApiResult.json(false,"密码错误,登录失败"));
return;
}
}else{
Student student = studentService.getBySno(username);
if(student == null){
resp.getWriter().print(ApiResult.json(false,"用户不存在"));
return;
}
if(student.getPassword().equals(password)){
req.getSession().setAttribute("role","student");
req.getSession().setAttribute("user",student);
resp.getWriter().print(ApiResult.json(true,"登录成功"));
return;
}else{
resp.getWriter().print(ApiResult.json(false,"密码错误,登录失败"));
return;
}
}
}
}
前端登录功能
角色选择
<div class="form-group" style="text-align: center">
<input checked type="radio" name="usertype" value="admin">管理员
<input type="radio" name="usertype" value="emp">学生
</div>
登录ajax请求
function login() {
let username = $("#username").val()
let password = $("#password").val()
let usertype = $("input[name=usertype]:checked").val()
console.log(username,password,usertype)
$.ajax({
type: "post",
url: "${pageContext.request.contextPath}/login",
dataType: 'json',
data: {
username: username,
password: password,
usertype: usertype,
},
success: function (data) {
if(data.success){
location.href="${pageContext.request.contextPath}/index.jsp";
}else{
alert(data.message)
}
},
error: function () {
alert("请求服务器失败");
}
});
}
登录验证码
login.jsp中,验证码图片的src改成:${pageContext.request.contextPath}/captcha
发送ajax请求时候,把验证码传给后端
然后添加验证码servlet、修改下IndexServlet
package com.hello.servlet;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
/** 生成验证码的工具 */
@WebServlet("/captcha")
public class CaptchaServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public static final int WIDTH = 120; // 生成图片的宽度
public static final int HEIGHT = 38; // 生成图片的高度
public static final int WORDS_NUMBER = 4; // 验证码中字符的个数
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String createTypeFlag = req.getParameter("createTypeFlag"); // 接收客户端传递的createTypeFlag标识
// 在内存中创建一张图片
BufferedImage bi = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_3BYTE_BGR);
// 得到图片
Graphics g = bi.getGraphics();
// 设置图片的背景色
setBackGround(g);
// 设置图片的边框
setBorder(g);
// 在图片上画干扰线
drawRandomLine(g);
// 在图片上放上随机字符
String randomString = this.drawRandomNum(g, createTypeFlag);
// 将随机数存在session中
req.getSession().setAttribute("captcha", randomString);
System.out.println(randomString);
// 设置响应头通知浏览器以图片的形式打开
resp.setContentType("image/jpeg");
// 设置响应头控制浏览器不要缓存
resp.setDateHeader("expries", -1);
resp.setHeader("Cache-Control", "no-cache");
resp.setHeader("Pragma", "no-cache");
// 将图片传给浏览器
ImageIO.write(bi, "jpg", resp.getOutputStream());
}
// 设置图片背景色
// @param g
private void setBackGround(Graphics g) {
// 设置颜色
g.setColor(Color.WHITE);
// 填充区域
g.fillRect(0, 0, WIDTH, HEIGHT);
}
/*
* 设置图片的边框
* @param g
* */
private void setBorder(Graphics g) {
// 设置边框颜色
g.setColor(Color.WHITE);
// 边框区域
g.drawRect(1, 1, WIDTH - 2, HEIGHT - 2);
}
/*
* 在图片上画随机线条
* @param g
* */
private void drawRandomLine(Graphics g) {
// 设置颜色
g.setColor(Color.GREEN);
// 设置线条个数并画线
for (int i = 0; i < 3; i++) {
int x1 = new Random().nextInt(WIDTH);
int y1 = new Random().nextInt(HEIGHT);
int x2 = new Random().nextInt(WIDTH);
int y2 = new Random().nextInt(HEIGHT);
g.drawLine(x1, y1, x2, y2);
}
}
/*
* 在图片上画随机字符
* @param g
* @param createTypeFlag
* @return String
* */
private String drawRandomNum(Graphics g, String createTypeFlag) {
// 设置颜色
g.setColor(Color.RED);
g.setFont(new Font("宋体", Font.BOLD, 20));
// 数字字母的组合
String baseNumLetter = "123456789ABCDEFGHJKMNPQRSTUVWXYZ";
String baseNum = "123456789";
String baseLetter = "ABCDEFGHJKMNPQRSTUVWXYZ";
if (createTypeFlag != null && createTypeFlag.length() > 0) {
if (createTypeFlag.equals("nl")) {
// 截取数字和字母的组合
return createRandomChar((Graphics2D) g, baseNumLetter);
} else if (createTypeFlag.equals("n")) {
// 截取数字的组合
return createRandomChar((Graphics2D) g, baseNum);
} else if (createTypeFlag.equals("l")) {
// 截取字母的组合
return createRandomChar((Graphics2D) g, baseLetter);
}
} else {
// 截取数字和字母的组合
return createRandomChar((Graphics2D) g, baseNumLetter);
}
return "";
}
/*
* 创建随机字符
* @param g
* @param baseChar
* @return String
* */
private String createRandomChar(Graphics2D g, String baseChar) {
StringBuffer b = new StringBuffer();
int x = 5;
String ch = "";
for (int i = 0; i < WORDS_NUMBER; i++) {
// 设置字体的旋转角度
int degree = new Random().nextInt() % 30;
ch = baseChar.charAt(new Random().nextInt(baseChar.length())) + "";
b.append(ch);
// 正向角度
g.rotate(degree * Math.PI / 180, x, 20);
g.drawString(ch, x, 20);
// 反向角度
g.rotate(-degree * Math.PI / 180, x, 20);
x += 30;
}
return b.toString();
}
}
修改下IndexServlet
String captcha = req.getParameter("captcha");
Object sessionCaptcha = req.getSession().getAttribute("captcha");
if(captcha == null || !captcha.equalsIgnoreCase((String) sessionCaptcha)){
resp.getWriter().print(ApiResult.json(false,"验证码错误!"));
return;
}
首页展示数据
首页需要展示班级数、学生数、各班级学生数量echarts图,可以通过ajax请求方式获取数据
为了统计班级的学生数量,可以在班积类里面加一个int stuCount
来接收学生数量
ClazzDao
package com.hello.dao;
import com.hello.entity.Clazz;
import com.hello.utils.JdbcHelper;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
public class ClazzDao {
//班级数量
public int count(){
JdbcHelper helper = new JdbcHelper();
ResultSet resultSet = helper.executeQuery("select count(1) from tb_clazz");
try {
resultSet.next();
return resultSet.getInt(1);
}catch (Exception e){
e.printStackTrace();
}finally {
helper.closeDB();
}
return 0;
}
//班级学生统计
public List<Clazz> statistics(){
JdbcHelper helper = new JdbcHelper();
ResultSet resultSet = helper.executeQuery(
"select c.clazzno,c.name,count(1) as stuCount " +
"from tb_clazz c, tb_student s " +
"where s.clazzno = c.clazzno " +
"group by c.clazzno,c.name "
);
try {
List<Clazz> clazzes = new ArrayList<>();
while (resultSet.next()){
Clazz clazz = new Clazz();
clazz.setStuCount(resultSet.getInt("stuCount"));
clazz.setClazzno(resultSet.getString("clazzno"));
clazz.setName(resultSet.getString("name"));
clazzes.add(clazz);
}
return clazzes;
}catch (Exception e){
e.printStackTrace();
}finally {
helper.closeDB();
}
return null;
}
}
ClazzService
package com.hello.service;
import com.hello.dao.ClazzDao;
import com.hello.entity.Clazz;
import java.util.List;
public class ClazzService {
ClazzDao dao = new ClazzDao();
public int count(){
return dao.count();
}
public List<Clazz> statistics(){
return dao.statistics();
}
}
StudentDao添加统计方法
/**
* 获取学生数量
* @return
*/
public int count() {
JdbcHelper helper = new JdbcHelper();
ResultSet resultSet = helper.executeQuery("select count(1) from tb_student");
try {
resultSet.next();
return resultSet.getInt(1);
}catch (Exception e){
e.printStackTrace();
}finally {
helper.closeDB();
}
return 0;
}
IndexServlet
import com.hello.entity.Clazz;
import com.hello.service.ClazzService;
import com.hello.service.StudentService;
import com.hello.utils.ApiResult;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 首页的数据
*/
@WebServlet("/index")
public class IndexServlet extends HttpServlet {
StudentService studentService = new StudentService();
ClazzService clazzService = new ClazzService();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");// 设置编码,否则从前端获取参数乱码
resp.setContentType("application/json; charset=utf-8");
int clazzCount = clazzService.count();
int studentCount = studentService.count();
List<Clazz> clazzes = clazzService.statistics();
Map<String,Object> res = new HashMap<>();
res.put("clazzCount",clazzCount);
res.put("studentCount",studentCount);
res.put("clazzes",clazzes);
resp.getWriter().write(ApiResult.json(true,"成功",res));
}
}
index.jsp修改
$(document).ready(function(e) {
$.ajax({
type: "get",//注意,这里使用的是get请求
url: "${pageContext.request.contextPath}/index",
dataType: 'json',
success: function (data) {
if(data.success){
let clazzCount = data.data.clazzCount
let studentCount = data.data.studentCount
let clazzes = data.data.clazzes
console.log(clazzCount)
console.log(studentCount)
$("#clazzCount").text(clazzCount)
$("#studentCount").text(studentCount)
let chartLabels = []
let chartData = []
for (let i = 0; i < clazzes.length; i++) {
chartLabels.push(clazzes[i].name)
chartData.push(clazzes[i].stuCount)
}
var $dashChartBarsCnt = jQuery( '.js-chartjs-bars' )[0].getContext( '2d' )
var $dashChartBarsData = {
labels: chartLabels,
datasets: [
{
label: '学生数',
borderWidth: 1,
borderColor: 'rgba(0,0,0,0)',
backgroundColor: 'rgba(51,202,185,0.5)',
hoverBackgroundColor: "rgba(51,202,185,0.7)",
hoverBorderColor: "rgba(0,0,0,0)",
data: chartData
}
]
};
new Chart($dashChartBarsCnt, {
type: 'bar',
data: $dashChartBarsData,
options:{
scales: {
yAxes: [
{
ticks: {
min: 0, //最小值
},
display: true
}
]
}
}
});
}else{
alert(data.message)
}
},
error: function () {
alert("请求服务器失败");
}
});
});