【员工信息管理】
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
*/
@Override
public 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
*/
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println(" 进行具体的过滤操作 doFilter..... ");
// xxxxx
System.out.println("在调用下一个方法之前干点啥......");
// 调用下一个方法
// 在进入servlet 之前 就已经设置好了编码格式
servletRequest.setCharacterEncoding("UTF-8");
servletResponse.setCharacterEncoding("UTF-8");
filterChain.doFilter(servletRequest,servletResponse);
// xxxxx
System.out.println("在调用完成也干点啥......");
}
@Override
public 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 {
@Override
public 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();
}
//执行sql
arr = 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=1
int pages = temp==0? (int)(total/pageSize): (int)Math.ceil((double)total/(double)pageSize);
pageInfo.setPages(pages