跳至主要內容

项目搭建

学长敲代码原创大约 10 分钟教程javaweb

项目搭建

接下来搭建javaweb的项目

本次教程主要使用idea进行开发,eclipse也是可以的,只要对eclipse的基本使用熟悉就好!

我也会演示一下怎么用eclipse创建项目!

提示:

如果文档里面有错误或者疑问,可以通过B站提醒我~

前端模板下载

我这里使用的是笔下光年这款前端模板,可以直接通过gitee下载:

笔下光年前端模板下载地址open in new window

登录页面

  • 在做页面之前,把资源文件粘贴进我们自己的项目
  • 新建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("请求服务器失败");
      }
    });

  });