Servlet项目教学(附实例代码)

【员工信息管理】

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 过滤器的实现

  1. 实现Filter接口

  2. 重写相关方法:doFilter方法

  3. 注册过滤器

(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三大作用域就是三个用于存储数据的容器,根据其范围划分分为以下三类(小到大):

  1. 当前请求作用域

  2. 当前会话作用域

  3. 当前应用作用域

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类接口:

  1. 生命周期监听接口

  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("修改了属性值时  调用");}
} 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/629080.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

二次开发在线预约上门服务、预约到家系统 增加开发票功能 轮播图链接跳转 uniapp代码

客户具体要求&#xff1a; 1、在我的个人中心里面增加一个 开票功能&#xff0c;点击进去之后可以查看到能开票的订单列表&#xff0c;如果是个人是填写姓名电话邮箱&#xff0c;就是填写单位名称 税号 邮箱&#xff0c;提交申请到后台审核&#xff0c;如果审核通过后线下人工…

各种设备上恢复已删除的文件和文件夹的数据恢复软件清单

最好的数据恢复软件可以简单轻松地恢复计算机、移动设备或存储介质上已删除的文件和文件夹。 询问任何经历过数据丢失的人这是否是一种有趣的经历&#xff0c;他们会告诉您数据丢失&#xff0c;无论是由于硬件或软件故障、意外删除还是网络犯罪&#xff0c;都会带来极大的压力…

高精度算法笔记

目录 加法 减法 乘法 除法 高精度加法的步骤&#xff1a; 1.高精度数字利用字符串读入 2.把字符串翻转存入两个整型数组A、B 3.从低位到高位&#xff0c;逐位求和&#xff0c;进位&#xff0c;存余 4.把数组C从高位到低位依次输出 1.2为准备 vector<int> A, B, C…

接近8000字的SpringSpring常用注解总结!安排

接近8000字的Spring/Spring常用注解总结&#xff01;安排 为什么要写这篇文章&#xff1f; 最近看到网上有一篇关于 SpringBoot 常用注解的文章被转载的比较多&#xff0c;我看了文章内容之后属实觉得质量有点低&#xff0c;并且有点会误导没有太多实际使用经验的人&#xff…

如何用AI提高论文阅读效率?

已经2024年了&#xff0c;该出现一个写论文解读AI Agent了。 大家肯定也在经常刷论文吧。 但真正尝试过用GPT去刷论文、写论文解读的小伙伴&#xff0c;一定深有体验——费劲。其他agents也没有能搞定的&#xff0c;今天我发现了一个超级厉害的写论文解读的agent &#xff0c…

UML-实现图(组件图和部署图)

实现图是从系统的层次来描述的&#xff0c;描述硬件的组成和布局&#xff0c;描述软件系统划分和功能实现。 UML-实现图&#xff08;组件图和部署图&#xff09; 一、组件图1.组件图的元素&#xff08;1&#xff09;组件&#xff08;2&#xff09;接口&#xff08;3&#xff09…

为什么要将应用微服务化

上古时期的高可用架构 其实在十多年前&#xff0c;“架构师”并不是一个需求很大的职业&#xff0c;一来那时还没有“全民App”级别的应用&#xff0c;除了三大门户网站以外&#xff0c;其他的网上应用业务压力并不大;二来也没有现如今这么丰富的技术选型&#xff0c;几乎清一…

LINUX基础培训九之网络管理

前言、本章学习目标 了解LINUX网络接口和主机名配置的方法熟悉网络相关的几个配置文件了解网关和路由熟悉网络相关的命令使用 一、网络IP地址配置 在Linux中配置IP地址的方法有以下这么几种&#xff1a; 1、图形界面配置IP地址&#xff08;操作方式如Windows系统配置IP&…

快速入门Torch构建自己的网络模型

真有用构建自己的网络模型 读前必看刚学完Alex网络感觉很厉害的样子&#xff0c;我也要搭建一个可以看着网络结构实现上面的代码你已经很强了&#xff0c;千万不要再想实现VGG等网络&#xff01;&#xff01;&#xff01;90%你能了解到的模型大佬早已实现好&#xff0c;直接调用…

MFC CAsyncSocket类作为客户端示例

之前写过CAsyncSocket类使用的博客;进一步看一下; VS新建一个MFC 对话框工程; 添加一个类,从CAsyncSocket继承,起个自己的名字; 对话框添加几个编辑框,按钮,静态控件; 为自己的CxxxAsyncSocket类添加重写的虚函数,OnConnect、OnReceive、OnSend; 自己的CAsyncSoc…

pytorch一致数据增强—独用增强

前作 [1] 介绍了一种用 pytorch 模仿 MONAI 实现多幅图&#xff08;如&#xff1a;image 与 label&#xff09;同用 random seed 保证一致变换的写法&#xff0c;核心是 MultiCompose 类和 to_multi 包装函数。不过 [1] 没考虑各图用不同 augmentation 的情况&#xff0c;如&am…

生物制药厂污水处理需要哪些工艺设备

生物制药厂是一种特殊的工业场所&#xff0c;由于其生产过程中涉及的有机物较多&#xff0c;导致废水中含有高浓度的有机物和微生物等污染物&#xff0c;因此需要采用一些特殊的工艺设备来进行污水处理。本文将介绍生物制药厂污水处理中常用的工艺设备。 首先&#xff0c;对于生…

【面试合集】说说微信小程序的支付流程?

面试官&#xff1a;说说微信小程序的支付流程&#xff1f; 一、前言 微信小程序为电商类小程序&#xff0c;提供了非常完善、优秀、安全的支付功能 在小程序内可调用微信的API完成支付功能&#xff0c;方便、快捷 场景如下图所示&#xff1a; 用户通过分享或扫描二维码进入商…

2024年华数杯国际赛赛题浅析

21号完赛&#xff0c;28号出成绩的华数杯国际赛&#xff0c;作为美赛最合适的练手赛正式开赛。为了让大家更好地比赛&#xff0c;首先为大家带来本次竞赛两道题目的浅要解析。主要分析两道题目适合的群体&#xff0c;未来大家求解过程中可能遇到的问题。方便大家快速完成选题。…

农业四情监测管理系统的特点优势

TH-Q2农业四情监测管理系统是一种利用现代信息技术&#xff0c;对农业生产中的墒情、苗情、虫情、灾情进行实时监测和管理的智能化系统。那么&#xff0c;这个系统到底有哪些特点和优势呢&#xff1f;让我们一起来了解一下。 1.实时监测&#xff1a;通过传感器、摄像头等设备&a…

美国智库发布《用人工智能展望网络未来》的解析

文章目录 前言一、人工智能未来可能改善网络安全的方式二、人工智能可能损害网络安全的方式三、人工智能使用的七条建议四、人工智能的应用和有效使用AI五、安全有效地使用人工智能制定具体建议六、展望网络未来的人工智能&#xff08;一&#xff09;提高防御者的效率&#xff…

DWM1000 MAC层

DWM1000 MAC层 MAC层 概述 MAC层&#xff0c;即媒体访问控制层&#xff0c;是数据通信协议栈中的一个重要部分&#xff0c;位于链路层的下半部分&#xff0c;紧邻物理层。在OSI模型中&#xff0c;它属于第二层&#xff0c;即数据链路层的一部分。MAC层的主要职责是控制如何在…

框架基础-Maven+SpringBoot入门

框架基础 Maven基础 Maven概述 Maven是为Java项目提供项目构建和依赖管理的工具 Maven三大功能 - 项目构建构建&#xff1a;是一个将代码从开发阶段到生产阶段的一个过程&#xff1a;清理&#xff0c;编译&#xff0c;测试&#xff0c;打包&#xff0c;安装&#xff0c;部署…

运筹说 第46期 | 目标规划-数学模型

经过前几期的学习&#xff0c;想必大家已经对线性规划问题有了详细的了解&#xff0c;但线性规划作为一种决策工具&#xff0c;在解决实际问题时&#xff0c;存在着一定的局限性&#xff1a;(1)线性规划只能处理一个目标&#xff0c;而现实问题往往存在多个目标&#xff1b;(2)…

GEE时序——利用sentinel-2(哨兵-2)数据进行地表物候学分析(时间序列平滑法估算和非平滑算法代码)

简介 哨兵-2A/B 串联卫星的空间分辨率高、重访时间长,有可能改进对陆地表面物候的检索。不过,生物群落和区域特征在很大程度上限制了陆表物候学算法的设计。在北极地区,这种生物群落特有的特征包括长期积雪、持续云层覆盖和生长季节短暂。在此,我们评估了哨兵-2 获取北极高…