【员工信息管理】
1.员工信息管理
1.1 介绍
用户进行登录后,可以对员工信息进行管理(增删查改),等操作.如果用户没有登录,不能访问员工操作页面.并且员工操作页面显示当前登录用户信息.
1.2 技术点
使用Vue+ElementUI充当前端界面,使用Servlet+JDBC+Mysql提供数据管理控制.后端统一向前端返回JSON格式的数据.
2. 项目搭建
2.1 统一前置处理
2.1.1 过滤器
由于所有的请求都是servlet进行处理,但是存在一些共性问题,例如:编码格式,跨域响应头.基于这样的情况,早期web设计者,定义一个对所有请求进行过滤的组件,这个组件叫过滤器.通过实现过滤器的规范,将过滤器注册到服务器,过滤器就会对相应的项目中所有的请求进行干预处理.
基于过滤器机制,可以将一些共性问题由过滤器处理.JavaWeb中提供接口:Filter,通过实现Filter接口,重写相关方法,再进行注册,就可以使用.
2.1.2 过滤器的实现
-
实现Filter接口
-
重写相关方法:doFilter方法
-
注册过滤器
(1) xml注册
<!-- 声明过滤器 -->
<filter><filter-name>encodingFilter</filter-name><filter-class>com.powernode.filter.EncodingFilter</filter-class>
</filter>
<!-- 配置过滤器的规则 -->
<filter-mapping><filter-name>encodingFilter</filter-name><!-- 所有 .do 后缀结尾的请求 进行编码处理 --><url-pattern>*.do</url-pattern>
</filter-mapping>
(2) 注解注册
@WebFilter("*.do")
//@WebFilter(value="*.do")
//@WebFilter(urlPatterns="*.do")
public class EncodingFilter implements Filter {}
2.1.3 编码字符集处理
package com.powernode.filter;import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;/*** 编码过滤* 在进入servlet之前就进行编码设置*/
@WebFilter(urlPatterns = "*.do")
public class EncodingFilter implements Filter {/*** Filter 初始化方法 只会执行一次 项目启动就执行* @param filterConfig* @throws ServletException*/@Overridepublic void init(FilterConfig filterConfig) throws ServletException {System.out.println("filter 中 init 方法");}/*** 进行具体的过滤方法* @param servletRequest 当前请求对象* @param servletResponse 当前响应对象* @param filterChain 过滤器链 项目中可以存在多个过滤器* 过滤器的注册方式有2种 :* xml配置* 注解* 过滤存在先后执行问题: 过滤使用责任链模式* 最先执行的最后执行完.如果XML配置方式,配置在最上方的最先执行* 如果是注解的方式,按照文件名顺序(类加载器是按照文件名称顺序加载的)* filterChain.doFilter(servletRequest,servletResponse); // 将请求对象和响应对象向下传递 调用下一个方法* @throws IOException* @throws ServletException*/@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println(" 进行具体的过滤操作 doFilter..... ");// xxxxxSystem.out.println("在调用下一个方法之前干点啥......");// 调用下一个方法// 在进入servlet 之前 就已经设置好了编码格式servletRequest.setCharacterEncoding("UTF-8");servletResponse.setCharacterEncoding("UTF-8");filterChain.doFilter(servletRequest,servletResponse);// xxxxxSystem.out.println("在调用完成也干点啥......");}@Overridepublic void destroy() {System.out.println("过滤器 销毁前调用的方法");}
}
2.1.4 跨域处理
package com.powernode.filter;import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** 跨域过滤器*/
@WebFilter("*.do")
public class CrossFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {HttpServletRequest req = (HttpServletRequest) request;HttpServletResponse resp = (HttpServletResponse) response;// 所有的请求源 允许跨域resp.addHeader("Access-Control-Allow-Origin","*");// 放行chain.doFilter(req,response);}
}
2.2 数据库脚本
DROP TABLE IF EXISTS `dept`;CREATE TABLE `dept` (`dept_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '部门编号',`dept_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '部门名称',`dept_remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '部门备注',PRIMARY KEY (`dept_id`) USING BTREE) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;-- ------------------------------ Records of dept-- ----------------------------INSERT INTO `dept` VALUES (1, '开发一部', '开发一部');INSERT INTO `dept` VALUES (2, '开发二部', '开发二部');INSERT INTO `dept` VALUES (3, '开发三部', '开发三部');-- ------------------------------ Table structure for emp-- ----------------------------DROP TABLE IF EXISTS `emp`;CREATE TABLE `emp` (`emp_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '员工编号',`emp_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '员工姓名',`emp_sex` int(11) NULL DEFAULT NULL COMMENT '员工性别',`emp_address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '员工地址',`emp_age` int(11) NULL DEFAULT NULL COMMENT '员工年龄',`emp_salary` decimal(10, 2) NULL DEFAULT NULL COMMENT '员工工资',`emp_birth` datetime(0) NULL DEFAULT NULL COMMENT '员工生日',`dept_id` int(11) NULL DEFAULT NULL COMMENT '所属部门ID',PRIMARY KEY (`emp_id`) USING BTREE) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;-- ------------------------------ Table structure for user-- ----------------------------DROP TABLE IF EXISTS `user`;CREATE TABLE `user` (`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户ID',`username` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用户名',`password` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '密码',`realname` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '姓名',`img` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '头像',PRIMARY KEY (`id`) USING BTREE) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
2.3 postman安装
接口测试工具,模拟HTTP请求.使用postman模拟常规用户请求操作,可以看到服务器返回的数据,进行接口测试.
2.4 核心代码
2.4.1 统一业务结果包装类-Result
package com.powernode.common;/*** 统一业务结果 包装类*/
public class Result {/*** 统一的业务码 0 标识正常*/private Integer code = 0;/*** 统一业务消息 默认是 操作成功*/private String msg = "操作成功!";/*** 业务结果数据 所有操作的数据 放入data 属性中*/private Object data;/*** 成功 但是没有返回业务数据*/public Result(){}/*** 成功 但是 存在 返回业务数据* @param data*/public Result(Object data){this();this.data = data;}/*** 异常结果* @param code 异常码* @param msg 异常消息*/public Result(int code,String msg){this.code = code;this.msg = msg;}public Integer getCode() {return code;}public void setCode(Integer code) {this.code = code;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}public Object getData() {return data;}public void setData(Object data) {this.data = data;}
}
2.4.2 数据库连接配置文件
# 数据库连接配置文件
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/emp?useUnicode=true&useSSL=false&characterEncoding=UTF-8
jdbc.username=root
jdbc.password=123456
2.4.3 数据库连接工具类
package com.powernode.util;import java.io.InputStream;
import java.sql.*;
import java.util.Properties;/*** 自定义JDBC工具类:1)提供获取链接Connection的方法 2)关闭资源的方法 3)实现jdbc配置软编码*/
public final class DBUtils {/*** 驱动名称*/private static String driverClassName;/*** 链接信息*/private static String url;/*** 用户名*/private static String username;/*** 用户密码*/private static String password;static {try {//关联.properties配置文件Properties prop = new Properties();InputStream ins = DBUtils.class.getClassLoader().getResourceAsStream("db.properties");prop.load(ins);//读取.properties配置文件的属性值driverClassName = prop.getProperty("jdbc.driverClassName");url = prop.getProperty("jdbc.url");username = prop.getProperty("jdbc.username");password = prop.getProperty("jdbc.password");Class.forName(driverClassName);} catch (Exception e) {e.printStackTrace();}}/*** 获取连接** @return*/public static Connection getConn() {Connection conn = null;try {conn = DriverManager.getConnection(url, username, password);} catch (Exception e) {e.printStackTrace();}return conn;}/*** 关闭资源** @param acs*/public static void close(AutoCloseable acs) {try {if (acs != null) {acs.close();}} catch (Exception e) {e.printStackTrace();}}/*** 关闭资源** @param rs* @param st* @param conn*/public static void close(ResultSet rs, Statement st, Connection conn) {try {if (rs != null)rs.close();if (st != null)st.close();if (conn != null)conn.close();} catch (SQLException throwables) {throwables.printStackTrace();}}
}
2.4.4 通用数据库操作类
package com.powernode.dao;import com.powernode.util.DBUtils;
import com.powernode.util.PageInfo;import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;/*** JDBC工具类:旨在为客户提供更加便捷的操作数据库的方式*/
public class BaseDao {/*** 修改:可以执行添加、删除、修改单条操作* @param sql* @param params* @return*/public int executeUpdate(String sql,Object...params){Connection conn = null;PreparedStatement st = null;int i=0;try {//参数校验if(sql==null || "".equals(sql.trim())){return 0;}//获取连接conn = DBUtils.getConn();//创建Statement对象st = conn.prepareStatement(sql);//给sql赋值参数for (int n=0;params!=null && params.length>=1 &&n<params.length;n++){st.setObject(n+1,params[n]);}//向mysql发送sql语句,接受结果i = st.executeUpdate();} catch (Exception throwables) {throwables.printStackTrace();}finally {//释放资源DBUtils.close(null,st,conn);}return i;}/*** 批量删除* @param sql* @param params* @return*/public int executeBatchDel(String sql,Object...params){Connection conn = null;PreparedStatement st = null;int[] arr = null;try {//基本参数校验if(sql==null || "".equals(sql.trim())){return 0;}//获取连接conn = DBUtils.getConn();//在同一个事务中执行conn.setAutoCommit(false);st = conn.prepareStatement(sql);//给参数赋值for (int i = 0;params!=null && params.length>=1 && i < params.length; i++) {st.setObject(1,params[i]);st.addBatch();}//执行sqlarr = st.executeBatch();//[0,0,0,0]} catch (Exception throwables) {throwables.printStackTrace();} finally {try {conn.setAutoCommit(true);} catch (SQLException throwables) {throwables.printStackTrace();}//释放资源DBUtils.close(null,st,conn);}return arr.length;}/*** 查询多条记录* @param sql* @param c* @param params* @param <T>* @return*/public <T> List<T> executeQueryList(String sql, Class<T> c ,Object...params){Connection conn= null;PreparedStatement st = null;ResultSet rs = null;List<T> dataList = new ArrayList<>();//{}try {//参数校验if(sql==null || "".equals(sql.trim())){return dataList;}//获取Connection连接conn = DBUtils.getConn();//创建PrepareStatement对象st = conn.prepareStatement(sql);for (int i = 0;params!=null && params.length>=1 && i < params.length; i++) {st.setObject(i+1,params[i]);}//发送sql,接受结果rs = st.executeQuery();//获取查询数据的字段个数ResultSetMetaData metaData = rs.getMetaData();int columnCount = metaData.getColumnCount();for(;rs.next();){//取记录的次数//创建一个c字节码的对象,用来装一条记录T t = c.newInstance();for (int i = 1; i <=columnCount ; i++) {//获取某个字段别名 字段别名默认是和字段名一致String columnName = metaData.getColumnLabel(i);//获取字段对应的值Object value = rs.getObject(columnName);//内部for全部执行完了,则代表一条记录取出来了Field field = c.getDeclaredField(columnName);field.setAccessible(true);field.set(t,value);field.setAccessible(false);}//将对象装入到List中dataList.add(t);}} catch (Exception throwables) {throwables.printStackTrace();}finally {DBUtils.close(rs,st,conn);}return dataList;}/*** 查询单条记录* @param sql* @param c* @param param* @param <T>* @return*/public <T> T executeQueryOne(String sql,Class<T> c,Object...param){return executeQueryList(sql,c,param).size()==0?null:executeQueryList(sql,c,param).get(0);}/*** 分页查询* @param sql 基本分页sql,不用写limit* @param pageNum 页码* @param pageSize 每页显示的数据条数* @param c 某一条数据的类型* @param params 分页太哦建* @param <T>* @return*/public <T> PageInfo<T> executeQueryPage(String sql,int pageNum,int pageSize,Class<T> c,Object...params){Connection conn=null;PreparedStatement st = null;ResultSet rs = null;PageInfo<T> pageInfo = new PageInfo<>();try {//校验参数if(sql==null || "".equals(sql.trim())){return pageInfo;}if(pageNum<=0 || pageSize<=0){return pageInfo;}if(c==null){return pageInfo;}//去除;sql = sql.replaceAll(";","");//获取数据库连接:Connection对象conn = DBUtils.getConn();//准备sql语句//创建PrepareStatement对象 (此处有个;的小bug)String newSql = sql + " limit "+(pageNum-1)*pageSize+","+pageSize+"";st = conn.prepareStatement(newSql);//给sql占位符?赋值for (int i = 0;params!=null && params.length>=1 && i < params.length; i++) {st.setObject(i+1,params[i]);}//执行sql,处理结果rs = st.executeQuery();//数据表头信息ResultSetMetaData metaData = rs.getMetaData();//获取查询sql语句中字段的个数int columnCount = metaData.getColumnCount();for (;rs.next();){//创建一个对象,用于接收一条记录T t = c.newInstance();for (int i = 1; i <=columnCount ; i++) {//获取字段名String columnName = metaData.getColumnLabel(i);//获取字段值Object columnValue = rs.getObject(columnName);//将对应字段的值装入到实体类对象中去Field field = c.getDeclaredField(columnName);field.setAccessible(true);field.set(t,columnValue);field.setAccessible(false);}//将某一条记录放入到List集合中去//往pageInfo对象中添加分页数据pageInfo.getData().add(t);}//往pageInfo对象中添加总记录数long total = executeQueryCount(sql);pageInfo.setTotal(total);//往pageInfo对象中添加总页数long temp = total % pageSize;//3%2=1int pages = temp==0? (int)(total/pageSize): (int)Math.ceil((double)total/(double)pageSize);pageInfo.setPages(pages);} catch (Exception throwables) {throwables.printStackTrace();} finally {//释放资源DBUtils.close(rs,st,conn);}return pageInfo;}/*** 统计满足sql条件的总记录数* @param sql* @return*/private long executeQueryCount(String sql){long total = 0;Connection conn=null;PreparedStatement st = null;ResultSet rs = null;try {conn = DBUtils.getConn();String newSql = "select count(*) from ("+sql+") t";st = conn.prepareStatement(newSql);rs = st.executeQuery();for (;rs.next();){total = rs.getLong("count(*)");}return total;} catch (Exception throwables) {throwables.printStackTrace();} finally {DBUtils.close(rs,st,conn);}return total;}
}
2.4.5 通用分页结果包装类
package com.powernode.util;import java.util.ArrayList;
import java.util.List;/*** 此实体类对象中封装的是分页相关数据信息: 分页数据、总记录数、页码等*/
public class PageInfo<T> {/*** 分页数据*/private List<T> data = new ArrayList<>();/*** 满足sql条件的总记录数*/private long total;/*** 总页数*/private int pages;public PageInfo() {}public PageInfo(List<T> data, long total, int pages) {this.data = data;this.total = total;this.pages = pages;}public List<T> getData() {return data;}public void setData(List<T> data) {this.data = data;}public long getTotal() {return total;}public void setTotal(long total) {this.total = total;}public int getPages() {return pages;}public void setPages(int pages) {this.pages = pages;}@Overridepublic String toString() {return "PageInfo{" +"data=" + data +", total=" + total +", pages=" + pages +'}';}
}
3.登录功能
3.1 servlet三大作用域
servlet三大作用域就是三个用于存储数据的容器,根据其范围划分分为以下三类(小到大):
-
当前请求作用域
-
当前会话作用域
-
当前应用作用域
3.1.1 当前请求作用域
是指存储的数据只能在同一个请求中访问,因为tomcat将每一个请求封装成了HttpServletRequest对象,该对象中存在Map集合
private final Map<String, Object> attributes = new ConcurrentHashMap<>();
只要request对象相同,存储数据Map就相同.当在程序中,使用内部转发时,将一个请求对象传给多个servlet的service中,此时多个servlet使用的同一个请求级别的作用域.因为虽然经历多个servlet程序,但是请求只有一次,并且请求对象和响应对象在传递.
3.1.2 当前应用作用域
当前应用作用域对象,也被称之为servlet容器对象,当项目启动时,tomcat服务器会为每一个应用程序创建且只创建一个(有且只有一个)servlet容器对象,该对象可以在当前应用程序中任何地方进行访问(也就是在servlet中访问),该容器对象也存在Map容器.
获取Servlet容器对象:this.getServletContext()
/*** The context attributes for this context.*/protected Map<String,Object> attributes = new ConcurrentHashMap<>();
3.1.3 当前会话作用域
当前会话是指从客户端请求服务器开始,建立一个会话,会话中包含多次请求和响应.使用session对象表示.服务器如何知道多个请求是同一次会话?原理很简单,当第一次请求时,服务器默默的在响应头中添加了一个唯一标识,以后的请求如果带上了这个唯一标识.则服务器就将这批唯一标识一致的请求当做同一次会话中的请求.默认会话默认是30分钟或者一次浏览器的开启和关闭.
因为这个唯一标识,本质上服务器通过浏览器的Cookie机制.将唯一标识通过响应头,告诉浏览器将这个数据存在cookie中,然后浏览器每次请求时默认将有效的cookie带给服务器.所以服务器就会检查从请求头中带过来的数据JSESSIONID的,如果一致说明是同一个会话.
/*** The collection of user data attributes associated with this Session.*/protected ConcurrentMap<String,Object> attributes = new ConcurrentHashMap<>();
3.2 三大作用域的API
3.2.1 获取作用域对象
// 当前请求作用域对象
// 由于当前请求作用域对象本身就是request对象本身,所以无需获取
//当前会话作用域对象
HttpSession session = req.getSession();
//当前应用作用域对象
ServletContext applicationContext = req.getServletContext();
3.2.2 作用域存储数据
// 存放数据
// 向当前请求作用域中存放了数据
req.setAttribute("reqKey","reqValue");
session.setAttribute("sessionKey","sessionValue");
applicationContext.setAttribute("appKey","appValue");
3.2.3 获取数据
// 从作用域中获取数据
Object reqKey = req.getAttribute("reqKey");
// 新的请求 所以获取的值 是 null
System.out.println("request作用域数据:"+reqKey);Object sessionKey = req.getSession().getAttribute("sessionKey");
System.out.println("session作用域数据:"+sessionKey);Object appKey = req.getServletContext().getAttribute("appKey");System.out.println("application作用域数据:"+appKey);
3.2.4 删除数据
// 删除作用域中的数据
applicationContext.removeAttribute("appKey");
// 由于作用域底层是 Map结构
// 同样的key 就会覆盖
3.3 会话技术-Session
session技术被称之为会话技术,当今已经不适用了.session技术本质上,在服务器中开辟一块内存,将找到这块数据存储的标识返回给了浏览器,每次浏览器的请求,服务器进行解析时,会进行一个检查,检测session有效性.由于当今,应用需要提高稳定性和可用性.一般服务器多台.session本质上JVM内存中一块数据,多台服务器运行了多个JVM程序,每个JVM内存都有自己独立管理空间,相互无法共享.如果用户访问时,访问的是A服务器,第二次访问时访问的B服务器,就会出现永远不会有第二次访问.市面上,一般使用一些中间件存储会话唯一标识.
3.3.1 session相关API
// 获取当前关联的session 对象
HttpSession session = req.getSession();
// session的唯一标识
String id = session.getId();
// session 有效时间
int maxInactiveInterval = session.getMaxInactiveInterval();
// 设置session 最大有效时间 如果设置为 0 或者负数 则表示一直有效
// session.setMaxInactiveInterval();
// 作用域api
3.4 会话技术Cookie
cookie这个技术,也被称之为客户端缓存技术.cookie技术本质上浏览器的一个机制.是和HTTP协议的一个约定.每次浏览器在请求时,如果发现响应头中存在Set-Cookie的头,则会将相关数据存储在浏览器的缓存中(默认存储在浏览器内存中),如果Set-Cookie这个响应头的数据设置了有效时间,浏览器还会将数据存储在本地磁盘.
每次浏览器在请求时,会去检查存放cookie数据空间,看是否有需要带给服务器的cookie数据.如果有,则使用请求头:cookie带给服务器.
浏览器会从时间,域名,资源路径等多个方面进行检查.
当前cookie也不太适用,因为cookie的本质是数据存在客户端,首先可能存在安全问题,其次,当今是多终端时代(手机/平板/电脑/手表),如果数据存在客户端,很难实现数据共享.
3.4.1 Cookie的Api
Cookie中数据key=value形式,可以通过构造器创建Cookie对象,通过响应头将cookie添加到响应中.@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 获取请求中cookie// 获取所有的cookieCookie[] cookies = req.getCookies();// 通过for循环 遍历cookie// 只能通过对比 具体的 cookie的name值 找到自己想要cookieif (ObjectUtil.isNotEmpty(cookies)){for (Cookie cookie : cookies) {// cookie的名称String name = cookie.getName();// cookie的值String value = cookie.getValue();// cookie 有效的域名 域名分为多级域名 : www.baidu.com www.baike.baidu.com www.map.baidu.com// 一级域名: baidu.com// 二级域名 : baike.baidu.com map.baidu.comString domain = cookie.getDomain();// cookie 有效的资源路径 默认是当前项目根目录String path = cookie.getPath();// cookie是否只能被HTTP协议 访问boolean httpOnly = cookie.isHttpOnly();// 获取 cookie 最大有效期 ( 默认是 内存中 浏览器关闭就没了)int maxAge = cookie.getMaxAge();System.out.println("name : " + name);System.out.println("value : " + value);}}// 创建 cookieCookie cookie = new Cookie("myCookie","myCookieValue");// 设置 cookie 最大有效期 单位是秒 如果是 0 则表示删除cookie.setMaxAge(60*60);// 将cookie 返回给浏览器resp.addCookie(cookie);// 如果多个cookie 则需要 new 多个cookie 对象// 并且 多次调用addCookieresp.sendRedirect("index.html");
}
3.5 session和cookie比较
首先session和cookie都能够存储数据,但是session存储在服务器内存中,cookie是存储在浏览器中,相对而言session存储数据的安全性高于cookie.
但是session是依赖cookie实现的.因为查找session的唯一标识存储在cookie中的,session基于cookie.
3.6 应用
3.6.1 验证码功能
ackage com.powernode.servlet;import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.GifCaptcha;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 javax.servlet.http.HttpSession;
import java.io.IOException;/*** 验证码 servlet*/
@WebServlet("/code.do")
public class CheckCodeServlet extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//生成验证图像GifCaptcha gifCaptcha = CaptchaUtil.createGifCaptcha(116, 44, 4);// 获取验证码字符串String code = gifCaptcha.getCode();// 获取会话作用域HttpSession session = req.getSession();// 将验证码 放入session中session.setAttribute("code",code);// 将验证码返回给浏览器gifCaptcha.write(resp.getOutputStream());}
}
3.6.2 用户登录功能
package com.powernode.servlet;import cn.hutool.core.util.StrUtil;
import com.powernode.common.Result;
import com.powernode.listener.AppListener;
import com.powernode.service.UserService;
import com.powernode.service.impl.UserServiceImpl;
import com.powernode.util.RespUtil;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 javax.servlet.http.HttpSession;
import java.io.IOException;@WebServlet("/user.do")
public class UserServlet extends HttpServlet {UserService userService = AppListener.getInstance(UserService.class);@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String service = req.getParameter("service");if(StrUtil.equals(service,"login")){login(req,resp);}}/*** 处理具体的登录请求* @param req* @param resp* @throws ServletException* @throws IOException*/private void login(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{String username = req.getParameter("username");String password = req.getParameter("password");String code = req.getParameter("code");// 校验验证码HttpSession session = req.getSession();Object sessionCode = session.getAttribute("code");// 判断验证码是否一致if (sessionCode == null || !StrUtil.equals(code,sessionCode.toString())){RespUtil.writer(new Result(400,"验证码错误"),resp);return;}// 根据用户名和密码查询用户Result result = userService.login(username, password);if (result.getCode().equals(0)){// 将当前登录用户 存储在服务端内存session.setAttribute("user",result.getData());}RespUtil.writer(result,resp);}
}
4.员工信息管理
4.1 后端数据接口
所有的后端数据接口开发完成后,每开发一个必须使用postman进行一次测试.这样的做的目的,确保后端程序没有问题.
4.1.1 部门列表接口
4.1.1.1 servlet
package com.powernode.servlet;import cn.hutool.core.util.StrUtil;
import com.powernode.common.Result;
import com.powernode.service.DeptService;
import com.powernode.service.impl.DeptServiceImpl;
import com.powernode.util.RespUtil;import javax.servlet.ServletContext;
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 javax.servlet.http.HttpSession;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;@WebServlet("/dept.do")
public class DeptServlet extends HttpServlet {DeptService deptService = new DeptServiceImpl();@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {/** 根据 service 值 调用相关方法* service = login --> login* service = update --> update* 利用反射机制* 将service的值当做 方法名 根据 service 查找方法* 进行方法调用* 无序 各种 service 判断* */String service = req.getParameter("service");/* try {Method method = this.getClass().getDeclaredMethod(service, HttpServletRequest.class, HttpServletResponse.class);method.invoke(this,req,resp);} catch (Exception e) {throw new RuntimeException(e);}
*/if(StrUtil.equals(service,"all")){all(req,resp);}}/*** 返回所有的部门信息* @param req* @param resp* @throws IOException*/private void all(HttpServletRequest req, HttpServletResponse resp) throws IOException {Result result = deptService.queryAll();RespUtil.writer(result,resp);}
}
4.1.1.2 Service
package com.powernode.service;import com.powernode.common.Result;/*** 部门相关业务类* 业务层 基于具体业务需要 进行调用数据访问层的程序* 用户注册:* 1. 数据格式校验* 长度校验 非空校验 在 controller 层校验 servlet c层* 2. 数据业务校验* 用户名是否存在 ? 身份证是否有效* 查询数据* 3. 插入数据库*/
public interface DeptService {/*** 查询所有的部门信息* @return*/Result queryAll();
}package com.powernode.service.impl;import com.powernode.common.Result;
import com.powernode.dao.DeptDao;
import com.powernode.domain.Dept;
import com.powernode.service.DeptService;import java.util.List;public class DeptServiceImpl implements DeptService {DeptDao deptDao = new DeptDao();@Overridepublic Result queryAll() {// 查询部门信息List<Dept> depts = deptDao.selectAll();// 将部门信息数据包装return new Result(depts);}
}
4.1.1.3 Dao
package com.powernode.dao;import com.powernode.domain.Dept;import java.util.List;/*** 数据访问层 只做最基本的数据 增删查改*/
public class DeptDao extends BaseDao{/*** 查询所有的部门信息* @return*/public List<Dept> selectAll(){String sql = "select dept_id as deptId,dept_name as deptName,dept_remark as deptRemark from dept";List<Dept> depts = super.executeQueryList(sql, Dept.class);return depts;}
}
4.1.2 员工分页接口
4.1.2.1 查询实体类
package com.powernode.query;/*** 查询参数*/
public class EmpPageQuery {/*** 页码 默认 1*/private Integer page = 1;/*** 每页条数 默认10*/private Integer limit = 10;/*** 部门ID*/private Integer deptId;/*** 员工名称*/private String empName;/*** 员工地址*/private String empAddress;/*** 员工性别*/private Integer empSex;public Integer getPage() {return page;}public void setPage(Integer page) {this.page = page;}public Integer getLimit() {return limit;}public void setLimit(Integer limit) {this.limit = limit;}public Integer getDeptId() {return deptId;}public void setDeptId(Integer deptId) {this.deptId = deptId;}public String getEmpName() {return empName;}public void setEmpName(String empName) {this.empName = empName;}public String getEmpAddress() {return empAddress;}public void setEmpAddress(String empAddress) {this.empAddress = empAddress;}public Integer getEmpSex() {return empSex;}public void setEmpSex(Integer empSex) {this.empSex = empSex;}
}
4.1.2.2 servlet
package com.powernode.servlet;import cn.hutool.core.util.StrUtil;
import com.powernode.common.Result;
import com.powernode.query.EmpPageQuery;
import com.powernode.service.EmpService;
import com.powernode.service.impl.EmpServiceImpl;
import com.powernode.util.RespUtil;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;/*** 员工控制类*/
@WebServlet("/emp.do")
public class EmpServlet extends HttpServlet {EmpService empService = new EmpServiceImpl();@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String service = req.getParameter("service");if (StrUtil.equals(service,"page")){page(req,resp);}else if(StrUtil.equals(service,"add")){//TODO}else if(StrUtil.equals(service,"update")){//TODO}else if(StrUtil.equals(service,"delete")){//TODO}}/*** 获取员工的分页信息* @param req* @param resp*/private void page(HttpServletRequest req, HttpServletResponse resp) throws IOException {// 获取请求参数// 页码String page = req.getParameter("page");// 每页条数String limit = req.getParameter("limit");//部门IDString deptId = req.getParameter("deptId");//姓名String empName = req.getParameter("empName");//地址String empAddress = req.getParameter("empAddress");//性别String empSex = req.getParameter("empSex");EmpPageQuery query = new EmpPageQuery();if (StrUtil.isNotBlank(page)){query.setPage(Integer.parseInt(page));}if (StrUtil.isNotBlank(limit)){query.setLimit(Integer.parseInt(limit));}if (StrUtil.isNotBlank(deptId)){query.setDeptId(Integer.parseInt(deptId));}if (StrUtil.isNotBlank(empName)){query.setEmpName(empName);}if (StrUtil.isNotBlank(empAddress)){query.setEmpAddress(empAddress);}if (StrUtil.isNotBlank(empSex)){query.setEmpSex(Integer.parseInt(empSex));}Result result = empService.queryPage(query);// 将数据使用JSON返回RespUtil.writer(result,resp);}
}
4.1.2.3 service
package com.powernode.service;import com.powernode.common.Result;
import com.powernode.query.EmpPageQuery;/*** 员工的业务类*/
public interface EmpService {/*** 分页查询员工信息* @param query* @return*/Result queryPage(EmpPageQuery query);
}package com.powernode.service.impl;import com.powernode.common.Result;
import com.powernode.dao.EmpDao;
import com.powernode.domain.Emp;
import com.powernode.query.EmpPageQuery;
import com.powernode.service.EmpService;
import com.powernode.util.PageInfo;public class EmpServiceImpl implements EmpService {EmpDao empDao = new EmpDao();@Overridepublic Result queryPage(EmpPageQuery query) {PageInfo<Emp> empPageInfo = empDao.selectPage(query);return new Result(empPageInfo);}
}
4.1.2.4 dao
package com.powernode.dao;import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.powernode.domain.Emp;
import com.powernode.query.EmpPageQuery;
import com.powernode.util.PageInfo;public class EmpDao extends BaseDao{/*** 分页查询员工信息* @param query* @return*/public PageInfo<Emp> selectPage(EmpPageQuery query){String sql = "select emp_id as empId,emp_name as empName,emp_sex as empSex,emp_address as empAddress,emp_age as empAge,emp_salary as empSalary,`emp_birth` as empBirth, `dept_id` as deptId from emp where 1=1 ";if(ObjectUtil.isNotNull(query.getDeptId())){sql = sql + " and dept_id = "+query.getDeptId();}if(StrUtil.isNotBlank(query.getEmpName())){sql = sql + " and emp_name like '%"+ query.getEmpName() +"%'";}if(StrUtil.isNotBlank(query.getEmpAddress())){sql = sql + " and emp_addresss like '%"+ query.getEmpAddress() +"%'";}if(ObjectUtil.isNotNull(query.getEmpSex())){sql = sql + " and emp_sex = "+query.getEmpSex();}PageInfo<Emp> empPageInfo = super.executeQueryPage(sql, query.getPage(), query.getLimit(), Emp.class);return empPageInfo;}
}
4.1.3 新增员工接口
4.1.3.0.1 servlet
package com.powernode.servlet;import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.powernode.common.Result;
import com.powernode.domain.Emp;
import com.powernode.query.EmpPageQuery;
import com.powernode.service.EmpService;
import com.powernode.service.impl.EmpServiceImpl;
import com.powernode.util.RespUtil;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;/*** 员工控制类*/
@WebServlet("/emp.do")
public class EmpServlet extends HttpServlet {EmpService empService = new EmpServiceImpl();@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String service = req.getParameter("service");if (StrUtil.equals(service,"page")){page(req,resp);}else if(StrUtil.equals(service,"add")){add(req,resp);}}/*** 添加员工信息* @param req* @param resp*/private void add(HttpServletRequest req, HttpServletResponse resp) throws IOException {//姓名String empName = req.getParameter("empName");//性别String empSex = req.getParameter("empSex");//地址String empAddress = req.getParameter("empAddress");//年龄String empAge = req.getParameter("empAge");//工资String empSalary = req.getParameter("empSalary");//生日String empBirth = req.getParameter("empBirth");//部门IDString deptId = req.getParameter("deptId");// empBirth : 2022-04-22DateTime birth = DateUtil.parse(empBirth, DatePattern.NORM_DATE_PATTERN);Emp emp = new Emp(empName,Integer.parseInt(empSex),empAddress,Integer.parseInt(empAge),Integer.parseInt(empSalary),birth,Integer.parseInt(deptId));Result rs = empService.add(emp);RespUtil.writer(rs,resp);}
4.1.3.0.2 service
package com.powernode.service;import com.powernode.common.Result;
import com.powernode.domain.Emp;
import com.powernode.query.EmpPageQuery;/*** 员工的业务类*/
public interface EmpService {/*** 分页查询员工信息* @param query* @return*/Result queryPage(EmpPageQuery query);Result add(Emp emp);
}package com.powernode.service.impl;import com.powernode.common.Result;
import com.powernode.dao.EmpDao;
import com.powernode.domain.Emp;
import com.powernode.query.EmpPageQuery;
import com.powernode.service.EmpService;
import com.powernode.util.PageInfo;public class EmpServiceImpl implements EmpService {EmpDao empDao = new EmpDao();@Overridepublic Result queryPage(EmpPageQuery query) {PageInfo<Emp> empPageInfo = empDao.selectPage(query);return new Result(empPageInfo);}@Overridepublic Result add(Emp emp) {int m = empDao.insert(emp);if (m == 1){return new Result();}return new Result(400,"数据添加失败");}}
4.1.3.0.3 dao
package com.powernode.dao;import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.powernode.domain.Emp;
import com.powernode.query.EmpPageQuery;
import com.powernode.util.PageInfo;public class EmpDao extends BaseDao{/*** 分页查询员工信息* @param query* @return*/public PageInfo<Emp> selectPage(EmpPageQuery query){String sql = "select emp_id as empId,emp_name as empName,emp_sex as empSex,emp_address as empAddress,emp_age as empAge,emp_salary as empSalary,`emp_birth` as empBirth, `dept_id` as deptId from emp where 1=1 ";if(ObjectUtil.isNotNull(query.getDeptId())){sql = sql + " and dept_id = "+query.getDeptId();}if(StrUtil.isNotBlank(query.getEmpName())){sql = sql + " and emp_name like '%"+ query.getEmpName() +"%'";}if(StrUtil.isNotBlank(query.getEmpAddress())){sql = sql + " and emp_addresss like '%"+ query.getEmpAddress() +"%'";}if(ObjectUtil.isNotNull(query.getEmpSex())){sql = sql + " and emp_sex = "+query.getEmpSex();}PageInfo<Emp> empPageInfo = super.executeQueryPage(sql, query.getPage(), query.getLimit(), Emp.class);return empPageInfo;}public int insert(Emp emp) {String sql = "INSERT INTO emp(`emp_name`, `emp_sex`, `emp_address`, `emp_age`, `emp_salary`, `emp_birth`, `dept_id`) VALUES (?, ?, ?, ?, ?,?, ?)";return super.executeUpdate(sql,emp.getEmpName(),emp.getEmpSex(),emp.getEmpAddress(),emp.getEmpAge(),emp.getEmpSalary(),emp.getEmpBirth(),emp.getDeptId());}}
4.1.3.1 修改员工接口
4.1.3.1.1 servlet
package com.powernode.servlet;import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.powernode.common.Result;
import com.powernode.domain.Emp;
import com.powernode.query.EmpPageQuery;
import com.powernode.service.EmpService;
import com.powernode.service.impl.EmpServiceImpl;
import com.powernode.util.RespUtil;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;/*** 员工控制类*/
@WebServlet("/emp.do")
public class EmpServlet extends HttpServlet {EmpService empService = new EmpServiceImpl();@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String service = req.getParameter("service");if (StrUtil.equals(service,"page")){page(req,resp);}else if(StrUtil.equals(service,"add")){add(req,resp);}else if(StrUtil.equals(service,"update")){update(req,resp);}}/*** 修改员工信息* @param req* @param resp* @throws IOException*/private void update(HttpServletRequest req, HttpServletResponse resp) throws IOException {//员工IDString empId = req.getParameter("empId");//姓名String empName = req.getParameter("empName");//性别String empSex = req.getParameter("empSex");//地址String empAddress = req.getParameter("empAddress");//年龄String empAge = req.getParameter("empAge");//工资String empSalary = req.getParameter("empSalary");//生日String empBirth = req.getParameter("empBirth");//部门IDString deptId = req.getParameter("deptId");// empBirth : 2022-04-22DateTime birth = DateUtil.parse(empBirth, DatePattern.NORM_DATE_PATTERN);Emp emp = new Emp(Integer.parseInt(empId),empName,Integer.parseInt(empSex),empAddress,Integer.parseInt(empAge),Integer.parseInt(empSalary),birth,Integer.parseInt(deptId));Result rs = empService.update(emp);RespUtil.writer(rs,resp);}/*** 添加员工信息* @param req* @param resp*/private void add(HttpServletRequest req, HttpServletResponse resp) throws IOException {//姓名String empName = req.getParameter("empName");//性别String empSex = req.getParameter("empSex");//地址String empAddress = req.getParameter("empAddress");//年龄String empAge = req.getParameter("empAge");//工资String empSalary = req.getParameter("empSalary");//生日String empBirth = req.getParameter("empBirth");//部门IDString deptId = req.getParameter("deptId");// empBirth : 2022-04-22DateTime birth = DateUtil.parse(empBirth, DatePattern.NORM_DATE_PATTERN);Emp emp = new Emp(empName,Integer.parseInt(empSex),empAddress,Integer.parseInt(empAge),Integer.parseInt(empSalary),birth,Integer.parseInt(deptId));Result rs = empService.add(emp);RespUtil.writer(rs,resp);}/*** 获取员工的分页信息* @param req* @param resp*/private void page(HttpServletRequest req, HttpServletResponse resp) throws IOException {// 获取请求参数// 页码String page = req.getParameter("page");// 每页条数String limit = req.getParameter("limit");//部门IDString deptId = req.getParameter("deptId");//姓名String empName = req.getParameter("empName");//地址String empAddress = req.getParameter("empAddress");//性别String empSex = req.getParameter("empSex");EmpPageQuery query = new EmpPageQuery();if (StrUtil.isNotBlank(page)){query.setPage(Integer.parseInt(page));}if (StrUtil.isNotBlank(limit)){query.setLimit(Integer.parseInt(limit));}if (StrUtil.isNotBlank(deptId)){query.setDeptId(Integer.parseInt(deptId));}if (StrUtil.isNotBlank(empName)){query.setEmpName(empName);}if (StrUtil.isNotBlank(empAddress)){query.setEmpAddress(empAddress);}if (StrUtil.isNotBlank(empSex)){query.setEmpSex(Integer.parseInt(empSex));}Result result = empService.queryPage(query);// 将数据使用JSON返回RespUtil.writer(result,resp);}
}
4.1.3.1.2 service
package com.powernode.service;import com.powernode.common.Result;
import com.powernode.domain.Emp;
import com.powernode.query.EmpPageQuery;/*** 员工的业务类*/
public interface EmpService {/*** 分页查询员工信息* @param query* @return*/Result queryPage(EmpPageQuery query);Result add(Emp emp);Result update(Emp emp);
}package com.powernode.service.impl;import com.powernode.common.Result;
import com.powernode.dao.EmpDao;
import com.powernode.domain.Emp;
import com.powernode.query.EmpPageQuery;
import com.powernode.service.EmpService;
import com.powernode.util.PageInfo;public class EmpServiceImpl implements EmpService {EmpDao empDao = new EmpDao();@Overridepublic Result queryPage(EmpPageQuery query) {PageInfo<Emp> empPageInfo = empDao.selectPage(query);return new Result(empPageInfo);}@Overridepublic Result add(Emp emp) {int m = empDao.insert(emp);if (m == 1){return new Result();}return new Result(400,"数据添加失败");}@Overridepublic Result update(Emp emp) {int m = empDao.updateById(emp);if (m == 1){return new Result();}return new Result(400,"数据修改失败");}
}
4.1.3.1.3 dao
package com.powernode.dao;import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.powernode.domain.Emp;
import com.powernode.query.EmpPageQuery;
import com.powernode.util.PageInfo;public class EmpDao extends BaseDao{/*** 分页查询员工信息* @param query* @return*/public PageInfo<Emp> selectPage(EmpPageQuery query){String sql = "select emp_id as empId,emp_name as empName,emp_sex as empSex,emp_address as empAddress,emp_age as empAge,emp_salary as empSalary,`emp_birth` as empBirth, `dept_id` as deptId from emp where 1=1 ";if(ObjectUtil.isNotNull(query.getDeptId())){sql = sql + " and dept_id = "+query.getDeptId();}if(StrUtil.isNotBlank(query.getEmpName())){sql = sql + " and emp_name like '%"+ query.getEmpName() +"%'";}if(StrUtil.isNotBlank(query.getEmpAddress())){sql = sql + " and emp_addresss like '%"+ query.getEmpAddress() +"%'";}if(ObjectUtil.isNotNull(query.getEmpSex())){sql = sql + " and emp_sex = "+query.getEmpSex();}PageInfo<Emp> empPageInfo = super.executeQueryPage(sql, query.getPage(), query.getLimit(), Emp.class);return empPageInfo;}public int insert(Emp emp) {String sql = "INSERT INTO emp(`emp_name`, `emp_sex`, `emp_address`, `emp_age`, `emp_salary`, `emp_birth`, `dept_id`) VALUES (?, ?, ?, ?, ?,?, ?)";return super.executeUpdate(sql,emp.getEmpName(),emp.getEmpSex(),emp.getEmpAddress(),emp.getEmpAge(),emp.getEmpSalary(),emp.getEmpBirth(),emp.getDeptId());}public int updateById(Emp emp) {String sql = "UPDATE `emp` SET `emp_name` = ?, `emp_sex` = ?, `emp_address` = ?, `emp_age` = ?, `emp_salary` = ?, `emp_birth` = ? , `dept_id` = ? WHERE `emp_id` = ?";return super.executeUpdate(sql,emp.getEmpName(),emp.getEmpSex(),emp.getEmpAddress(),emp.getEmpAge(),emp.getEmpSalary(),emp.getEmpBirth(),emp.getDeptId(),emp.getEmpId());}
}
4.1.3.2 删除员工信息接口
4.1.3.2.1 servlet
package com.powernode.servlet;import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.powernode.common.Result;
import com.powernode.domain.Emp;
import com.powernode.query.EmpPageQuery;
import com.powernode.service.EmpService;
import com.powernode.service.impl.EmpServiceImpl;
import com.powernode.util.RespUtil;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;/*** 员工控制类*/
@WebServlet("/emp.do")
public class EmpServlet extends HttpServlet {EmpService empService = new EmpServiceImpl();@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String service = req.getParameter("service");if (StrUtil.equals(service,"page")){page(req,resp);}else if(StrUtil.equals(service,"add")){add(req,resp);}else if(StrUtil.equals(service,"update")){update(req,resp);}else if(StrUtil.equals(service,"delete")){delete(req,resp);}}/*** 删除员工信息* @param req* @param resp*/private void delete(HttpServletRequest req, HttpServletResponse resp) throws IOException {String empId = req.getParameter("empId");Result rs = empService.delete(empId);RespUtil.writer(rs,resp);}/*** 修改员工信息* @param req* @param resp* @throws IOException*/private void update(HttpServletRequest req, HttpServletResponse resp) throws IOException {//员工IDString empId = req.getParameter("empId");//姓名String empName = req.getParameter("empName");//性别String empSex = req.getParameter("empSex");//地址String empAddress = req.getParameter("empAddress");//年龄String empAge = req.getParameter("empAge");//工资String empSalary = req.getParameter("empSalary");//生日String empBirth = req.getParameter("empBirth");//部门IDString deptId = req.getParameter("deptId");// empBirth : 2022-04-22DateTime birth = DateUtil.parse(empBirth, DatePattern.NORM_DATE_PATTERN);Emp emp = new Emp(Integer.parseInt(empId),empName,Integer.parseInt(empSex),empAddress,Integer.parseInt(empAge),Integer.parseInt(empSalary),birth,Integer.parseInt(deptId));Result rs = empService.update(emp);RespUtil.writer(rs,resp);}/*** 添加员工信息* @param req* @param resp*/private void add(HttpServletRequest req, HttpServletResponse resp) throws IOException {//姓名String empName = req.getParameter("empName");//性别String empSex = req.getParameter("empSex");//地址String empAddress = req.getParameter("empAddress");//年龄String empAge = req.getParameter("empAge");//工资String empSalary = req.getParameter("empSalary");//生日String empBirth = req.getParameter("empBirth");//部门IDString deptId = req.getParameter("deptId");// empBirth : 2022-04-22DateTime birth = DateUtil.parse(empBirth, DatePattern.NORM_DATE_PATTERN);Emp emp = new Emp(empName,Integer.parseInt(empSex),empAddress,Integer.parseInt(empAge),Integer.parseInt(empSalary),birth,Integer.parseInt(deptId));Result rs = empService.add(emp);RespUtil.writer(rs,resp);}/*** 获取员工的分页信息* @param req* @param resp*/private void page(HttpServletRequest req, HttpServletResponse resp) throws IOException {// 获取请求参数// 页码String page = req.getParameter("page");// 每页条数String limit = req.getParameter("limit");//部门IDString deptId = req.getParameter("deptId");//姓名String empName = req.getParameter("empName");//地址String empAddress = req.getParameter("empAddress");//性别String empSex = req.getParameter("empSex");EmpPageQuery query = new EmpPageQuery();if (StrUtil.isNotBlank(page)){query.setPage(Integer.parseInt(page));}if (StrUtil.isNotBlank(limit)){query.setLimit(Integer.parseInt(limit));}if (StrUtil.isNotBlank(deptId)){query.setDeptId(Integer.parseInt(deptId));}if (StrUtil.isNotBlank(empName)){query.setEmpName(empName);}if (StrUtil.isNotBlank(empAddress)){query.setEmpAddress(empAddress);}if (StrUtil.isNotBlank(empSex)){query.setEmpSex(Integer.parseInt(empSex));}Result result = empService.queryPage(query);// 将数据使用JSON返回RespUtil.writer(result,resp);}
}
4.1.3.2.2 service
package com.powernode.service;import com.powernode.common.Result;
import com.powernode.domain.Emp;
import com.powernode.query.EmpPageQuery;/*** 员工的业务类*/
public interface EmpService {/*** 分页查询员工信息* @param query* @return*/Result queryPage(EmpPageQuery query);Result add(Emp emp);Result update(Emp emp);Result delete(String empId);
}package com.powernode.service.impl;import com.powernode.common.Result;
import com.powernode.dao.EmpDao;
import com.powernode.domain.Emp;
import com.powernode.query.EmpPageQuery;
import com.powernode.service.EmpService;
import com.powernode.util.PageInfo;public class EmpServiceImpl implements EmpService {EmpDao empDao = new EmpDao();@Overridepublic Result queryPage(EmpPageQuery query) {PageInfo<Emp> empPageInfo = empDao.selectPage(query);return new Result(empPageInfo);}@Overridepublic Result add(Emp emp) {int m = empDao.insert(emp);if (m == 1){return new Result();}return new Result(400,"数据添加失败");}@Overridepublic Result update(Emp emp) {int m = empDao.updateById(emp);if (m == 1){return new Result();}return new Result(400,"数据修改失败");}@Overridepublic Result delete(String empId) {int m = empDao.deleteById(empId);if (m == 1){return new Result();}return new Result(400,"数据删除失败");}
}
4.1.3.2.3 dao
package com.powernode.dao;import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.powernode.domain.Emp;
import com.powernode.query.EmpPageQuery;
import com.powernode.util.PageInfo;public class EmpDao extends BaseDao{/*** 分页查询员工信息* @param query* @return*/public PageInfo<Emp> selectPage(EmpPageQuery query){String sql = "select emp_id as empId,emp_name as empName,emp_sex as empSex,emp_address as empAddress,emp_age as empAge,emp_salary as empSalary,`emp_birth` as empBirth, `dept_id` as deptId from emp where 1=1 ";if(ObjectUtil.isNotNull(query.getDeptId())){sql = sql + " and dept_id = "+query.getDeptId();}if(StrUtil.isNotBlank(query.getEmpName())){sql = sql + " and emp_name like '%"+ query.getEmpName() +"%'";}if(StrUtil.isNotBlank(query.getEmpAddress())){sql = sql + " and emp_addresss like '%"+ query.getEmpAddress() +"%'";}if(ObjectUtil.isNotNull(query.getEmpSex())){sql = sql + " and emp_sex = "+query.getEmpSex();}PageInfo<Emp> empPageInfo = super.executeQueryPage(sql, query.getPage(), query.getLimit(), Emp.class);return empPageInfo;}public int insert(Emp emp) {String sql = "INSERT INTO emp(`emp_name`, `emp_sex`, `emp_address`, `emp_age`, `emp_salary`, `emp_birth`, `dept_id`) VALUES (?, ?, ?, ?, ?,?, ?)";return super.executeUpdate(sql,emp.getEmpName(),emp.getEmpSex(),emp.getEmpAddress(),emp.getEmpAge(),emp.getEmpSalary(),emp.getEmpBirth(),emp.getDeptId());}public int updateById(Emp emp) {String sql = "UPDATE `emp` SET `emp_name` = ?, `emp_sex` = ?, `emp_address` = ?, `emp_age` = ?, `emp_salary` = ?, `emp_birth` = ? , `dept_id` = ? WHERE `emp_id` = ?";return super.executeUpdate(sql,emp.getEmpName(),emp.getEmpSex(),emp.getEmpAddress(),emp.getEmpAge(),emp.getEmpSalary(),emp.getEmpBirth(),emp.getDeptId(),emp.getEmpId());}public int deleteById(String empId) {String sql = "delete from emp where emp_id = "+empId;return super.executeUpdate(sql);}
}
4.2 前端界面
4.2.1 登录界面
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>Login Page</title><!-- 样 式 文 件 --><link rel="stylesheet" href="resources/css/pear.css" /><link rel="stylesheet" href="resources/css/login.css" /><link rel="stylesheet" href="resources/element/index.css" /><script src="resources/js/vue.js"></script><script src="resources/js/axios.js"></script><script src="resources/element/index.js"></script>
</head>
<!-- 代 码 结 构 -->
<body background="resources/images/background.svg" style="background-size: cover;">
<form class="layui-form" action="javascript:void(0);" id="app"><div class="layui-form-item"><img class="logo" src="resources/images/logo.png" /><div class="title">E M P</div><div class="desc">江 夏 区 最 靓 的 仔!</div></div><div class="layui-form-item"><input placeholder="账 户 : admin " v-model="form.username" hover class="layui-input" /></div><div class="layui-form-item"><input placeholder="密 码 : admin " v-model="form.password" hover class="layui-input" /></div><div class="layui-form-item"><input placeholder="验证码 : " v-model="form.code" hover lay-verify="required" class="code layui-input layui-input-inline" /><img :src="codeUrl" class="codeImage" @click="getCheckCode" /></div><div class="layui-form-item"><button type="button" @click="login" class="pear-btn pear-btn-success login" lay-submit lay-filter="login">登 入</button></div>
</form>
<script>const app = new Vue({el:"#app",data:{form:{username:'',password:'',code:''},codeUrl:"code.do"},methods:{login(){console.log(this.form)axios.post("user.do?service=login",this.form,{transformRequest:[function (data,headers) {let arr = [];for (let key in data) {let value = data[key];arr.push(key+"="+value);}return arr.join("&");}]}).then(res=>{//打印 服务端返回的数据console.log(res.data);let result = res.data;if (result.code != 0){//将错误信息展示this.$message.error(result.msg);return false;}// 登录成功情况// 将当前用户 存储到 sessionStorage 便于 其他页面 获取当前用户信息sessionStorage.setItem("user",JSON.stringify(result.data))// 页面跳转location.href = "main.html";});},getCheckCode(){this.codeUrl = "code.do?"+new Date();}}});</script></body>
</html>
4.2.2 数据页面
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><link rel="stylesheet" href="resources/element/index.css"/><script src="resources/js/vue.js"></script><script src="resources/js/axios.js"></script><script src="resources/element/index.js"></script>
</head>
<body>
<div id="app"><!-- 上面编写搜索条件 --><el-row><el-col :span="20" :offset="2"><el-form :inline="true"><el-form-item label="部门" label-width="80px"><el-select v-model="search.deptId" clearable placeholder="请选择"><el-option v-for="item in depts" :label="item.deptName" :value="item.deptId"></el-option></el-select></el-form-item><el-form-item label="姓名" label-width="80px"><el-input placeholder="姓名" v-model="search.empName"></el-input></el-form-item><el-form-item label="地址" label-width="80px"><el-input placeholder="地址" v-model="search.empAddress"></el-input></el-form-item><el-form-item label="性别" label-width="80px"><el-select v-model="search.empSex" clearable placeholder="请选择"><el-option label="男" value="1"></el-option><el-option label="女" value="2"></el-option></el-select></el-form-item><el-button native-type="button" icon="el-icon-search" type="primary" @click="handlerSearch">查询</el-button><el-button native-type="reset" icon="el-icon-refresh" type="danger">重置</el-button></el-form></el-col></el-row><el-divider></el-divider><!-- 数据表格 --><el-row><el-col :span="20" :offset="2"><el-button type="primary" icon="el-icon-add" style="margin-bottom: 15px" size="small" @click="toAdd">添加</el-button><el-table:data="empPageInfo.data"style="width: 100%"><el-table-columnlabel="编号"prop="empId"width="180"></el-table-column><el-table-columnlabel="姓名"prop="empName"width="180"></el-table-column><el-table-columnlabel="性别"prop="empSex"width="180"><template slot-scope="scope">{{scope.row.empSex == 1 ? '男' : '女'}}<!-- <el-tag :type="scope.row.empSex == 1 ? 'success':'primary'"> {{scope.row.empSex == 1 ? '男':'女'}}</el-tag>--></template></el-table-column><el-table-columnlabel="地址"prop="empAddress"width="180"></el-table-column><el-table-columnlabel="年龄"prop="empAge"width="180"></el-table-column><el-table-columnlabel="工资"prop="empSalary"width="180"></el-table-column><el-table-columnlabel="部门"prop="deptId"width="180"><template slot-scope="scope">{{scope.row.deptId|getDeptName}}</template></el-table-column><el-table-column label="操作"><template slot-scope="scope"><el-buttonsize="mini"@click="toEdit(scope.row)">编辑</el-button><el-buttonsize="mini"type="danger"@click="handleDelete(scope.row)">删除</el-button></template></el-table-column></el-table><!-- 分页组件 --><el-pagination@size-change="handleSizeChange"@current-change="handleCurrentChange":current-page="currentPage":page-sizes="[10,20,50,100]":page-size="pageSize"layout="total, sizes, prev, pager, next, jumper":total="empPageInfo.total"></el-pagination></el-col></el-row><!-- 弹出层 --><el-dialog :title="title" :visible.sync="showed" :close-on-click-modal="false" :before-close="clearFormValidateMsg"><el-form ref="empForm" :model="form" :rules="rules"><el-form-item label="姓名" label-width="80px" prop="empName"><el-input v-model="form.empName" autocomplete="off" placeholder="姓名"></el-input></el-form-item><el-form-item label="性别" label-width="80px" prop="empSex"><el-radio-group v-model="form.empSex"><el-radio label="1">男</el-radio><el-radio label="2">女</el-radio></el-radio-group></el-form-item><el-form-item label="地址" label-width="80px" prop="empAddress"><el-input v-model="form.empAddress" autocomplete="off" placeholder="地址"></el-input></el-form-item><el-form-item label="年龄" label-width="80px" prop="empAge"><el-input v-model="form.empAge" autocomplete="off" placeholder="年龄"></el-input></el-form-item><el-form-item label="工资" label-width="80px" prop="empSalary"><el-input v-model="form.empSalary" autocomplete="off" placeholder="工资"></el-input></el-form-item><el-form-item label="生日" label-width="80px" prop="empBirth"><el-date-pickerv-model="form.empBirth"type="date"value-format="yyyy-MM-dd"placeholder="请选择生日"></el-date-picker></el-form-item><el-form-item label="部门" label-width="80px" prop="deptId"><el-select v-model="form.deptId" clearable placeholder="请选择部门"><el-option v-for="item in depts" :label="item.deptName" :value="item.deptId"></el-option></el-select></el-form-item></el-form><div slot="footer" class="dialog-footer"><el-button @click="clearFormValidateMsg">取 消</el-button><el-button type="primary" @click="handlerEdit">确 定</el-button></div></el-dialog>
</div><script>let that;const app = new Vue({el: "#app",beforeCreate() {that = this;},data: {depts: [], // 所有的部门信息search: { // 搜索数据deptId: undefined,empName: undefined,empAddress: undefined,empSex: undefined},empPageInfo: { // 分页查询的员工数据},pageSize: 10,// 每页条数currentPage: 1,// 当前页title: "添加员工",showed: false, // 弹出是否显示form: {empName: '', //员工名称empSex: undefined, //性别empAddress: '', //地址empAge: '', //年龄empSalary: '', //工资empBirth: '', //生日deptId: '', //部门},rules: {empName: [{required: true, min: 2, max: 10, message: '请输入员工名称2~10位字符', trigger: 'blur'}],empSex: [{required: true, type: 'enum', enum: ['1', '2'], message: '请选择员工性别:男或女'}],empAddress: [{required: true, min: 2, max: 100, message: '请输入员工地址,最多100字符'}],empAge: [{required: true, message: '请输入员工年龄'}],empSalary: [{required: true, message: '请输入员工工资'}],empBirth: [{required: true, message: '请选择员工生日'}],deptId: [{required: true, message: '请选择部门'}],}},created() {// 初始化 部门数据this.getAllDepts();//初始化员工信息表格this.getEmpPage();},methods: {clearFormValidateMsg(){this.$message("弹层准备关闭!")// 清除校验信息this.$refs.empForm.clearValidate();this.showed = false;},// 获取所有的部门信息getAllDepts() {axios.get("dept.do?service=all").then(res => {let rs = res.data;if (rs.code != 0) {this.$message.error(rs.msg);return false;}// 为部门赋值this.depts = rs.data;});},getEmpPage() { // 查询 emp 分页信息// 为当前页码赋值this.search.page = this.currentPage;// 为每页条数赋值this.search.limit = this.pageSize;axios.get("emp.do?service=page", {params: this.search}).then(res => {let rs = res.data;if (rs.code != 0) {this.$message.error(rs.msg);return false;}// 为员工信息赋值this.empPageInfo = rs.data;});},handlerSearch() {this.currentPage = 1;// 调用获取员工信息的方法this.getEmpPage();},handleSizeChange(val) { // 每页条数 发生变化是调用的函数this.pageSize = val;this.currentPage = 1;// 调用获取员工信息的方法this.getEmpPage();},handleCurrentChange(val) { // 当前页码发生变化的函数this.currentPage = val;// 调用获取员工信息的方法this.getEmpPage();},toEdit(emp) { //编辑方法// 展示弹出层this.title = "编辑员工",this.showed = true;let data = {};Object.assign(data,emp);this.form = data;this.form.empSex = "" + emp.empSex; //性别// 标识添加this.form.service = "update";},toAdd() { // 将弹出层展示this.title = "添加员工",// 展示弹出层this.showed = true;// 标识添加this.form.service = "add";},handlerEdit() { // 该方法即是添加 也是修改的方法 service = add 就是添加 update 就是修改// 进行数据校验let flag = this.$refs.empForm.validate(rs => {// rs 是校验结果if (!rs) {// 阻止提交return false;}axios.post("emp.do", this.form, {transformRequest: [function (data, headers) {let arr = [];for (let key in data) {let value = data[key];arr.push(key + "=" + value);}return arr.join("&");}]}).then(res => {let rs = res.data;let code = rs.code;let msg = rs.msg;if (code != 0) {this.$message.error(msg);return false;}// 将关闭this.showed = false;//重置属性this.$refs.empForm.resetFields();this.$refs.empForm.clearValidate();// 成功则刷新表格this.handlerSearch();}).catch(error => {this.$message.error("数据添加失败!");});});},handleDelete(emp) { //删除方法/** 1. 删除二次确认框* 2. 获取业务员ID* 3. 将业务员ID 传递给后端* 4. 处理后端返回结果* */this.$confirm('确定要删除员工【' + emp.empName + '】吗?', '确认删除', {confirmButtonText: '确定',cancelButtonText: '取消',type: 'danger'}).then(() => {axios.get("emp.do?service=delete&empId=" + emp.empId).then(res => {// 获取返回的数据let rs = res.data;// 将操作结果进行提示this.$message({type: 'info',message: rs.msg})// 操作成功 刷新表格if (rs.code == 0) {//点击查询按钮this.handlerSearch();}});}).catch(() => {this.$message({type: 'info',message: '已取消删除'});});}},filters: { // 数据转发getDeptName(id) {//循环所有的部门 对比 ID 如果一致 则返回 部门名称for (let dept of that.depts) {let deptId = dept.deptId;if (deptId == id) {return dept.deptName;}}return '未知';}}});</script>
</body>
</html>
5.监听器
5.1 ServletContext监听器
在Javaweb中监听器是只对Java的三大作用域进行监视的组件,监视3大作用域的生命周期和属性变化。
监视作用域对象的创建和销毁,监视作用域对象中的容器的数据的变化.JavaWeb分别提供2类接口:
-
生命周期监听接口
-
属性变化监听接口
生命周期监听接口:
ServletContextListener : 监听ServletContext的生命周期
HttpSessionListener : 监听HttpSession的生命周期
ServletRequestListener :监听每个HttpServletRequest对象的生命周期
在生命周期变化中,只有2个方法:创建和销毁
属性变化监听接口:
ServletContextAttributeListener : 监听ServletContext属性变化
HttpSessionAttributeListener : 监听HttpSession的属性变化
ServletRequestAttributeListener : 监听HttpServletRequest的属性变化
在属性变化中,只有3个方法:新增/删除/修改
5.1.1 生命周期监听器
5.1.1.1 ServletContextListener
ServletContext对象生命周期监听器,初始化方法,在应用程序启动时调用.因为ServletContext是全局作用域,全局有些只有一个.其中销毁方法在应用程序停止时调用.
5.1.1.2 HttpSessionListener
在创建Session对象时调用初始化方法,当session销毁时调用销毁方法
5.1.1.3 ServletRequestListener
在HttpServletRequst对象创建时调用初始化方法,service结束时,就会调用销毁方法.
5.1.2 属性变化监听器
当作用域的Map容器中,有新增的属性值时,触发新增的方法,如果有属性值被删除时,触发删除的方法,如果添加了一个属性值,覆盖了之前的属性值则触发修改方法.
5.2 应用
5.2.1 实现相关监听器接口
package com.powernode.listener;import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;/*** ServletContextListener : 生命周期监听器*/
public class AppListener implements ServletContextListener {/*** ServletContext 初始化完成的监听器* @param sce Information about the ServletContext that was initialized*/@Overridepublic void contextInitialized(ServletContextEvent sce) {System.out.println("ServletContext 要初始化完成了!");ServletContext servletContext = sce.getServletContext();String value1 = servletContext.getInitParameter("key1");System.out.println(value1);}/*** ServletContext 要被销毁的监听器* @param sce Information about the ServletContext that was destroyed*/@Overridepublic void contextDestroyed(ServletContextEvent sce) {System.out.println("ServletContext 要被销毁了");System.out.println(sce.getServletContext());}
}
5.2.2 监听器注册
5.2.2.1 xml配置
<!-- 注册监听器 -->
<listener><listener-class>com.powernode.listener.AppListener</listener-class>
</listener>
<!-- ServletContext 初始化参数 -->
<context-param><param-name>key1</param-name><param-value>value1</param-value>
</context-param>
<context-param><param-name>key2</param-name><param-value>value2</param-value>
</context-param>
5.2.2.2 注解
@WebListener
public class AppListener implements ServletContextListener {}
5.3 监听器场景
由于ServletContextListener在项目启动时就可以调用初始化方法,将一些耗时的操作进行全局化初始化,例如:初始化连接池.将比较大复杂对象初始化,可以使用ServletContextListener在项目启动时进行完成,具体的业务中只需要实际使用即可.
package com.powernode.listener;import com.powernode.dao.UserDao;
import com.powernode.domain.User;
import com.powernode.service.UserService;
import com.powernode.service.impl.UserServiceImpl;
import com.powernode.util.DBUtils;import javax.servlet.*;
import javax.servlet.annotation.WebListener;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;/*** ServletContextListener : 生命周期监听器*/
@WebListener
public class AppListener implements ServletContextListener, ServletContextAttributeListener {/*** 存储所有业务对象*/final static Map<Class,Object> context = new ConcurrentHashMap<>();/*** ServletContext 初始化完成的监听器* @param sce Information about the ServletContext that was initialized*/@Overridepublic void contextInitialized(ServletContextEvent sce) {context.put(UserDao.class,new UserDao());context.put(UserService.class,new UserServiceImpl());System.out.println("ServletContext 要初始化完成了!");ServletContext servletContext = sce.getServletContext();String value1 = servletContext.getInitParameter("key1");System.out.println(value1);try {//关联.properties配置文件Properties prop = new Properties();InputStream ins = DBUtils.class.getClassLoader().getResourceAsStream("db.properties");prop.load(ins);//读取.properties配置文件的属性值DBUtils.driverClassName = prop.getProperty("jdbc.driverClassName");DBUtils.url = prop.getProperty("jdbc.url");DBUtils.username = prop.getProperty("jdbc.username");DBUtils.password = prop.getProperty("jdbc.password");Class.forName(DBUtils.driverClassName);} catch (Exception e) {e.printStackTrace();}Connection conn = DBUtils.getConn();DBUtils.close(conn);}/*** ServletContext 要被销毁的监听器* @param sce Information about the ServletContext that was destroyed*/@Overridepublic void contextDestroyed(ServletContextEvent sce) {System.out.println("ServletContext 要被销毁了");System.out.println(sce.getServletContext());}public static <T> T getInstance(Class<T> cls){return (T) context.get(cls);}//===============================以下是属性监听==========================================@Overridepublic void attributeAdded(ServletContextAttributeEvent scae) {System.out.println("新增了属性值时 调用");}@Overridepublic void attributeRemoved(ServletContextAttributeEvent scae) {System.out.println("删除了属性值时 调用");}@Overridepublic void attributeReplaced(ServletContextAttributeEvent scae) {System.out.println("修改了属性值时 调用");}
}