Java WEB管理系统
文章目录
java web 第二次作业讲解
需求分析
要求完成注册登录以及表单验证
完成登录之后跳转至首页
概要设计
技术选型
依赖管理:maven
异步交互:AJAX
数据库:MySQL5.6
交互数据格式:JSON
测试:Junit
采用姓名和学号登录(坑)。
文件目录以及梳理:
│ pom.xml # maven配置文件
├─src # 源代码路径
│ ├─main
│ │ ├─java
│ │ │ ├─dao # 访问数据库
│ │ │ │ │ LiangZaiDao.java # 访问靓仔数据库的接口
│ │ │ │ │
│ │ │ │ └─imlp
│ │ │ │ LiangZaiDaoImpl.java # 靓仔dao的实现类
│ │ │ │
│ │ │ ├─filter
│ │ │ │ CharacterFilter.java # 字符过滤器
│ │ │ │ LoginFilter.java # 首页过滤器
│ │ │ │
│ │ │ ├─pojo # 实体
│ │ │ │ LiangZai.java # 靓仔实体类
│ │ │ │ ResultInfo.java # 响应数据类
│ │ │ │
│ │ │ ├─service # 业务
│ │ │ │ │ LiangZaiService.java # 靓仔业务逻辑接口
│ │ │ │ │
│ │ │ │ └─impl
│ │ │ │ LiangZaiServiceImpl.java # 靓仔业务逻辑实现类
│ │ │ │
│ │ │ ├─servlet # 处理前后端交互
│ │ │ │ LoginServlet.java # 处理登录交互
│ │ │ │ RegisterServlet.java # 处理注册交互
│ │ │ │
│ │ │ └─utils
│ │ │ DbUtil.java # JDBC工具类
│ │ │
│ │ ├─resources
│ │ │ db.propertice # JDBC配置
│ │ │
│ │ └─webapp # 前端代码
│ │ │ index.html # 首页
│ │ │ login.html # 登录页面
│ │ │ register.html # 注册页面
│ │ ├─css
│ │ │ layui.css
│ │ │ style.css
│ │ ├─img
│ │ └─js
│ │
│ └─test # 测试类
│ └─java
│ LiangDaoTest.java # Dao测试类
总体设计
第一步:数据库搭建
此处仅提供数据库结构,因为本次作业不是我主要负责,所以我取名比较随意(靓仔),实际开发请勿模仿。
自行根据自己的想法修改数据库并添加数据。
DROP TABLE IF EXISTS `liangzai`;
CREATE TABLE `liangzai` (
`id` int(20) NOT NULL AUTO_INCREMENT,
`name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`sex` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`class` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`stu_id` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
`password` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 13 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = Compact;
第二步:IDEA创建项目
建议创建maven项目或java ee项目(spring 项目也行),此处采用java ee项目(tomcat8.0以上支持cookie写入中文,servlet3.0以上支持注解配置)
项目目录如下:
因为采用异步交互,所以删去index.jsp文件。
第三步:导入依赖
在pom.xml文件中粘贴以下代码
<dependencies>
<!--项目创建好自带的servlet-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<!--MySQL数据库连接依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.37</version>
</dependency>
<!--junit测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>RELEASE</version>
<scope>test</scope>
</dependency>
<!--beanUtils-->
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.2</version>
<scope>compile</scope>
</dependency>
<!--jackson-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.3.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.3.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.3.3</version>
</dependency>
</dependencies>
第四步:创建实体类
需要在java文件夹下创建一个pojo文件夹并在其中新建两个类一个为:LiangZai,一个为ResultInfo。LiangZai用于映射数据库,ResultInfo用于与前端的交互
具体代码如下:
package pojo;
/**
* @author 北落燕门
*/
public class LiangZai {
private int id;
private String name;
private String sex;
private String banJi;
private String stuId;
@Override
public String toString() {
return "Liang{" +
"id=" + id +
", name='" + name + '\'' +
", sex='" + sex + '\'' +
", banJi='" + banJi + '\'' +
", stuId='" + stuId + '\'' +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getBanJi() {
return banJi;
}
public void setBanJi(String banJi) {
this.banJi = banJi;
}
public String getStuId() {
return stuId;
}
public void setStuId(String stuId) {
this.stuId = stuId;
}
public LiangZai(int id, String name, String sex, String banJi, String stuId) {
this.id = id;
this.name = name;
this.sex = sex;
this.banJi = banJi;
this.stuId = stuId;
}
public LiangZai() {
}
}
package pojo;
/**
* @author 北落燕门
*/
public class ResultInfo {
private boolean flag;
private Object data;
private String msg;
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public String getMsg() {
return msg;
}
public void setMsg(String errorMsg) {
this.msg = errorMsg;
}
public ResultInfo(boolean flag, Object data, String errorMsg) {
this.flag = flag;
this.data = data;
this.msg = errorMsg;
}
public ResultInfo() {
}
}
第五步:连接数据库
编写配置文件
在resources文件夹下创建db.propertice文件然后输入以下内容
driver = com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/[数据库名称]?UseUnicode=true&characterEncoding=UTF-8
username = [数据库用户名]
password = [数据库密码]
实现JDBC建立连接
在java文件夹下新建utils文件夹并创建DbUtil类,内容如下:
package utils;
import com.mysql.jdbc.Connection;
import com.mysql.jdbc.Driver;
import java.io.FileReader;
import java.net.URL;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Properties;
/**
* @author 北落燕门
*/
public class DbUtil {
private static String url;
private static String username;
private static String password;
//使用静态方法自动执行
static {
try {
//实用反射将db.propertice文件加载进内存
Properties pro = new Properties();
ClassLoader classLoader = Driver.class.getClassLoader();
URL resource = classLoader.getResource("db.propertice");
assert resource != null;
String path = resource.getPath();
FileReader fileReader = new FileReader(path);
pro.load(fileReader);
//获取db.propertice文件的内容
String driver = pro.getProperty("driver");
url = pro.getProperty("url");
username = pro.getProperty("username");
password = pro.getProperty("password");
//加载驱动
Class.forName(driver);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 建立连接
* @return 返回Connecting连接对象
* @throws Exception 抛出异常
*/
public static Connection getConnection()throws Exception{
return (Connection) DriverManager.getConnection(url, username, password);
}
/**
* 关闭连接
* @param ps
* @param conn
*/
public static void close(PreparedStatement ps, Connection conn){
if (ps!=null){
try {
ps.close();
}catch (Exception e){
e.printStackTrace();
}
}else if (conn!=null){
try {
conn.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
/**
* 方法重载 关闭连接
* @param rs
* @param ps
* @param conn
*/
public static void close(ResultSet rs, PreparedStatement ps, Connection conn){
if (rs!=null){
try {
rs.close();
}catch (Exception e){
e.printStackTrace();
}
}else if (ps!=null){
try {
ps.close();
}catch (Exception e){
e.printStackTrace();
}
}else if (conn!=null){
try {
conn.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
}
第六步:实现Dao层
之后在java文件夹下创建dao文件夹,并创建LiangZaiDao接口
根据任务需求我们需要实现添加实体、查询实体的功能,因此创建以下三个抽象方法
/**
* 通过id和password查找
* @param name 姓名
* @param stuId 班级
* @return flag
*/
boolean findByNameAndStuId(String name, String stuId);
/**
* 通过用户名和密码查找
* @param id id
* @return flag
*/
boolean findById(int id);
/**
* 添加
* @param lz 传入靓仔对象
* @return flag
*/
boolean add(LiangZai lz);
之后在dao文件夹下新建impl文件夹并创建LiangZaiDaoImpl类继承LiangZaiDao接口并复写其中所有方法。返回值boolean类型用于判断是否执行成功。代码如下:
public class LiangZaiDaoImpl implements LiangZaiDao {
Connection conn = null;
PreparedStatement pstm = null ;
ResultSet rs = null;
/**
* 用于登录界面在数据库中查询姓名与学号
* @param name 姓名
* @param stuId 学号
* @return flag
*/
@Override
public boolean findByNameAndStuId(String name, String stuId) {
//编写sql
String sql = "SELECT * FROM liangzai WHERE name = ? AND stu_id = ?";
try {
//调用DbUtil建立连接
conn = DbUtil.getConnection();
//开启事务
conn.setAutoCommit(false);
//绑定sql
pstm = conn.prepareStatement(sql);
//补全sql语句
pstm.setString(1,name);
pstm.setString(2,stuId);
//执行sql
rs = pstm.executeQuery();
if (rs.next()){
//提交
conn.commit();
return true;
}
} catch (Exception e) {
try {
//回滚
if (conn!=null){
conn.rollback();
}
}catch (Exception e1){
e1.printStackTrace();
}
e.printStackTrace();
}finally {
//关闭数据库连接
DbUtil.close(rs,pstm,conn);
}
return false;
}
/**
* 用于查询用户是否存在(不用于登录)
* @param id id
* @return flag
*/
@Override
public boolean findById(int id) {
//编写sql
String sql = "SELECT * FROM liangzai WHERE id = ?";
try {
//建立连接
conn = DbUtil.getConnection();
//开启事务
conn.setAutoCommit(false);
//绑定sql语句
pstm = conn.prepareStatement(sql);
pstm.setInt(1,id);
//执行sql
rs = pstm.executeQuery();
if (rs.next()){
conn.commit();
return true;
}
} catch (Exception e) {
try{
if (conn!=null){
//回滚
conn.rollback();
}
}catch (Exception e1){
e1.printStackTrace();
}
e.printStackTrace();
}finally {
//关闭数据库连接
DbUtil.close(rs,pstm,conn);
}
return false;
}
/**
* 用于注册等对数据库进行添加的操作
* @param lz 传入靓仔对象
* @return flag
*/
@Override
public boolean add(LiangZai lz) {
//编写sql
String sql = "INSERT INTO liangzai(name,sex,class,stu_id) VALUES(?,?,?,?)";
try {
//建立连接
conn = DbUtil.getConnection();
//开启事务
conn.setAutoCommit(false);
pstm = conn.prepareStatement(sql);
pstm.setString(1,lz.getName());
pstm.setString(2,lz.getSex());
pstm.setString(3,lz.getBanJi());
pstm.setString(4,lz.getStuId());
int i = pstm.executeUpdate();
if (i!=0){
//提交事务
conn.commit();
return true;
}
} catch (Exception e) {
try{
if (conn!=null){
//回滚
conn.rollback();
}
}catch (Exception e1){
e1.printStackTrace();
}
e.printStackTrace();
}finally {
//关闭连接
DbUtil.close(pstm,conn);
}
return false;
}
}
第七步:实现service层
在java文件夹下新建一个包命名为service其中新建一个接口命名为LiangZaiService。
package service;
import pojo.LiangZai;
/**
* @author 北落燕门
*/
public interface LiangZaiService {
/**
* 登录服务
* @param lz 靓仔实体
* @return 返回实体对象
*/
boolean liangZaiLogin(LiangZai lz);
/**
* 注册服务
* @param lz 靓仔实体
* @return 返回flag
*/
boolean liangZaiRegister(LiangZai lz);
}
之后在service文件夹中新建文件夹并创建类LiangZaiServiceImpl实现LiangZaiService接口
package service.impl;
import dao.LiangZaiDao;
import dao.imlp.LiangZaiDaoImpl;
import pojo.LiangZai;
import service.LiangZaiService;
/**
* @author 北落燕门
*/
public class LiangZaiServiceImpl implements LiangZaiService {
LiangZaiDao lzDao = new LiangZaiDaoImpl();
@Override
public boolean liangZaiLogin(LiangZai lz) {
return lzDao.findByNameAndStuId(lz.getName(), lz.getStuId());
}
@Override
public boolean liangZaiRegister(LiangZai lz) {
boolean byNameAndStuId = lzDao.findByNameAndStuId(lz.getName(), lz.getStuId());
if (byNameAndStuId){
return false;
}
return lzDao.add(lz);
}
}
第八步:实现servlet
注册servlet
package servlet;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.beanutils.BeanUtils;
import pojo.LiangZai;
import pojo.ResultInfo;
import service.impl.LiangZaiServiceImpl;
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.lang.reflect.InvocationTargetException;
import java.util.Map;
/**
* @author 北落燕门
*/
@WebServlet("/register")
public class RegisterServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//封装获取到的数据为map
Map<String, String[]> map = req.getParameterMap();
LiangZai lz = new LiangZai();
try {
//使用工具类将map元素封装为对象
BeanUtils.populate(lz,map);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
System.out.println(lz);
LiangZaiServiceImpl liangZaiService = new LiangZaiServiceImpl();
boolean flag = liangZaiService.liangZaiRegister(lz);
ResultInfo resultInfo = new ResultInfo();
if (flag){
resultInfo.setFlag(true);
resultInfo.setMsg("注册成功");
}else {
resultInfo.setFlag(false);
resultInfo.setMsg("注册失败");
}
//响应数据
ObjectMapper mapper = new ObjectMapper();
resp.setContentType("application/json;charset=UTF-8");
mapper.writeValue(resp.getOutputStream(),resultInfo);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
}
登录servlet
package servlet;
import com.fasterxml.jackson.databind.ObjectMapper;
import pojo.LiangZai;
import pojo.ResultInfo;
import service.LiangZaiService;
import service.impl.LiangZaiServiceImpl;
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;
/**
* @author 北落燕门
*/
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
LiangZai lz = new LiangZai();
ResultInfo resultInfo = new ResultInfo();
lz.setName(req.getParameter("name"));
lz.setStuId(req.getParameter("stuId"));
LiangZaiService liangZaiService = new LiangZaiServiceImpl();
boolean flag = liangZaiService.liangZaiLogin(lz);
if (!flag){
resultInfo.setMsg("用户名或密码错误");
resultInfo.setFlag(false);
}else{
resultInfo.setMsg("登录成功");
resultInfo.setFlag(true);
req.getSession().setAttribute("liangzai",lz);
//跳转首页
//req.getRequestDispatcher("index.html").forward(req,resp);
}
//响应数据
ObjectMapper mapper = new ObjectMapper();
resp.setContentType("application/json;charset=UTF-8");
mapper.writeValue(resp.getOutputStream(),resultInfo);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
}
第九步:实现前台
我们需要三个页面:index.html,login.html,register.html
通过login.html的登录之后才能转跳到index.html
在webapp文件夹下新建这三个文件夹
login.html(此处只给出核心代码)
<script>
$(function () {
//给登录按钮绑定单击事件
$('#btn').click(function () {
var serializeUrl = $('#login').serialize();
//console.log(serializeUrl)
$.post('/login', serializeUrl, function (data) {
if (data.flag) {
var serializeUrl = $('#login').serialize();
location.href = 'index.html';
} else {
// var serializeUrl = $("#login").serialize();
console.log(data);
alert('用户名或密码错误,登录失败...');
}
});
});
});
</script>
<div class="switch">
<h2>没有账号?</h2>
<a href="register.html">注册账号</a>
</div>
<div class="main">
<form action="" id="login" method="post" accept-charset="utf-8">
<h1>欢迎访问</h1>
<input name="name" type="text" placeholder="姓名" required />
<input name="stuId" type="password" placeholder="学号" required />
<button type="button" id="btn" class="btn">登录</button>
</form>
</div>
</body>
register.html
<script>
$(function () {
//表单提交时进行校验
$('#btn').click(function () {
// return false;
//发送数据到服务器
//校验通过发送ajax请求,提交表单数据
$.post('/register', $('#registerForm').serialize(), function (data) {
console.log($('#registerForm').serialize());
if (data.flag) {
alert('注册成功');
} else {
alert('注册失败');
}
});
return false;
});
</script>
<div class="switch">
<h2>已有账号?</h2>
<a href="./login.html">点击登录</a>
</div>
<div class="main">
<form
action=""
id="registerForm"
method="post"
accept-charset="UTF-8"
class="sign"
>
<h1>注册账号</h1>
<input name="name" type="text" placeholder="姓名" required />
<input name="stuId" type="text" placeholder="学号" required />
<input name="sex" type="text" placeholder="性别" required />
<input name="banJi" type="text" placeholder="班级" required />
<button class="btn" id="btn" type="button">注册</button>
</form>
</div>
</body>
index.html
自行补充
第十步:过滤器
这里我们需要实现两个过滤器,一个是CharacterFilter,一个是LoginFilter。CharacterFilter用于统一请求与响应的汉字编码格式为UTF-8,LoginFilter用于解决在uri直接输入/index.html便可绕过登录访问主页的问题。
CharacterFilter
package filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author 北落燕门
*/
@WebFilter("/*")
public class CharacterFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
//获取请求方式
String method = req.getMethod();
String post = "post";
if (post.equals(method)){
req.setCharacterEncoding("UTF-8");
}
//处理响应乱码
resp.setContentType("text/html;charset=UTF-8");
chain.doFilter(req,resp);
}
@Override
public void destroy() {
Filter.super.destroy();
}
}
LoginFilter
package filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author 北落燕门
*/
@WebFilter("/index.html")
public class LoginFilter implements Filter{
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
Object lz = req.getSession().getAttribute("liangzai");
if (lz!=null){
chain.doFilter(req,resp);
}else {
req.setAttribute("login_msg","您尚未登录,请登录");
req.getRequestDispatcher("login.html").forward(req,resp);
}
}
@Override
public void destroy() {
}
}