JavaWeb综合项目——快递e栈(后台部分)

文章目录

写在前面

  Java学习者一个重要的学习分水岭就是JavaWeb技术,这个阶段的学习在已经掌握了Java基础语法之后,并且在学习框架知识之前。
  在我个人看来,完成了JavaWeb知识的学习之后,如果可以自己动手写一个无限接近实际项目的demo的话可以更好的有助于之后阶段的学习。各类框架固然可以极大程度上的简便我们的开发流程,但如果基本的JavaWeb都并不熟练的学习者,可能很难get到框架带来的简便性,反而会被框架中各类的配置劝退,与学习的初衷渐行渐远。
  此外,JavaWeb的练习也可以让我们体验到真正项目的实际后台开发过程,网上的资料也都参差不齐,所以我将花费了一周时间做的demo的步骤一步一步记录下来,并提供全部源码(遇到bug并不可怕,所有调试bug的经历都会成为以后工作学习生涯的宝贵财富)。

  本例实现了但不仅限于以下功能:

后台部分 微信端部分
1.管理员登录
2.管理员退出
3.快件增加
4.快件删除
5.快件修改
6.快件列表查看
7.用户增加
8.用户删除
9.用户删除
10.用户列表查看
11.快递员增加
12.快递员删除
13.快递员修改
14.快递员查询
15.控制台-显示快件区域区分图
16.控制台-显示用户人数
17.控制台-显示快递员人数
18.控制台-显示总快件数
19.控制台-显示等待取件数量
1.用户/快递员登录
2.用户/快递员注册
3.用户-我的取件列表(未取件/已取件)
4.用户-快件取件码展示
5.快递员-扫码取件 6.快递员-取件码取件
7.首页根据快递单号查询快递信息
8.快递员-录入快递
9.快递员历史查询
10.个人中心-昵称显示与修改
11.懒人排行榜

此外,借助微信公众平台实现扫码功能,ngrok实现内网穿透…部分界面如下:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

注:本例提供所有源码和相应jar文件,可以去我的下载界面下载或者关注我的公众号找我领取。

在这里插入图片描述

1 编写MVC框架

  服务器启动时,会加载application.properties配置文件,配置文件中有多个类,配置文件是由HandlerMapping来加载。
  HandlerMapping根据配置文件中的每个类,获取到每个类的方法,获取到方法之后再循环遍历这些方法,再找每个带有ResponseBodyResponseView的方法,再把这些方法都存放在HandlerMapping中,之后用于处理给用户响应,所以服务器启动之后HandlerMapping中会存一堆方法。
  当用户去请求DispatcherServlet时,首先去HandlerMapping中找有没有处理这个请求的方法,没有的话抛404异常。
  请求servlet的路径是:*.do

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <servlet>
        <servlet-name>DispatcherServlet</servlet-name>
        <servlet-class>com.wangjiawei.mvc.DispatcherServlet</servlet-class>
        <!-- 启动的时候加载配置文件 -->
        <init-param>
            <param-name>contentConfigLocation</param-name>
            <param-value>application.properties</param-value>
        </init-param>
        <load-on-startup>0</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>DispatcherServlet</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>

</web-app>

在这里插入图片描述

1.1 定义两个注解

package com.wangjiawei.mvc;

import java.lang.annotation.*;

/**
 * 2 * @Author: 小王同学
 * 3 * @Date: 2020/9/30 9:56
 * 4 被此注解添加的方法,会被用于处理请求
 * 5 方法返回的内容,会以文字形式返回到客户端
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ResponseBody {
    
    
    String value();
}
package com.wangjiawei.mvc;

import java.lang.annotation.*;

/**
 * 2 * @Author: 小王同学
 * 3 * @Date: 2020/9/30 9:56
 * 4 被此注解添加的方法,会被用于处理请求
 * 5 方法返回的内容,会直接重定向
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ResponseView {
    
    
    String value();
}

再定义枚举类对应上面的两个注解:

package com.wangjiawei.mvc;

/**
 * 2 * @Author: 小王同学
 * 3 * @Date: 2020/9/30 10:01
 * 4 响应的类型是文字还是视图
 */
public enum ResponseType {
    
    
    TEXT,VIEW;
}

1.2 编写映射器 HandlerMapping

package com.wangjiawei.mvc;

import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * 2 * @Author: 小王同学
 * 3 * @Date: 2020/9/30 10:04
 * 4 映射器,包含了大量的网址与方法的对应关系
 */
public class HandlerMapping {
    
    

    private static Map<String, MVCMapping> data = new HashMap<>();

    public static MVCMapping get(String uri){
    
    
        return data.get(uri);
    }

    public static void load(InputStream is){
    
    
        Properties ppt = new Properties();
        try {
    
    
            ppt.load(is);
        } catch (IOException e) {
    
    
            e.printStackTrace();
        }
        // 获取配置文件中描述的每个类
        Collection<Object> values = ppt.values();
        for (Object value : values) {
    
    
            String className = (String)value;
            try {
    
    
                // 加载配置文件中描述的每个类(用于处理请求的类)
                Class c = Class.forName(className);
                // 创建类的对象
                Object obj = c.getConstructor().newInstance();
                // 获取类的所有方法
                Method[] methods = c.getMethods();
                for (Method method : methods) {
    
    
                    Annotation[] as = method.getAnnotations();
                    if (as != null){
    
    
                        for (Annotation annotation : as){
    
    
                            if (annotation instanceof ResponseBody){
    
    
                                // 此方法用于返回字符串给客户端
                                MVCMapping mvcMapping = new MVCMapping(obj, method, ResponseType.TEXT);
                                Object o = data.put(((ResponseBody) annotation).value(), mvcMapping);
                                if (o != null){
    
    
                                    // 存在了重复的请求地址
                                    throw new RuntimeException("请求地址重复" + ((ResponseBody) annotation).value());
                                }
                            }else if(annotation instanceof ResponseView){
    
    
                                // 此方法用于返回界面给客户端
                                MVCMapping mvcMapping = new MVCMapping(obj, method, ResponseType.VIEW);
                                Object o = data.put(((ResponseView) annotation).value(), mvcMapping);
                                if (o != null){
    
    
                                    // 存在了重复的请求地址
                                    throw new RuntimeException("请求地址重复" + ((ResponseView) annotation).value());
                                }
                            }
                        }
                    }
                }
            } catch (Exception e) {
    
    
                e.printStackTrace();
            }
        }
    }

    /**
     * 映射对象,每一个对象封装了一个方法,用于处理请求
     */
    public static class MVCMapping{
    
    
        private Object obj;
        private Method method;
        private ResponseType type;

        public MVCMapping() {
    
    
        }

        public MVCMapping(Object obj, Method method, ResponseType type) {
    
    
            this.obj = obj;
            this.method = method;
            this.type = type;
        }

        public Object getObj() {
    
    
            return obj;
        }

        public void setObj(Object obj) {
    
    
            this.obj = obj;
        }

        public Method getMethod() {
    
    
            return method;
        }

        public void setMethod(Method method) {
    
    
            this.method = method;
        }

        public ResponseType getType() {
    
    
            return type;
        }

        public void setType(ResponseType type) {
    
    
            this.type = type;
        }
    }
}

1.3 定义分发Servlet

package com.wangjiawei.mvc;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;

/**
 * 2 * @Author: 小王同学
 * 3 * @Date: 2020/9/29 21:22
 * 4
 */
public class DispatcherServlet extends HttpServlet {
    
    

    @Override
    public void init(ServletConfig config) throws ServletException {
    
    
        String path = config.getInitParameter("contentConfigLocation");
        InputStream is = DispatcherServlet.class.getClassLoader().getResourceAsStream(path);
        HandlerMapping.load(is);
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        // 获取用户请求的uri
        String uri = req.getRequestURI();
        HandlerMapping.MVCMapping mvcMapping = HandlerMapping.get(uri);

        if (mvcMapping == null){
    
    
            resp.sendError(404, "MVC:映射地址不存在" + uri);
            return;
        }

        Object obj = mvcMapping.getObj();
        Method method = mvcMapping.getMethod();
        Object result = null;
        try {
    
    
            result = method.invoke(obj, req, resp);
        } catch (IllegalAccessException e) {
    
    
            e.printStackTrace();
        } catch (InvocationTargetException e) {
    
    
            e.printStackTrace();
        }
        switch (mvcMapping.getType()){
    
    
            case TEXT:
                resp.getWriter().write((String) result);
                break;
            case VIEW:
                resp.sendRedirect((String) result);
                break;
            default:
                break;
        }

    }
}

1.4 测试类

package com.wangjiawei.test;

import com.sun.deploy.net.HttpResponse;
import com.wangjiawei.mvc.ResponseBody;
import com.wangjiawei.mvc.ResponseView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 2 * @Author: 小王同学
 * 3 * @Date: 2020/9/30 11:08
 * 4
 */
public class UserController {
    
    

    @ResponseBody("/login.do")
    public String login(HttpServletRequest request, HttpServletResponse response){
    
    
        return "login success";
    }

    @ResponseView("/reg.do")
    public String reg(HttpServletRequest request, HttpServletResponse response){
    
    
        return "success.jsp";
    }
}

2 前端补充

2.1 二维码生成

步骤:

  1. 引入Jquery.js文件
  2. 引入jquery.qrcode.js文件
  3. 引入支持中文的编码js文件 (utf.js)
  4. 在网页中编写一个div 用于显示二维码
 <div id="div1"></div>
  1. 准备二维码的规格对象(JSON)
var config  = {
    
    
    width:数字,//值是number类型, 表示的单位是px  必须传递
    height:数字,//值是number类型, 表示的单位是px  必须传递 
    text:"内容",//text就表示二维码中存储的数据  必须传递
    correctLevel:数字,//取值为0|1|2|3 表示二维码的纠错级别0:L/1:M/2:Q/3:H ,默认0  可选参数
    background:"#rrggbb",//默认白色, 表示二维码的后景颜色 可选参数
    foreground:"#rrggbb",//默认黑色, 表示二维码的前景颜色 可选参数
    render:"绘制模式"//取值:table/canvas , 默认table 可选参数
};
  1. 通过选择器, 查找到上述的div ,得到Jquery对象, 通过jquery对象的qrcode函数生成二维码
$("#div1").qrcode(config);
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>二维码生成</title>
    <script src="js/jquery2.1.4.js"></script>
    <script src="js/jquery.qrcode.js"></script>
    <script src="js/utf.js"></script>
</head>
<body>
    <div id="qrcode"></div>
    <script>
        var config = {
     
     
            width:200,
            height:200,
            text:"欢迎关注【N小王日记】"
        };
        $("#qrcode").qrcode(config);
    </script>
</body>
</html>

2.2 layui

layui官网

2.2.1 布局部分

与BootStrap很像,就是展示一些界面效果。

2.2.2 弹出层

步骤:

  1. 下载layer , 并将解压后的layer文件夹 移动到项目中
  2. 引入jquery.js
  3. 引入layer.js

layer - msg函数

用于弹出信息提示框

格式1

layer.msg("文本");

格式2 抖动显示

 layer.msg("文本",function(){
    
    
        //弹窗结束后会执行
    });

layer - load函数
格式1
  弹出loading:

var index = layer.load(数字0-2); 
// 参数表示 loading的图表
//loading窗口在弹出时, 不允许进行操作.

关闭loading:

layer.close(index);

格式2
  超时自动关闭的loading

var index = layer.load(数字0-2,{
    
    time:毫秒数字})
//在指定的毫秒后 ,如果没有使用layer.close关闭, 则自动关闭

layer - msg函数(load效果)
格式:
  弹出的格式:

var index = layer.msg("文本",{
    
    icon:16,shade:0.01})
//因为是msg函数, 所以此窗口会自动消失

关闭的格式:

layer.close(index);

layer - alert函数 信息提示窗
格式:

layer.alert("文本内容",{
    
    icon:图片编号});
//图片编号: 0-16之间 

layer - tips函数 提示层
格式:

layer.tips("文本内容","选择器",{
    
    tipsMore:true,tips:数字});

参数:

  1. 参数: tipsMore : 是否允许同时存在多个弹出的tips
  2. 参数: tips : 取值为数字1-4 , 分别表示弹出在元素的 上/右/下/左 . 默认弹出在右边

layer 所有弹出层的关闭

layer.closeAll();
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/jquery2.1.4.js"></script>
    <script src="layer/layer.js"></script>
    
    <script>
        function msgTest() {
     
     
            // layer.msg("提示的文字");
            layer.msg("提示的文字", function () {
     
     
                // 窗口关系时执行,和上面的区别还有会添加一个抖动
            });
        }
        
        function loadTest() {
     
     
            // 返回弹出层的id
            var windowId = layer.load(0);  // 0 - 16的数字,每一个代表不同效果
            // 通过窗口id关闭窗口
            setTimeout(function () {
     
     
                layer.close(windowId);
            }, 2000);
        }

        function msg_loadTest() {
     
     
            // icon不同的值对应不同的图标
            layer.msg("提示的文字", {
     
     icon:16, shade:0.01});
        }
        
        function alertTest() {
     
     
            layer.alert("文字内容", {
     
     icon : 10});
        }

        function tipsTest() {
     
     
            // tipsMore表示
            layer.tips("这里有秘密", "#s1", {
     
     tipsMore:true, tips:2});
        }
    </script>
</head>
<body>
    <button onclick="msgTest()">msg函数(*)</button><br>
    <button onclick="loadTest()">load函数(*)</button><br>
    <button onclick="msg_loadTest()">load函数(load效果)</button><br>
    <button onclick="alertTest()">alert函数</button><br>
    <button onclick="tipsTest()">tips函数</button><br>
    <p>
        锄禾日<span id="s1">当午</span>,汗滴禾下土
    </p>
</body>
</html>

3 云短信使用

关键点:

  1. 在阿里云的sms控制台 创建签名
  2. 在阿里云的sms控制台 创建短信模板code值
  3. 在阿里云的RAM访问控制中心,新建一个用户 accessKeyId
  4. 在阿里云的RAM访问控制中心,新建一个用户 AccessKeySecret

《1》点击进入阿里云免费试用 , 然后登陆账号。
《2》 如图选择短信0元试用 (已经领取过的,直接走第三步即可。)

在这里插入图片描述
《3》点击进入阿里云短信官网 , 登陆状态下点击免费开通 (已开通的文字会替换为控制台 , 点击效果一样)
在这里插入图片描述
《4》选择国内消息

在这里插入图片描述
《5》创建短信签名
在这里插入图片描述
在这里插入图片描述
《6》创建短信模板
在这里插入图片描述
《7》创建子账户秘钥

  • 鼠标移至右上角账户名称 选择accesskeys
    在这里插入图片描述
  • 选择开始使用子用户AccessKey
  • 输入登陆名称和显示名称, 选择编程访问
    在这里插入图片描述
    复制得到的accessKeyId和 AccessKeySecret 留待后续使用
    在这里插入图片描述
  • 选择创建的子账户 ,点击添加权限
    在这里插入图片描述
  • 选择相应的权限, 并点击确定添加
    在这里插入图片描述
    《8》回到国内短信页面 , 复制审核成功的短信签名名称 以及 短信模板ID
    《9》完成上述步骤后, 已经得到了四个关键性参数
    短信签名名称 : 快递e栈
    短信模板CODE : SMS_20411…
    accessKeyId:LTAI4GKsiFzUmLZ8…
    AccessKeySecret: jUhIqqk3wwvhm2T1HOUVbC…
    在这里插入图片描述
    《9》下载jar文件 , 并引入到项目中

《10》将上述参数, 复制到如下代码中。 并通过JSON方式顺序填充每一个短信模板中到参数

import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.google.gson.Gson;

import java.util.HashMap;
import java.util.Random;

/**
 * 2 * @Author: 小王同学
 * 3 * @Date: 2020/10/1 10:42
 * 4
 */
public class SMSDemo {
    
    
    public static void main(String[] args) {
    
    
        Random r = new Random();
        int num = r.nextInt(900000) + 100000;
        send("18373110779", num + "");
    }

    public static boolean send(String phoneNumber,String code) {
    
    
        DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", "LTAI4GKsiFzUmLZ8Qnx1Sfza", "jUhIqqk3wwvhm2T1HOUVbCmIOWNE0O");
        IAcsClient client = new DefaultAcsClient(profile);

        CommonRequest request = new CommonRequest();
        request.setSysMethod(MethodType.POST);
        request.setSysDomain("dysmsapi.aliyuncs.com");
        request.setSysVersion("2017-05-25");
        request.setSysAction("SendSms");
        request.putQueryParameter("RegionId", "cn-hangzhou");
        request.putQueryParameter("PhoneNumbers", phoneNumber);
        request.putQueryParameter("SignName", "快递e栈");
        request.putQueryParameter("TemplateCode", "SMS_204115757");
        request.putQueryParameter("TemplateParam", "{\"code\":\""+ code +"\"}");
        try {
    
    
            CommonResponse response = client.getCommonResponse(request);
            System.out.println(response.getData());
            String json = response.getData();
            Gson g = new Gson();
            HashMap result = g.fromJson(json, HashMap.class);
            if("OK".equals(result.get("Message"))) {
    
    
                return true;
            }else{
    
    
                System.out.println("短信发送失败,原因:"+result.get("Message"));
            }
        } catch (ServerException e) {
    
    
            e.printStackTrace();
        } catch (ClientException e) {
    
    
            e.printStackTrace();
        }
        return false;
    }
}

4 项目搭建

4.1 Druid

见下载资源

4.2 MVC

见 编写MVC框架 部分

4.3 时间格式化工具类

package com.wangjiawei.util;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 2 * @Author: 小王同学
 * 3 * @Date: 2020/10/1 11:30
 * 4
 */
public class DateFormatUtil {
    
    

    private static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    public static String format(Date date){
    
    
        return format.format(date);
    }
}

4.4 前后端用于通信的消息类

package com.wangjiawei.bean;

/**
 * 2 * @Author: 小王同学
 * 3 * @Date: 2020/10/1 12:36
 * 4
 */
public class Message {
    
    

    // {status:0, result:"", data:{}}

    /**
     * 状态码 0表示成功,-1表示失败
     */
    private int status;

    /**
     * 消息内容
    */
    private String result;

    /**
    消息所携带的一组数据
     */
    private Object data;

    public Message() {
    
    
    }

    public Message(int status) {
    
    
        this.status = status;
    }

    public Message(String result) {
    
    
        this.result = result;
    }

    public Message(int status, String result, Object data) {
    
    
        this.status = status;
        this.result = result;
        this.data = data;
    }

    public String getResult() {
    
    
        return result;
    }

    public void setResult(String result) {
    
    
        this.result = result;
    }

    public Object getData() {
    
    
        return data;
    }

    public void setData(Object data) {
    
    
        this.data = data;
    }

    public int getStatus() {
    
    
        return status;
    }

    public void setStatus(int status) {
    
    
        this.status = status;
    }
}

4.5 随机数工具类

用于生成取件码

package com.wangjiawei.util;

import java.util.Random;

/**
 * 2 * @Author: 小王同学
 * 3 * @Date: 2020/10/4 14:09
 * 4
 */
public class RandomUtil {
    
    

    private static Random r = new Random();
    public static int getCode(){
    
    
        return r.nextInt(900000) + 100000;
    }

}

4.6 Json操作类

package com.wangjiawei.util;

import com.google.gson.Gson;

/**
 * 2 * @Author: 小王同学
 * 3 * @Date: 2020/10/1 13:50
 * 4
 */
public class JSONUtil {
    
    

    private static Gson g = new Gson();

    public static String toJSON(Object obj){
    
    
        return g.toJson(obj);
    }
}

5 管理员数据操作部分

后台管理前端页面模板:放在web.admin文件夹下

CREATE TABLE eadmin ( 
    id INT PRIMARY KEY auto_increment, 
    username VARCHAR ( 32 ), 
    PASSWORD VARCHAR ( 32 ), 
    loginip VARCHAR ( 32 ), 
    logintime datetime, 
    createtime datetime 
);

前台和后台交互的模式大致如下:
在这里插入图片描述
dao层接口:

package com.wangjiawei.dao;

import java.util.Date;

/**
 * 2 * @Author: 小王同学
 * 3 * @Date: 2020/10/2 9:20
 * 4   用于定义eadmin表的操作规范
 */
public interface BaseAdminDao {
    
    

    /**
     * 根据用户名,更新登录时间和登录ip
     * @param username
     */
    void updateLoginTime(String username, Date date, String ip);

    /**
     * 管理员根据账号密码登录
     * @param username
     * @param password
     * @return 登录结果 true:登录成功
     */
    boolean login(String username, String password);
}

dao层的实现类:

package com.wangjiawei.dao.imp;

import com.wangjiawei.dao.BaseAdminDao;
import com.wangjiawei.util.DruidUtil;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;

/**
 * 2 * @Author: 小王同学
 * 3 * @Date: 2020/10/2 9:26
 * 4
 */
public class AdminDaoMysql implements BaseAdminDao {
    
    
    private static final String SQL_UPDATE_LOGIN_TIME = "UPDATE EADMIN SET LOGINTIME = ?, LOGINIP = ? WHERE USERNAME = ?";
    private static final String SQL_LOGIN = "SELECT ID FROM EADMIN WHERE USERNAME = ? AND PASSWORD = ?";

    /**
     * 根据用户名,更新登录时间和登录ip
     *
     * @param username
     * @param date
     * @param ip
     */
    @Override
    public void updateLoginTime(String username, Date date, String ip) {
    
    
        Connection connection = DruidUtil.getConnection();
        PreparedStatement state = null;
        try {
    
    
            state = connection.prepareStatement(SQL_UPDATE_LOGIN_TIME);
            state.setDate(1, new java.sql.Date(date.getTime()));
            state.setString(2, ip);
            state.setString(3, username);
            state.executeUpdate();
        } catch (SQLException throwables) {
    
    
            throwables.printStackTrace();
        }finally {
    
    
            DruidUtil.close(connection,state,null);
        }
    }

    /**
     * 管理员根据账号密码登录
     *
     * @param username
     * @param password
     * @return 登录结果 true:登录成功
     */
    @Override
    public boolean login(String username, String password) {
    
    
        Connection connection = DruidUtil.getConnection();
        PreparedStatement state = null;
        ResultSet resultSet = null;
        try {
    
    
            state = connection.prepareStatement(SQL_LOGIN);
            state.setString(1,username);
            state.setString(2,password);
            resultSet = state.executeQuery();
            // 如果能查出来则有,返回true
            return resultSet.next();
        } catch (SQLException throwables) {
    
    
            throwables.printStackTrace();
        }finally {
    
    
            DruidUtil.close(connection,state,null);
        }
        return false;
    }
}

service层:

package com.wangjiawei.service;

import com.wangjiawei.dao.BaseAdminDao;
import com.wangjiawei.dao.imp.AdminDaoMysql;

import java.util.Date;

/**
 * 2 * @Author: 小王同学
 * 3 * @Date: 2020/10/2 9:52
 * 4
 */
public class AdminService {
    
    

    private static BaseAdminDao dao = new AdminDaoMysql();

    /**
     * 更新登陆时间与ip
     * @param username
     * @param date
     * @param ip
     */
    public static void updateLoginTimeAndIp(String username, Date date, String ip){
    
    
        dao.updateLoginTime(username, date, ip);
    }

    /**
     * 登录
     * @param username
     * @param password
     * @return true:成功,false:失败
     */
    public static boolean login(String username, String password){
    
    
        return dao.login(username, password);
    }
}

6 管理员登录前后端交互

6.1 登录

前端页面login.html:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <link rel="stylesheet" href="assets/css/layui.css">
    <link rel="stylesheet" href="assets/css/login.css">
    <link rel="icon" href="/favicon.ico">
    <title>快递e栈管理后台</title>
</head>
<body class="login-wrap">
    <div class="login-container">
       <h3>快递e栈后台管理</h3>
        <form class="login-form" action="index.html">
            <div class="input-group">
                <input type="text" id="username" class="input-field">
                <label for="username" class="input-label">
                    <span class="label-title">用户名</span>
                </label>
            </div>
            <div class="input-group">
                <input type="password" id="password" class="input-field">
                <label for="password" class="input-label">
                    <span class="label-title">密码</span>
                </label>
            </div>
            <button type="button" class="login-button">登录<i class="ai ai-enter"></i></button>
        </form>
    </div>
</body>
<script src="assets/layui.js"></script>
<script src="js/index.js" data-main="login"></script>
<script src="js/login.js" data-main="login"></script>
<script src="../qrcode/jquery2.1.4.js"></script>
<script src="../layer/layer.js"></script>
<script>
    $(function () {
     
     
        $(".login-button").click(function () {
     
     
            var username = $("#username").val();
            var password = $("#password").val();

            if(username == null || password == null || username == "" || password == ""){
     
     
                alert("用户名或密码不能为空");
           }else{
     
     
                // 先转圈(使用layer弹出load,提示加载中)
                var windowId = layer.load();
                // ajax与服务器交互
                $.post("login.do", {
     
     username:username, password:password}, function (data) {
     
     
                    // 关闭load窗口
                    layer.close(windowId);
                    // 将服务器回复的结果进行显示
                    layer.msg(data.result);
                    if (data.status == 0){
     
     
                        // 跳转到主页
                        location.assign("index.html");
                    }

                }, "JSON");
            }
        });
    })
</script>
</html>

编写管理员登录的controller:

package com.wangjiawei.controller;

import com.wangjiawei.bean.Message;
import com.wangjiawei.mvc.ResponseBody;
import com.wangjiawei.service.AdminService;
import com.wangjiawei.util.JSONUtil;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;

/**
 * 2 * @Author: 小王同学
 * 3 * @Date: 2020/10/2 10:28
 * 4
 */
public class AdminController {
    
    

    @ResponseBody("/admin/login.do")
    public String login(HttpServletRequest request, HttpServletResponse response){
    
    
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        boolean result = AdminService.login(username, password);
        // 准备不同的返回数据
        Message msg = null;
        if (result){
    
    
            // {status:0, result:"登录成功"}
            msg = new Message(0, "登录成功");
            // 登录时间和ip的更新
            Date date = new Date();
            String ip = request.getRemoteAddr();
            AdminService.updateLoginTimeAndIp(username, date, ip);
        }else {
    
    
            // {status:-1, result:"登录失败"}
            msg = new Message(-1, "登录失败");
        }
        String json = JSONUtil.toJSON(msg);
        return json;
    }
}

为了不显示乱码,定义过滤器设置编码:

package com.wangjiawei.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

/**
 * 2 * @Author: 小王同学
 * 3 * @Date: 2020/10/2 10:50
 * 4
 */
@WebFilter("*.do")
public class CharSetFilter implements Filter {
    
    
    public void destroy() {
    
    
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
    
    
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/json;charset=utf-8");
        resp.setCharacterEncoding("utf-8");
        chain.doFilter(req, resp);
    }

    public void init(FilterConfig config) throws ServletException {
    
    

    }

}

6.2 显示当前用户姓名(以主页面为例)

AdminController中添加获取姓名方法:

@ResponseBody("/admin/getName.do")
public String getName(HttpServletRequest request, HttpServletResponse response){
    
    
    String userName = UserUtil.getUserName(request.getSession());
    Message msg = new Message();
    msg.setStatus(0);
    msg.setResult("查询成功");
    msg.setData(userName);
    String json = JSONUtil.toJSON(msg);
    return json;
}

index.html部分:

$.post("/admin/getName.do",{
    
    },function (data) {
    
    
    // {
    
    
    //     "status": 0,
    //     "result": "查询成功",
    //     "data": "admin"
    // }
    $("#adminName").text(data.data);
});

6.3 退出登录(以主页面为例)

AdminController中添加退出登录方法:

@ResponseBody("/admin/logout.do")
public String logout(HttpServletRequest request, HttpServletResponse response){
    
    
    HttpSession session = request.getSession();
    session.removeAttribute("adminUserName");
    Message msg = new Message();
    msg.setStatus(0);
    msg.setResult("退出成功");
    String json = JSONUtil.toJSON(msg);
    return json;
}

index.html完整代码:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <link rel="stylesheet" href="assets/css/layui.css">
    <link rel="stylesheet" href="assets/css/admin.css">
    <link rel="icon" href="/favicon.ico">
    <title>快递e栈管理后台</title>
</head>
<body class="layui-layout-body">
    <div class="layui-layout layui-layout-admin">
        <div class="layui-header custom-header">
            
            <ul class="layui-nav layui-layout-left">
                <li class="layui-nav-item slide-sidebar" lay-unselect>
                    <a href="javascript:;" class="icon-font"><i class="ai ai-menufold"></i></a>
                </li>
            </ul>

            <ul class="layui-nav layui-layout-right">
                <li class="layui-nav-item">
                    <a><span id="adminName">aaaaaaa</span></a>
                    <dl class="layui-nav-child">
                        <dd><a href="#">帮助中心</a></dd>
                        <dd><a id="logout" href="login.html">退出</a></dd>
                    </dl>
                </li>
            </ul>
        </div>

        <div class="layui-side custom-admin">
            <div class="layui-side-scroll">

                <div class="custom-logo">
                    <img src="assets/images/logo.gif" alt=""/>
                    <h1>快递e栈</h1>
                </div>
                <ul id="Nav" class="layui-nav layui-nav-tree">
                    <li class="layui-nav-item">
                        <a href="javascript:;">
                            <i class="layui-icon">&#xe68e;</i>
                            <em>主页</em>
                        </a>
                        <dl class="layui-nav-child">
                            <dd><a href="views/console.html"><i class="layui-icon">&#xe665;</i> 控制台</a></dd>
                        </dl>
                    </li>
                    <li class="layui-nav-item">
                        <a href="javascript:;">
                            <i class="layui-icon">&#xe664;</i>
                            <em>快递员管理</em>
                        </a>
                        <dl class="layui-nav-child">
                            <dd><a href="views/courier/list.html"><i class="layui-icon">&#xe60a;</i> 快递员列表</a></dd>
                            <dd><a href="views/courier/add.html"><i class="layui-icon">&#xe654;</i> 快递员录入</a></dd>
                            <dd><a href="views/courier/update.html"><i class="layui-icon">&#xe642;</i> 快递员修改</a></dd>
                            <dd><a href="views/courier/delete.html"><i class="layui-icon">&#xe640;</i> 快递员删除</a></dd>
                        </dl>
                    </li>
                    <li class="layui-nav-item">
                        <a href="javascript:;">
                            <i class="layui-icon">&#xe857;</i>
                            <em>快件管理</em>
                        </a>
                        <dl class="layui-nav-child">
                            <dd><a href="views/express/list.html"><i class="layui-icon">&#xe60a;</i> 快件列表</a></dd>
                            <dd><a href="views/express/add.html"><i class="layui-icon">&#xe654;</i> 快件录入</a></dd>
                            <dd><a href="views/express/update.html"><i class="layui-icon">&#xe642;</i> 快件修改</a></dd>
                            <dd><a href="views/express/delete.html"><i class="layui-icon">&#xe640;</i> 快件删除</a></dd>
                        </dl>
                    </li>
                     <li class="layui-nav-item">
                        <a href="javascript:;">
                            <i class="layui-icon">&#xe770;</i>
                            <em>用户管理</em>
                        </a>
                        <dl class="layui-nav-child">
                            <dd><a href="views/user/list.html"><i class="layui-icon">&#xe60a;</i> 用户列表</a></dd>
                            <dd><a href="views/user/add.html"><i class="layui-icon">&#xe654;</i> 用户增加</a></dd>
                            <dd><a href="views/user/update.html"><i class="layui-icon">&#xe642;</i> 用户修改</a></dd>
                            <dd><a href="views/user/delete.html"><i class="layui-icon">&#xe640;</i> 用户删除</a></dd>
                        </dl>
                    </li>
                </ul>

            </div>
        </div>

        <div class="layui-body">
             <div class="layui-tab app-container" lay-allowClose="true" lay-filter="tabs">
                <ul id="appTabs" class="layui-tab-title custom-tab"></ul>
                <div id="appTabPage" class="layui-tab-content"></div>
            </div>
        </div>

        <div class="layui-footer">
            <p>©2020 <a href="http://www.itdage.com/" target="_blank">王家尉版权声明</a></p>
        </div>

        <div class="mobile-mask"></div>
    </div>
    <script src="assets/layui.js"></script>
    <script src="js/index.js" data-main="home"></script>
    <script src="/qrcode/jquery2.1.4.js"></script>
    <script>
        $(function () {
     
     
            $.post("/admin/getName.do",{
     
     },function (data) {
     
     
                // {
     
     
                //     "status": 0,
                //     "result": "查询成功",
                //     "data": "admin"
                // }
                $("#adminName").text(data.data);
            });

            $("#logout").click(function () {
     
     
                var windowId = layer.load();
                $.post("/admin/logout.do",{
     
     },function (data) {
     
     
                    layer.msg(data.result);
                    layer.close(windowId);
                    location.href = "/admin/login.html";
                })
            });
        });
    </script>

</body>
</html>

7 流程与快递表格创建

7.1 编写流程

  1. 管理员登录
  2. 快递管理
  • 快递列表
    • 分页查询的列表
  • 新增快递
    • 用户输入内容,后台接收参数,向数据库存储
  • 删除快递
    • 用户输入快递单号查询快递信息
    • 浏览快递信息的最后,可以点击删除按钮,删除快递
  • 修改快递
    • 用户输入快递单号查询到快递信息
    • 浏览(可修改)快递信息的最后,可以点击确认按钮,确认修改快递
  1. 用户管理
  • 用户列表
  • 新增用户
  • 删除用户
  • 修改用户
  1. 快递员管理
  • 快递员列表
  • 新增快递员
  • 删除快递员
  • 修改快递员
  1. 控制台显示

7.2 编写步骤

  • 创建数据库表格
  • 编写DAO
  • 编写service
  • 编写controller
  • 前后端交互
    • 前端发起ajax→DispatcherServlet→Controller→Service→DAO→数据库

前后端交互标准流程:

  • 前端发起ajax
$("按钮选择器").click(function(){
    
    
            //1.    先使用layer,弹出load(提示加载中...)
            var windowId = layer.load();
            //2.    ajax与服务器交互
            $.post("服务器地址",参数JSON,function(data){
    
    
                //3.    关闭load窗口
                layer.close(windowId);
                //4.    将服务器回复的结果进行显示
                layer.msg(data.result);
            },"JSON");
        });
  • 编写Controller,用于处理ajax的请求
    • 在Controller中调用service处理
    • 处理完毕, 根据service返回的结果,给ajax返回

7.3 数据库创建

7.3.1 快递

CREATE TABLE Express(
	id int PRIMARY KEY auto_increment,
	number VARCHAR(64) UNIQUE,
	username VARCHAR(32),
	userphone VARCHAR(32),
	company VARCHAR(32),
	code VARCHAR(32) UNIQUE,
	intime TIMESTAMP,
	outtime TIMESTAMP,
	status int,
	sysPhone VARCHAR(32)
);

7.3.2 快递员

create table courier(
	id int primary key auto_increment,
	courierName varchar(32),
	courierPhone varchar(32),
	courierIdNumber varchar(32),
	courierPassword varchar(32),
	courierSendNumber int,
	enrollTime TIMESTAMP,
	loginTime TIMESTAMP
);

7.3.3 用户

create table user(
	id int primary key auto_increment,
	userName varchar(32),
	userPhone varchar(32),
	userIdNumber varchar(32),
	userPassword varchar(32),
	enrollTime timestamp,
	loginTime timestamp
);

7.4 bean

7.4.1 快递类.

package com.wangjiawei.bean;

import java.sql.Timestamp;
import java.util.Objects;

/**
 * 2 * @Author: 小王同学
 * 3 * @Date: 2020/10/2 18:55
 * 4
 */
public class Express {
    
    
    private int id;
    private String number;
    private String username;
    private String userPhone;
    private String company;
    private String code;
    private Timestamp inTime;
    private Timestamp outTime;
    private int status;
    private String sysPhone;

    /* getter setter toString hash 构造函数略 */
}

7.4.2 快递员类

public class Courier {
    
    
    private int id;
    private String courierName;
    private String courierPhone;
    private String courierIdNumber;
    private String courierPassword;
    private String courierSendNumber;
    private Timestamp enrollTime;
    private Timestamp loginTime;
    
    /* getter setter toString hash 构造函数略 */
}

7.4.3 用户类

public class User {
    
    
    private int id;
    private String userName;
    private String userPhone;
    private String userIdNumber;
    private String userPassword;
    private Timestamp enrollTime;
    private Timestamp loginTime;
    
    /* getter setter toString hash 构造函数略 */
}

8 api设计

8.1 console 部分(控制台)

1. 获取控制台所需的快递数据
请求地址:
  express/console.do
参数列表:
  无
返回格式示例:

{
    
    
    status:0,
    result:"获取成功",
    data:[
        {
    
     // 全部快递
            size:1000, // 总件数
            day:100    // 当日新增
        },{
    
     // 待取件快递
            size:500,  // 待取件数
           day:100    // 今日新增
        }
    ]
}

8.2 快递管理

1. 快件列表(分页)
请求地址:
  express/findAll.do
参数列表:
  1. limit:
    a. 值:0,开启分页(默认)
    b. 值:1,查询所有
  2. offset:
    值:数字,sql语句的起始索引
  3. pageNumber:
    值:数字,表示每页获取的快递数量

2. 根据单号查询快递信息
请求地址:express/findByNumber.do
参数列表:
  1. number:快递单号

3. 根据取件码查询快递信息
请求地址:express/findByCode.do
参数列表:
  1. code:取件码

4. 根据用户的手机号,查询快递信息
请求地址:express/findByUserPhone.do
参数列表:
  1. userPhone:手机号码
  2. status:
    值:0表示查询待取件的快递(默认)
    值:1表示查询已取件的快递
    值:2表示查询用户的所有快递

5. 根据录入人的手机号,查询快递信息(快递员/柜子的历史记录)
请求地址:express/findBySysPhone.do
参数列表:
  1. sysPhone:手机号码

6. 进行快递数量的排序查询(用户表)
请求地址:express/lazyboard.do
参数列表:
  1. type:
    值:0,表示查询总排名
    值:1,表示查询年排名
    值:2,表示查询月排名

7. 快件录入
请求地址:
  express/insert.do
参数列表:
  1. number:快递单号
  2. company:快递公司
  3. username:收件人姓名
  4. phoneNumber:收件人手机号码

8. 修改快递信息
请求地址:express/update.do
参数列表:
  1. id:要修改的快递id
  2. number:新的快递单号
  3. company:新的快递公司
  4. username:新的收货人姓名
  5. userPhone:新的收件人手机号码,(手机号码更新,重新生成取件码,并发送短信)
  6. status:新的快递的状态

9. 根据id删除快递信息
请求地址:express/delete.do
参数列表:
  1. id: 要删除的快递的id

10. 确认取件
请求地址:express/updateStatus.do
参数列表:
  number:要更改状态为已取件的快递单号

9 dao接口编写与具体实现

9.1 快递操作相关的dao

9.1.1 sql语句书写

/**
 * 查询全部快递(总数+新增),待取件快递(总数+新增)
  */
public static final String SQL_CONSOLE = "SELECT " +
        "COUNT(ID) data1_size," +
        "COUNT(TO_DAYS(INTIME)=TO_DAYS(NOW()) OR NULL) data1_day," +
        "COUNT(STATUS=0 OR NULL) data2_size," +
        "COUNT(TO_DAYS(INTIME)=TO_DAYS(NOW()) AND STATUS=0 OR NULL) data2_day" +
        " FROM EXPRESS";
/**
 * 查询数据库中所有的快递信息
 */
public static final String SQL_FIND_ALL = "SELECT * FROM EXPRESS";
/**
 * 分页查询数据库中所有快递信息
 */
public static final String SQL_FIND_LIMIT = "SELECT * FROM EXPRESS LIMIT ?,?";
/**
 * 通过取件码查询快递信息
 */
public static final String SQL_FIND_BY_CODE = "SELECT * FROM EXPRESS WHERE CODE=?";
/**
 * 通过快递单号查询快递信息
 */
public static final String SQL_FIND__BY_NUMBER = "SELECT * FROM EXPRESS WHERE NUMBER=?";
/**
 * 通过录入手机号查询快递信息
 */
public static final String SQL_FIND_BY_SYSPHONE = "SELECT * FROM EXPRESS WHERE SYSPHONE=?";
/**
 * 通过用户手机号查询快递信息
 */
public static final String SQL_FIND_BY_USERPHONE = "SELECT * FROM EXPRESS WHERE USERPHONE=?";
/**
 * 录入快递
 */
public static final String SQL_INSERT = "INSERT INTO EXPRESS(NUMBER,USERNAME,USERPHONE,COMPANY,CODE,INTIME,STATUS,SYSPHONE) VALUES(?,?,?,?,?,NOW(),0,?)";
/**
 * 修改快递
 */
public static final String SQL_UPDATE = "UPDATE EXPRESS SET NUMBER=?,USERNAME=?,COMPANY=?,STATUS=? WHERE ID=?";
/**
 * 快递状态码修改(取件)
 */
public static final String SQL_UPDATE_STATUS = "UPDATE EXPRESS SET STATUS=1,OUTTIME=NOW(),CODE=NULL WHERE CODE=?";
/**
 * 快递的删除
 */
public static final String SQL_DELETE = "DELETE FROM EXPRESS WHERE ID=?";

9.1.2 快递相关的dao

步骤:

  1. 获取数据库连接
  2. 预编译sql
  3. 填充参数(可选)
  4. 执行sql
  5. 获取执行结果
  6. 资源释放

创建自定义异常:
  用于记录插入快递数据时因取件码重复而报的异常

package com.wangjiawei.exception;

/**
 * 2 * @Author: 小王同学
 * 3 * @Date: 2020/10/4 11:32
 * 4
 */
public class DuplicateCodeException extends Exception{
    
    

    /**
     * Constructs a new exception with {@code null} as its detail message.
     * The cause is not initialized, and may subsequently be initialized by a
     * call to {@link #initCause}.
     */
    public DuplicateCodeException() {
    
    
    }

    /**
     * Constructs a new exception with the specified detail message.  The
     * cause is not initialized, and may subsequently be initialized by
     * a call to {@link #initCause}.
     *
     * @param message the detail message. The detail message is saved for
     *                later retrieval by the {@link #getMessage()} method.
     */
    public DuplicateCodeException(String message) {
    
    
        super(message);
    }
}

dao接口定义:

package com.wangjiawei.dao;

import com.wangjiawei.bean.Express;
import com.wangjiawei.exception.DuplicateCodeException;

import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;

/**
 * 2 * @Author: 小王同学
 * 3 * @Date: 2020/10/3 13:38
 * 4
 */
public interface BaseExpressDao {
    
    

    /**
     * 用于查询数据库中的全部快递(总数,当日新增)
     * 待取件快递(总数,当日新增)
     * @return [{size:总数, day:新增},{size:总数, day:新增}]
     */
    List<Map<String, Integer>> console();

    /**
     * 查询所有快递
     * @param limit 是否分页的标记,true:分页,false:查询所有
     * @param offset sql语句的起始索引
     * @param pageNumber 每一页查询的数量
     * @return 快递的集合
     */
    List<Express> findAll(boolean limit, int offset, int pageNumber);

    /**
     * 根据快递单号查询快递信息
     * @param number 单号
     * @return 查询的快递信息,单号不存在时返回null
     */
    Express findByNumber(String number);

    /**
     * 根据快递单号查询快递信息
     * @param code 取件码
     * @return 查询的快递信息,取件码不存在时返回null
     */
    Express findByCode(String code);

    /**
     * 根据用户手机号查询所有快递
     * @param userPhone 手机号
     * @return 查询的快递信息,手机号不存在时返回null
     */
    List<Express> findByUserPhone(String userPhone);

    /**
     * 根据录入人手机号查询录入的所有记录
     * @param sysPhone 手机号
     * @return 查询的快递信息,手机号不存在时返回null
     */
    List<Express> findBySysPhone(String sysPhone);

    /**
     * 快递的录入
     * @param e 要录入的对象
     * @return 录入的结果
     */
    boolean insert(Express e) throws DuplicateCodeException;

    /**
     * 快递的修改
     * @param id 要修改的快递id
     * @param newExpress 新的快递对象(number, company, username, userPhone)
     * @return 修改的结果
     */
    boolean update(int id, Express newExpress);

    /**
     * 更改快递状态为1,表示取件完成
     * @param number 要修改的快递单号
     * @return 修改的结果
     */
    boolean updateStatus(String code);

    /**
     * 根据id,删除单个快递信息
     * @param id 要删除的快递信息
     * @return 删除结果
     */
    boolean delete(int id);
}

dao完整实现:

package com.wangjiawei.dao.imp;

import com.wangjiawei.bean.Express;
import com.wangjiawei.dao.BaseExpressDao;
import com.wangjiawei.exception.DuplicateCodeException;
import com.wangjiawei.util.DruidUtil;

import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 2 * @Author: 小王同学
 * 3 * @Date: 2020/10/3 14:16
 * 4
 */
public class ExpressDaoMysql implements BaseExpressDao {
    
    
    /**
     * 查询全部快递(总数+新增),待取件快递(总数+新增)
      */
    public static final String SQL_CONSOLE = "SELECT " +
            "COUNT(ID) data1_size," +
            "COUNT(TO_DAYS(INTIME)=TO_DAYS(NOW()) OR NULL) data1_day," +
            "COUNT(STATUS=0 OR NULL) data2_size," +
            "COUNT(TO_DAYS(INTIME)=TO_DAYS(NOW()) AND STATUS=0 OR NULL) data2_day" +
            " FROM EXPRESS";
    /**
     * 查询数据库中所有的快递信息
     */
    public static final String SQL_FIND_ALL = "SELECT * FROM EXPRESS";
    /**
     * 分页查询数据库中所有快递信息
     */
    public static final String SQL_FIND_LIMIT = "SELECT * FROM EXPRESS LIMIT ?,?";
    /**
     * 通过取件码查询快递信息
     */
    public static final String SQL_FIND_BY_CODE = "SELECT * FROM EXPRESS WHERE CODE=?";
    /**
     * 通过快递单号查询快递信息
     */
    public static final String SQL_FIND__BY_NUMBER = "SELECT * FROM EXPRESS WHERE NUMBER=?";
    /**
     * 通过录入手机号查询快递信息
     */
    public static final String SQL_FIND_BY_SYSPHONE = "SELECT * FROM EXPRESS WHERE SYSPHONE=?";
    /**
     * 通过用户手机号查询快递信息
     */
    public static final String SQL_FIND_BY_USERPHONE = "SELECT * FROM EXPRESS WHERE USERPHONE=?";
    /**
     * 录入快递
     */
    public static final String SQL_INSERT = "INSERT INTO EXPRESS(NUMBER,USERNAME,USERPHONE,COMPANY,CODE,INTIME,STATUS,SYSPHONE) VALUES(?,?,?,?,?,NOW(),0,?)";
    /**
     * 修改快递
     */
    public static final String SQL_UPDATE = "UPDATE EXPRESS SET NUMBER=?,USERNAME=?,COMPANY=?,STATUS=? WHERE ID=?";
    /**
     * 快递状态码修改(取件)
     */
    public static final String SQL_UPDATE_STATUS = "UPDATE EXPRESS SET STATUS=1,OUTTIME=NOW(),CODE=NULL WHERE CODE=?";
    /**
     * 快递的删除
     */
    public static final String SQL_DELETE = "DELETE FROM EXPRESS WHERE ID=?";

    /**
     * 用于查询数据库中的全部快递(总数,当日新增)
     * 待取件快递(总数,当日新增)
     *
     * @return [{size:总数, day:新增},{size:总数, day:新增}]
     */
    @Override
    public List<Map<String, Integer>> console() {
    
    
        ArrayList<Map<String, Integer>> data = new ArrayList<>();
        Connection conn = DruidUtil.getConnection();
        PreparedStatement state = null;
        ResultSet result = null;

        try {
    
    
            state = conn.prepareStatement(SQL_CONSOLE);
            result = state.executeQuery();
            if (result.next()){
    
    
                int data1_size = result.getInt("data1_size");
                int data1_day = result.getInt("data1_day");

                int data2_size = result.getInt("data2_size");
                int data2_day = result.getInt("data2_day");

                Map<String,Integer> data1 = new HashMap<>();
                data1.put("data1_size",data1_size);
                data1.put("data1_day",data1_day);

                Map<String,Integer> data2 = new HashMap<>();
                data2.put("data2_size",data2_size);
                data2.put("data2_day",data2_day);

                data.add(data1);
                data.add(data2);

            }
        }catch (SQLException throwables){
    
    
            throwables.printStackTrace();
        }finally {
    
    
            DruidUtil.close(conn,state,result);
        }

        return data;
    }

    /**
     * 查询所有快递
     *
     * @param limit      是否分页的标记,true:分页,false:查询所有
     * @param offset     sql语句的起始索引
     * @param pageNumber 每一页查询的数量
     * @return 快递的集合
     */
    @Override
    public List<Express> findAll(boolean limit, int offset, int pageNumber) {
    
    
        ArrayList<Express> data = new ArrayList<>();
        Connection conn = DruidUtil.getConnection();
        PreparedStatement state = null;
        ResultSet result = null;

        try {
    
    
            if (limit){
    
    
                state = conn.prepareStatement(SQL_FIND_LIMIT);
                state.setInt(1,offset);
                state.setInt(2,pageNumber);
            }else {
    
    
                state = conn.prepareStatement(SQL_FIND_ALL);
            }
            result = state.executeQuery();

            while (result.next()){
    
    
                int id = result.getInt("id");
                String number = result.getString("number");
                String username = result.getString("username");
                String userPhone = result.getString("userPhone");
                String company = result.getString("company");
                String code = result.getString("code");
                Timestamp inTime = result.getTimestamp("inTime");
                Timestamp outTime = result.getTimestamp("outTime");
                int status = result.getInt("status");
                String sysPhone = result.getString("sysPhone");
                Express e = new Express(id, number, username, userPhone, company, code, inTime, outTime, status, sysPhone);
                data.add(e);
            }

        }catch (SQLException throwables){
    
    
            throwables.printStackTrace();
        }finally {
    
    
            DruidUtil.close(conn,state,result);
        }
        return data;
    }

    /**
     * 根据快递单号查询快递信息
     *
     * @param number 单号
     * @return 查询的快递信息,单号不存在时返回null
     */
    @Override
    public Express findByNumber(String number) {
    
    
        Connection conn = DruidUtil.getConnection();
        PreparedStatement state = null;
        ResultSet result = null;

        try {
    
    
            state = conn.prepareStatement(SQL_FIND__BY_NUMBER);
            state.setString(1, number);
            result = state.executeQuery();

            if (result.next()){
    
    
                int id = result.getInt("id");
                String username = result.getString("username");
                String userPhone = result.getString("userPhone");
                String company = result.getString("company");
                String code = result.getString("code");
                Timestamp inTime = result.getTimestamp("inTime");
                Timestamp outTime = result.getTimestamp("outTime");
                int status = result.getInt("status");
                String sysPhone = result.getString("sysPhone");
                Express e = new Express(id, number, username, userPhone, company, code, inTime, outTime, status, sysPhone);
                return e;
            }
        }catch (SQLException throwables){
    
    
            throwables.printStackTrace();
        }finally {
    
    
            DruidUtil.close(conn,state,result);
        }
        return null;
    }

    /**
     * 根据快递单号查询快递信息
     *
     * @param code 取件码
     * @return 查询的快递信息,取件码不存在时返回null
     */
    @Override
    public Express findByCode(String code) {
    
    
        Connection conn = DruidUtil.getConnection();
        PreparedStatement state = null;
        ResultSet result = null;

        try {
    
    
            state = conn.prepareStatement(SQL_FIND_BY_CODE);
            state.setString(1, code);
            result = state.executeQuery();

            if (result.next()){
    
    
                int id = result.getInt("id");
                String number = result.getString("number");
                String username = result.getString("username");
                String userPhone = result.getString("userPhone");
                String company = result.getString("company");
                Timestamp inTime = result.getTimestamp("inTime");
                Timestamp outTime = result.getTimestamp("outTime");
                int status = result.getInt("status");
                String sysPhone = result.getString("sysPhone");
                Express e = new Express(id, number, username, userPhone, company, code, inTime, outTime, status, sysPhone);
                return e;
            }
        }catch (SQLException throwables){
    
    
            throwables.printStackTrace();
        }finally {
    
    
            DruidUtil.close(conn,state,result);
        }
        return null;
    }

    /**
     * 根据用户手机号查询所有快递
     *
     * @param userPhone 手机号
     * @return 查询的快递信息,手机号不存在时返回null
     */
    @Override
    public List<Express> findByUserPhone(String userPhone) {
    
    
        ArrayList<Express> data = new ArrayList<>();
        Connection conn = DruidUtil.getConnection();
        PreparedStatement state = null;
        ResultSet result = null;

        try {
    
    
            state = conn.prepareStatement(SQL_FIND_BY_USERPHONE);
            state.setString(1,userPhone);
            result = state.executeQuery();
            while (result.next()){
    
    
                int id = result.getInt("id");
                String number = result.getString("number");
                String username = result.getString("username");
                String company = result.getString("company");
                String code = result.getString("code");
                Timestamp inTime = result.getTimestamp("inTime");
                Timestamp outTime = result.getTimestamp("outTime");
                int status = result.getInt("status");
                String sysPhone = result.getString("sysPhone");
                Express e = new Express(id, number, username, userPhone, company, code, inTime, outTime, status, sysPhone);
                data.add(e);
            }
        }catch (SQLException throwables){
    
    
            throwables.printStackTrace();
        }finally {
    
    
            DruidUtil.close(conn,state,result);
        }
        return data;
    }

    /**
     * 根据录入人手机号查询录入的所有记录
     *
     * @param sysPhone 手机号
     * @return 查询的快递信息,手机号不存在时返回null
     */
    @Override
    public List<Express> findBySysPhone(String sysPhone) {
    
    
        ArrayList<Express> data = new ArrayList<>();
        Connection conn = DruidUtil.getConnection();
        PreparedStatement state = null;
        ResultSet result = null;

        try {
    
    
            state = conn.prepareStatement(SQL_FIND_BY_SYSPHONE);
            state.setString(1,sysPhone);
            result = state.executeQuery();

            while (result.next()){
    
    
                int id = result.getInt("id");
                String number = result.getString("number");
                String username = result.getString("username");
                String userPhone = result.getString("userPhone");
                String company = result.getString("company");
                String code = result.getString("code");
                Timestamp inTime = result.getTimestamp("inTime");
                Timestamp outTime = result.getTimestamp("outTime");
                int status = result.getInt("status");
                Express e = new Express(id, number, username, userPhone, company, code, inTime, outTime, status, sysPhone);
                data.add(e);
            }
        }catch (SQLException throwables){
    
    
            throwables.printStackTrace();
        }finally {
    
    
            DruidUtil.close(conn,state,result);
        }
        return data;
    }

    /**
     * 快递的录入
     * INSERT INTO EXPRESS(NUMBER,USERNAME,USERPHONE,COMPANY,CODE,INTIME,STATUS,SYSPHONE) VALUES(?,?,?,?,?,NOW(),0,?)
     * @param e 要录入的对象
     * @return 录入的结果
     */
    @Override
    public boolean insert(Express e) throws DuplicateCodeException{
    
    

        Connection conn = DruidUtil.getConnection();
        PreparedStatement state = null;
        try {
    
    
            state = conn.prepareStatement(SQL_INSERT);

            state.setString(1,e.getNumber());
            state.setString(2,e.getUsername());
            state.setString(3,e.getUserPhone());
            state.setString(4,e.getCompany());
            state.setString(5,e.getCode());
            state.setString(6,e.getSysPhone());

            return (state.executeUpdate() > 0);
        } catch (SQLException e1) {
    
    
            /*throwables.printStackTrace();*/
            /*System.out.println(e1.getMessage());*/
            if (e1.getMessage().endsWith("for key 'code'")){
    
    
                // 是因为取件码重复而出现了异常
                DuplicateCodeException e2 = new DuplicateCodeException(e1.getMessage());
                throw e2;
            }else {
    
    
                e1.printStackTrace();
            }
        }finally {
    
    
            DruidUtil.close(conn,state,null);
        }

        return false;
    }

    /**
     * 快递的修改
     * UPDATE EXPRESS SET NUMBER=?,USERNAME=?,COMPANY=?,STATUS=? WHERE ID=?
     * @param id         要修改的快递id
     * @param newExpress 新的快递对象(number, company, username, userPhone)
     * @return 修改的结果
     */
    @Override
    public boolean update(int id, Express newExpress) {
    
    
        Connection conn = DruidUtil.getConnection();
        PreparedStatement state = null;

        try {
    
    
            state = conn.prepareStatement(SQL_UPDATE);
            state.setString(1,newExpress.getNumber());
            state.setString(2,newExpress.getUsername());
            state.setString(3,newExpress.getCompany());
            state.setInt(4,newExpress.getStatus());
            state.setInt(5,id);

            return state.executeUpdate() > 0;
        } catch (SQLException throwables) {
    
    
            throwables.printStackTrace();
        }finally {
    
    
            DruidUtil.close(conn, state, null);
        }
        return false;
    }

    /**
     * 更改快递状态为1,表示取件完成
     * UPDATE EXPRESS SET STATUS=1 WHERE CODE=?
     * @param code 要取件的取件码
     * @return 修改的结果
     */
    @Override
    public boolean updateStatus(String code) {
    
    
        Connection conn = DruidUtil.getConnection();
        PreparedStatement state = null;

        try {
    
    
            state = conn.prepareStatement(SQL_UPDATE_STATUS);
            state.setString(1,code);
            return state.executeUpdate() > 0;
        } catch (SQLException throwables) {
    
    
            throwables.printStackTrace();
        }finally {
    
    
            DruidUtil.close(conn, state, null);
        }
        return false;
    }

    /**
     * 根据id,删除单个快递信息
     *
     * @param id 要删除的快递信息
     * @return 删除结果
     */
    @Override
    public boolean delete(int id) {
    
    
        Connection conn = DruidUtil.getConnection();
        PreparedStatement state = null;

        try {
    
    
            state = conn.prepareStatement(SQL_DELETE);
            state.setInt(1,id);
            return state.executeUpdate() > 0;
        } catch (SQLException throwables) {
    
    
            throwables.printStackTrace();
        }finally {
    
    
            DruidUtil.close(conn, state, null);
        }
        return false;
    }
}

9.2 快递员操作相关的dao

9.2.1 sql语句编写

/**
 * 查询所有快递员(总数 + 新增)
 */
public static final String SQL_CONSOLE = "SELECT " +
        "COUNT(ID) data_size," +
        "COUNT(TO_DAYS(ENROLLTIME)=TO_DAYS(NOW()) OR NULL) data_day " +
        " FROM COURIER";
/**
 * 查询所有快递员
 */
public static final String SQL_FIND_ALL = "SELECT * FROM COURIER";
/**
 * 分页查询数据库中所有快递员
 */
public static final String SQL_FIND_LIMIT = "SELECT * FROM COURIER LIMIT ?,?";
/**
 * 根据id查快递员
 */
public static final String SQL_FIND_BY_ID = "SELECT * FROM COURIER WHERE ID=?";
/**
 * 根据手机号查快递员
 */
public static final String SQL_FIND_BY_PHONE = "SELECT * FROM COURIER WHERE COURIERPHONE=?";
/**
 * 根据姓名查快递员
 */
public static final String SQL_FIND_BY_NAME = "SELECT * FROM COURIER WHERE COURIERNAME=?";
/**
 * 根据身份证号查快递员
 */
public static final String SQL_FIND_BY_ID_NUMBER = "SELECT * FROM COURIER WHERE COURIERIDNUMBER=?";

9.2.2 快递员dao具体实现

接口:

package com.wangjiawei.dao;

import com.wangjiawei.bean.Courier;
import com.wangjiawei.bean.Express;

import java.util.List;
import java.util.Map;

/**
 * 2 * @Author: 小王同学
 * 3 * @Date: 2020/10/8 10:43
 * 4
 */
public interface BaseCourierDao {

    /**
     * 用于查询数据库中的全部快递快递员(总数,当日新增)
     * 快递员(总数,当日新增)
     * @return [{size:总数, day:新增}]
     */
    List<Map<String, Integer>> console();

    /**
     * 查询所有快递员
     * @param limit 是否分页的标记,true:分页,false:查询所有
     * @param offset sql语句的起始索引
     * @param pageNumber 每一页查询的数量
     * @return 快递员的集合
     */
    List<Courier> findAll(boolean limit, int offset, int pageNumber);

    /**
     * 根据id查快递员
     * @param id
     * @return 查到的快递员,id不存在时返回null
     */
    Courier findById(int id);

    /**
     * 根据姓名查快递员
     * @param courierName 姓名
     * @return 查到的快递员,courierName不存在时返回null
     */
    Courier findByName(String courierName);

    /**
     * 根据手机号查快递员
     * @param courierPhone 手机号
     * @return 查到的快递员,courierPhone不存在时返回null
     */
    Courier findByPhone(String courierPhone);

    /**
     * 根据身份证号查快递员
     * @param courierIdNumber 身份证号
     * @return 查到的快递员,courierIdNumber不存在时返回null
     */
    Courier findByIdNumber(String courierIdNumber);

    /**
     * 快递员的录入
     * @param c 要录入的对象
     * @return 录入的结果
     */
    boolean insert(Courier c);

    /**
     * 快递员的修改
     * @param id 要修改的快递员id
     * @param newCourier 新的快递员对象
     * @return 修改的结果
     */
    boolean update(int id, Courier newCourier);

    /**
     * 派件数修改
     * @param id 快递员id
     * @param increment 新增的派件数
     * @return 是否修改成功
     */
    boolean updateSendNumber(int id, int increment);

    /**
     * 更新登陆时间
     * @param id
     * @return
     */
    boolean updateLoginTime(int id);

    /**
     * 根据id,删除单个快递员信息
     * @param id 要删除的快递员信息
     * @return 删除结果
     */
    boolean delete(int id);

}

实现类:

package com.wangjiawei.dao.imp;

import com.wangjiawei.bean.Courier;
import com.wangjiawei.bean.Express;
import com.wangjiawei.dao.BaseCourierDao;
import com.wangjiawei.exception.DuplicateCodeException;
import com.wangjiawei.util.DruidUtil;

import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 2 * @Author: 小王同学
 * 3 * @Date: 2020/10/8 10:54
 * 4
 */
public class CourierDaoMysql implements BaseCourierDao {
    
    

    /**
     * 查询所有快递员(总数 + 新增)
     */
    public static final String SQL_CONSOLE = "SELECT " +
            "COUNT(ID) data_size," +
            "COUNT(TO_DAYS(ENROLLTIME)=TO_DAYS(NOW()) OR NULL) data_day " +
            " FROM COURIER";
    /**
     * 查询所有快递员
     */
    public static final String SQL_FIND_ALL = "SELECT * FROM COURIER";
    /**
     * 分页查询数据库中所有快递员
     */
    public static final String SQL_FIND_LIMIT = "SELECT * FROM COURIER LIMIT ?,?";
    /**
     * 根据id查快递员
     */
    public static final String SQL_FIND_BY_ID = "SELECT * FROM COURIER WHERE ID=?";
    /**
     * 根据手机号查快递员
     */
    public static final String SQL_FIND_BY_PHONE = "SELECT * FROM COURIER WHERE COURIERPHONE=?";
    /**
     * 根据姓名查快递员
     */
    public static final String SQL_FIND_BY_NAME = "SELECT * FROM COURIER WHERE COURIERNAME=?";
    /**
     * 根据身份证号查快递员
     */
    public static final String SQL_FIND_BY_ID_NUMBER = "SELECT * FROM COURIER WHERE COURIERIDNUMBER=?";
    /**
     * 录入快递
     */
    public static final String SQL_INSERT = "INSERT INTO COURIER(COURIERNAME,COURIERPHONE,COURIERIDNUMBER,COURIERPASSWORD,COURIERSENDNUMBER,ENROLLTIME) VALUES(?,?,?,?,0,NOW())";
    /**
     * 修改快递员
     */
    public static final String SQL_UPDATE = "UPDATE COURIER SET COURIERNAME=?,COURIERPHONE=?,COURIERIDNUMBER=?,COURIERPASSWORD=? WHERE ID=?";
    /**
     * 修改快递员派件数
     */
    public static final String SQL_UPDATE_SEND_NUMBER = "UPDATE COURIER SET COURIERSENDNUMBER=COURIERSENDNUMBER+? WHERE ID=?";
    /**
     * 修改快递员登录时间
     */
    public static final String SQL_UPDATE_LOGIN_TIME = "UPDATE COURIER SET LOGINTIME=NOW() WHERE ID=?";
    /**
     * 快递员的删除
     */
    public static final String SQL_DELETE = "DELETE FROM COURIER WHERE ID=?";

    /**
     * 用于查询数据库中的全部快递快递员(总数,当日新增)
     * 快递员(总数,当日新增)
     *
     * @return [{size:总数, day:新增}]
     */
    @Override
    public List<Map<String, Integer>> console() {
    
    
        ArrayList<Map<String, Integer>> data = new ArrayList<>();
        Connection conn = DruidUtil.getConnection();
        PreparedStatement state = null;
        ResultSet result = null;
        try {
    
    
            state = conn.prepareStatement(SQL_CONSOLE);
            result = state.executeQuery();
            if (result.next()){
    
    
                int data_size = result.getInt("data_size");
                int data_day = result.getInt("data_day");
                Map<String,Integer> data1 = new HashMap<>();
                data1.put("data_size",data_size);
                data1.put("data_day",data_day);
                data.add(data1);
            }
        } catch (SQLException throwables) {
    
    
            throwables.printStackTrace();
        }finally {
    
    
            DruidUtil.close(conn,state,result);
        }
        return data;
    }

    /**
     * 查询所有快递员
     *
     * @param limit      是否分页的标记,true:分页,false:查询所有
     * @param offset     sql语句的起始索引
     * @param pageNumber 每一页查询的数量
     * @return 快递员的集合
     */
    @Override
    public List<Courier> findAll(boolean limit, int offset, int pageNumber) {
    
    
        ArrayList<Courier> data = new ArrayList<>();
        Connection conn = DruidUtil.getConnection();
        PreparedStatement state = null;
        ResultSet result = null;
        try {
    
    
            if (limit){
    
    
                state = conn.prepareStatement(SQL_FIND_LIMIT);
                state.setInt(1,offset);
                state.setInt(2,pageNumber);
            }else {
    
    
                state = conn.prepareStatement(SQL_FIND_ALL);
            }

            result = state.executeQuery();

            while (result.next()){
    
    
                int id = result.getInt("id");
                String courierName = result.getString("courierName");
                String courierPhone = result.getString("courierPhone");
                String courierIdNumber = result.getString("courierIdNumber");
                String courierPassword = result.getString("courierPassword");
                int courierSendNumber = result.getInt("courierSendNumber");
                Timestamp enrollTime = result.getTimestamp("enrollTime");
                Timestamp loginTime = result.getTimestamp("loginTime");

                Courier c = new Courier(id, courierName, courierPhone, courierIdNumber, courierPassword, courierSendNumber, enrollTime, loginTime);
                data.add(c);
            }
        }catch (SQLException throwables){
    
    
            throwables.printStackTrace();
        }finally {
    
    
            DruidUtil.close(conn,state,result);
        }
        return data;
    }

    /**
     * 根据id查快递员
     *
     * @param id
     * @return 查到的快递员,id不存在时返回null
     */
    @Override
    public Courier findById(int id) {
    
    
        ArrayList<Courier> data = new ArrayList<>();
        Connection conn = DruidUtil.getConnection();
        PreparedStatement state = null;
        ResultSet result = null;
        try {
    
    
            state = conn.prepareStatement(SQL_FIND_BY_ID);
            state.setInt(1, id);
            result = state.executeQuery();

            if (result.next()){
    
    
                String courierName = result.getString("courierName");
                String courierPhone = result.getString("courierPhone");
                String courierIdNumber = result.getString("courierIdNumber");
                String courierPassword = result.getString("courierPassword");
                int courierSendNumber = result.getInt("courierSendNumber");
                Timestamp enrollTime = result.getTimestamp("enrollTime");
                Timestamp loginTime = result.getTimestamp("loginTime");
                Courier c = new Courier(id, courierName, courierPhone, courierIdNumber, courierPassword, courierSendNumber, enrollTime, loginTime);
                return c;
            }
        }catch (SQLException throwables){
    
    
            throwables.printStackTrace();
        }finally {
    
    
            DruidUtil.close(conn,state,result);
        }
        return null;
    }

    /**
     * 根据姓名查快递员
     *
     * @param courierName 姓名
     * @return 查到的快递员,courierName不存在时返回null
     */
    @Override
    public Courier findByName(String courierName) {
    
    
        Connection conn = DruidUtil.getConnection();
        PreparedStatement state = null;
        ResultSet result = null;
        try {
    
    
            state = conn.prepareStatement(SQL_FIND_BY_NAME);
            state.setString(1, courierName);
            result = state.executeQuery();

            if (result.next()){
    
    
                int id = result.getInt("id");
                String courierPhone = result.getString("courierPhone");
                String courierIdNumber = result.getString("courierIdNumber");
                String courierPassword = result.getString("courierPassword");
                int courierSendNumber = result.getInt("courierSendNumber");
                Timestamp enrollTime = result.getTimestamp("enrollTime");
                Timestamp loginTime = result.getTimestamp("loginTime");
                Courier c = new Courier(id, courierName, courierPhone, courierIdNumber, courierPassword, courierSendNumber, enrollTime, loginTime);
                return c;
            }
        }catch (SQLException throwables){
    
    
            throwables.printStackTrace();
        }finally {
    
    
            DruidUtil.close(conn,state,result);
        }
        return null;
    }

    /**
     * 根据手机号查快递员
     *
     * @param courierPhone 手机号
     * @return 查到的快递员,courierPhone不存在时返回null
     */
    @Override
    public Courier findByPhone(String courierPhone) {
    
    
        Connection conn = DruidUtil.getConnection();
        PreparedStatement state = null;
        ResultSet result = null;

        try {
    
    
            state = conn.prepareStatement(SQL_FIND_BY_PHONE);
            state.setString(1, courierPhone);
            result = state.executeQuery();

            if (result.next()){
    
    
                int id = result.getInt("id");
                String courierName = result.getString("courierName");
                String courierIdNumber = result.getString("courierIdNumber");
                String courierPassword = result.getString("courierPassword");
                int courierSendNumber = result.getInt("courierSendNumber");
                Timestamp enrollTime = result.getTimestamp("enrollTime");
                Timestamp loginTime = result.getTimestamp("loginTime");

                Courier c = new Courier(id, courierName, courierPhone, courierIdNumber, courierPassword, courierSendNumber, enrollTime, loginTime);
                return c;
            }
        }catch (SQLException throwables){
    
    
            throwables.printStackTrace();
        }finally {
    
    
            DruidUtil.close(conn,state,result);
        }
        return null;
    }

    /**
     * 根据身份证号查快递员
     *
     * @param courierIdNumber 身份证号
     * @return 查到的快递员,courierIdNumber不存在时返回null
     */
    @Override
    public Courier findByIdNumber(String courierIdNumber) {
    
    
        ArrayList<Courier> data = new ArrayList<>();
        Connection conn = DruidUtil.getConnection();
        PreparedStatement state = null;
        ResultSet result = null;
        try {
    
    
            state = conn.prepareStatement(SQL_FIND_BY_ID_NUMBER);
            state.setString(1, courierIdNumber);
            result = state.executeQuery();

            if (result.next()){
    
    
                int id = result.getInt("id");
                String courierName = result.getString("courierName");
                String courierPhone = result.getString("courierPhone");
                String courierPassword = result.getString("courierPassword");
                int courierSendNumber = result.getInt("courierSendNumber");
                Timestamp enrollTime = result.getTimestamp("enrollTime");
                Timestamp loginTime = result.getTimestamp("loginTime");
                Courier c = new Courier(id, courierName, courierPhone, courierIdNumber, courierPassword, courierSendNumber, enrollTime, loginTime);
                return c;
            }
        }catch (SQLException throwables){
    
    
            throwables.printStackTrace();
        }finally {
    
    
            DruidUtil.close(conn,state,result);
        }
        return null;
    }

    /**
     * 快递员的录入
     * "INSERT INTO COURIER(COURIERNAME,COURIERPHONE,COURIERIDNUMBER,COURIERPASSWORD,COURIERSENDNUMBER,ENROLLTIME) VALUES(?,?,?,?,0,NOW())"
     * @param c 要录入的对象
     * @return 录入的结果
     */
    @Override
    public boolean insert(Courier c) {
    
    
        Connection conn = DruidUtil.getConnection();
        PreparedStatement state = null;
        try {
    
    
            state = conn.prepareStatement(SQL_INSERT);

            state.setString(1,c.getCourierName());
            state.setString(2,c.getCourierPhone());
            state.setString(3,c.getCourierIdNumber());
            state.setString(4,c.getCourierPassword());

            return (state.executeUpdate() > 0);
        } catch (SQLException e1) {
    
    
            e1.printStackTrace();
        }finally {
    
    
            DruidUtil.close(conn,state,null);
        }
        return false;
    }

    /**
     * 快递员的修改
     * "UPDATE COURIER SET COURIERNAME=?,COURIERPHONE=?,COURIERIDNUMBER=?,COURIERPASSWORD=? WHERE ID=?"
     * @param id         要修改的快递员id
     * @param newCourier 新的快递员对象
     * @return 修改的结果
     */
    @Override
    public boolean update(int id, Courier newCourier) {
    
    
        Connection conn = DruidUtil.getConnection();
        PreparedStatement state = null;

        try {
    
    
            state = conn.prepareStatement(SQL_UPDATE);
            state.setString(1,newCourier.getCourierName());
            state.setString(2,newCourier.getCourierPhone());
            state.setString(3,newCourier.getCourierIdNumber());
            state.setString(4,newCourier.getCourierPassword());
            state.setInt(5,id);

            return state.executeUpdate() > 0;
        } catch (SQLException throwables) {
    
    
            throwables.printStackTrace();
        }finally {
    
    
            DruidUtil.close(conn, state, null);
        }
        return false;
    }

    /**
     * 派件数修改
     *
     * @param id        快递员id
     * @param increment 新增的派件数
     * @return 是否修改成功
     */
    @Override
    public boolean updateSendNumber(int id, int increment) {
    
    
        Connection conn = DruidUtil.getConnection();
        PreparedStatement state = null;

        try {
    
    
            state = conn.prepareStatement(SQL_UPDATE_SEND_NUMBER);
            state.setInt(1,increment);
            state.setInt(2,id);

            return state.executeUpdate() > 0;
        } catch (SQLException throwables) {
    
    
            throwables.printStackTrace();
        }finally {
    
    
            DruidUtil.close(conn, state, null);
        }
        return false;
    }

    /**
     * 更新登陆时间
     *
     * @param id
     * @return
     */
    @Override
    public boolean updateLoginTime(int id) {
    
    
        Connection conn = DruidUtil.getConnection();
        PreparedStatement state = null;

        try {
    
    
            state = conn.prepareStatement(SQL_UPDATE_LOGIN_TIME);
            state.setInt(1,id);

            return state.executeUpdate() > 0;
        } catch (SQLException throwables) {
    
    
            throwables.printStackTrace();
        }finally {
    
    
            DruidUtil.close(conn, state, null);
        }
        return false;
    }

    /**
     * 根据id,删除单个快递员信息
     *
     * @param id 要删除的快递员信息
     * @return 删除结果
     */
    @Override
    public boolean delete(int id) {
    
    
        Connection conn = DruidUtil.getConnection();
        PreparedStatement state = null;

        try {
    
    
            state = conn.prepareStatement(SQL_DELETE);
            state.setInt(1,id);
            return state.executeUpdate() > 0;
        } catch (SQLException throwables) {
    
    
            throwables.printStackTrace();
        }finally {
    
    
            DruidUtil.close(conn, state, null);
        }
        return false;
    }
}

9.3.2 用户相关dao

步骤:

  1. 获取数据库连接
  2. 预编译sql
  3. 填充参数(可选)
  4. 执行sql
  5. 获取执行结果
  6. 资源释放

dao接口定义:

package com.wangjiawei.dao;

import com.wangjiawei.bean.User;

import java.util.List;
import java.util.Map;

/**
 * 2 * @Author: 小王同学
 * 3 * @Date: 2020/10/9 9:54
 * 4
 */
public interface BaseUserDao {

    /**
     * 用于查询数据库中的全部用户(总数,当日新增)
     * @return [{size:总数, day:新增}]
     */
    List<Map<String, Integer>> console();

    /**
     * 查询所有用户
     * @param limit 是否分页的标记,true:分页,false:查询所有
     * @param offset sql语句的起始索引
     * @param pageNumber 每一页查询的数量
     * @return 用户的集合
     */
    List<User> findAll(boolean limit, int offset, int pageNumber);

    /**
     * 根据用户名查询用户
     * @param userName 用户名
     * @return
     */
    List<User> findByName(String userName);

    /**
     * 根据身份证号查询用户
     * @param userIdNumber 身份证号
     * @return 查询结果
     */
    User findByIdNumber(String userIdNumber);

    /**
     * 根据手机号查询用户
     * @param userPhone 手机号
     * @return
     */
    User findByUserPhone(String userPhone);

    /**
     * 用户录入
     * @param u 要录入的对象
     * @return 录入的结果
     */
    boolean insert(User u);

    /**
     * 用户的修改
     * @param id 要修改用户的id
     * @param newUser 新的用户对象
     * @return 修改的结果
     */
    boolean update(int id, User newUser);

    /**
     * 更新登录时间
     * @param id
     * @return
     */
    boolean updateLoginTime(int id);

    /**
     * 根据id,删除单个用户信息
     * @param id 要删除的用户信息
     * @return 删除结果
     */
    boolean delete(int id);

}

dao完整实现:

package com.wangjiawei.dao.imp;

import com.wangjiawei.bean.User;
import com.wangjiawei.dao.BaseUserDao;
import com.wangjiawei.util.DruidUtil;

import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 2 * @Author: 小王同学
 * 3 * @Date: 2020/10/9 10:07
 * 4
 */
public class UserDaoMysql implements BaseUserDao {

    /**
     * 查询用户(总数+新增)
     */
    public static final String SQL_CONSOLE = "SELECT " +
            "COUNT(ID) data_size," +
            "COUNT(TO_DAYS(ENROLLTIME)=TO_DAYS(NOW()) OR NULL) data_day " +
            "FROM USER";
    /**
     * 查询数据库中所有的用户信息
     */
    public static final String SQL_FIND_ALL = "SELECT * FROM USER";
    /**
     * 分页查询数据库中所有用户信息
     */
    public static final String SQL_FIND_LIMIT = "SELECT * FROM USER LIMIT ?,?";
    /**
     * 通过用户名查询用户信息
     */
    public static final String SQL_FIND_BY_USER_NAME = "SELECT * FROM USER WHERE USERNAME=?";
    /**
     * 通过手机号查询用户信息
     */
    public static final String SQL_FIND_BY_USER_PHONE = "SELECT * FROM USER WHERE USERPHONE=?";

    public static final String SQL_FIND_BY_USER_ID_NUMBER = "SELECT * FROM USER WHERE USERIDNUMBER=?";
    /**
     * 录入用户
     */
    public static final String SQL_INSERT = "INSERT INTO USER(USERNAME,USERPHONE,USERIDNUMBER,USERPASSWORD,ENROLLTIME,LOGINTIME) VALUES(?,?,?,?,NOW(),NOW())";
    /**
     * 修改用户
     */
    public static final String SQL_UPDATE = "UPDATE USER SET USERNAME=?,USERPHONE=?,USERIDNUMBER=?,USERPASSWORD=? WHERE ID=?";
    /**
     * 修改用户登录时间
     */
    public static final String SQL_UPDATE_LOGIN_TIME = "UPDATE USER SET LOGINTIME=NOW() WHERE ID=?";
    /**
     * 快递员的删除
     */
    public static final String SQL_DELETE = "DELETE FROM USER WHERE ID=?";


    /**
     * 用于查询数据库中的全部用户(总数,当日新增)
     *
     * @return [{size:总数, day:新增}]
     */
    @Override
    public List<Map<String, Integer>> console() {
        ArrayList<Map<String, Integer>> data = new ArrayList<>();
        Connection conn = DruidUtil.getConnection();
        PreparedStatement state = null;
        ResultSet result = null;
        try {
            state = conn.prepareStatement(SQL_CONSOLE);
            result = state.executeQuery();
            if (result.next()){
                int data_size = result.getInt("data_size");
                int data_day = result.getInt("data_day");
                Map<String,Integer> data1 = new HashMap<>();
                data1.put("data_size",data_size);
                data1.put("data_day",data_day);
                data.add(data1);
            }
        }catch (SQLException throwables){
            throwables.printStackTrace();
        }finally {
            DruidUtil.close(conn,state,result);
        }
        return data;
    }

    /**
     * 查询所有用户
     *
     * @param limit      是否分页的标记,true:分页,false:查询所有
     * @param offset     sql语句的起始索引
     * @param pageNumber 每一页查询的数量
     * @return 用户的集合
     */
    @Override
    public List<User> findAll(boolean limit, int offset, int pageNumber) {
        ArrayList<User> data = new ArrayList<>();
        Connection conn = DruidUtil.getConnection();
        PreparedStatement state = null;
        ResultSet result = null;
        try {
            if (limit){
                state = conn.prepareStatement(SQL_FIND_LIMIT);
                state.setInt(1,offset);
                state.setInt(2,pageNumber);
            }else {
                state = conn.prepareStatement(SQL_FIND_ALL);
            }
            result = state.executeQuery();

            while (result.next()){
                int id = result.getInt("id");
                String userName = result.getString("userName");
                String userPhone = result.getString("userPhone");
                String userIdNumber = result.getString("userIdNumber");
                String userPassword = result.getString("userPassword");
                Timestamp enrollTime = result.getTimestamp("enrollTime");
                Timestamp loginTime = result.getTimestamp("loginTime");

                User u = new User(id, userName, userPhone, userIdNumber, userPassword, enrollTime, loginTime);
                data.add(u);
            }
        }catch (SQLException throwables){
            throwables.printStackTrace();
        }finally {
            DruidUtil.close(conn,state,result);
        }
        return data;
    }

    /**
     * 根据用户名查询用户
     *
     * @param userName 用户名
     * @return
     */
    @Override
    public List<User> findByName(String userName) {
        ArrayList<User> data = new ArrayList<>();
        Connection conn = DruidUtil.getConnection();
        PreparedStatement state = null;
        ResultSet result = null;
        try {
            state = conn.prepareStatement(SQL_FIND_BY_USER_NAME);
            state.setString(1,userName);
            result = state.executeQuery();
            while (result.next()){
                int id = result.getInt("id");
                String userPhone = result.getString("userPhone");
                String userIdNumber = result.getString("userIdNumber");
                String userPassword = result.getString("userPassword");
                Timestamp enrollTime = result.getTimestamp("enrollTime");
                Timestamp loginTime = result.getTimestamp("loginTime");

                User u = new User(id, userName, userPhone, userIdNumber, userPassword, enrollTime, loginTime);
                data.add(u);
            }
        }catch (SQLException throwables){
            throwables.printStackTrace();
        }finally {
            DruidUtil.close(conn,state,result);
        }
        return data;
    }

    /**
     * 根据身份证号查询用户
     *
     * @param userIdNumber 身份证号
     * @return 查询结果
     */
    @Override
    public User findByIdNumber(String userIdNumber) {
        Connection conn = DruidUtil.getConnection();
        PreparedStatement state = null;
        ResultSet result = null;
        try {
            state = conn.prepareStatement(SQL_FIND_BY_USER_ID_NUMBER);
            state.setString(1, userIdNumber);
            result = state.executeQuery();

            if (result.next()){
                int id = result.getInt("id");
                String userName = result.getString("userName");
                String userPhone = result.getString("userPhone");
                String userPassword = result.getString("userPassword");
                Timestamp enrollTime = result.getTimestamp("enrollTime");
                Timestamp loginTime = result.getTimestamp("loginTime");

                User u = new User(id, userName, userPhone, userIdNumber, userPassword, enrollTime, loginTime);
                return u;
            }
        }catch (SQLException throwables){
            throwables.printStackTrace();
        }finally {
            DruidUtil.close(conn,state,result);
        }
        return null;
    }

    /**
     * 根据手机号查询用户
     *
     * @param userPhone 手机号
     * @return
     */
    @Override
    public User findByUserPhone(String userPhone) {
        Connection conn = DruidUtil.getConnection();
        PreparedStatement state = null;
        ResultSet result = null;
        try {
            state = conn.prepareStatement(SQL_FIND_BY_USER_PHONE);
            state.setString(1, userPhone);
            result = state.executeQuery();
            if (result.next()){
                int id = result.getInt("id");
                String userName = result.getString("userName");
                String userIdNumber = result.getString("userIdNumber");
                String userPassword = result.getString("userPassword");
                Timestamp enrollTime = result.getTimestamp("enrollTime");
                Timestamp loginTime = result.getTimestamp("loginTime");

                User u = new User(id, userName, userPhone, userIdNumber, userPassword, enrollTime, loginTime);
                return u;
            }
        }catch (SQLException throwables){
            throwables.printStackTrace();
        }finally {
            DruidUtil.close(conn,state,result);
        }
        return null;
    }

    /**
     * 用户录入
     *
     * @param u 要录入的对象
     * @return 录入的结果
     */
    @Override
    public boolean insert(User u) {
        Connection conn = DruidUtil.getConnection();
        PreparedStatement state = null;
        try {
            state = conn.prepareStatement(SQL_INSERT);
            state.setString(1,u.getUserName());
            state.setString(2,u.getUserPhone());
            state.setString(3,u.getUserIdNumber());
            state.setString(4,u.getUserPassword());
            return (state.executeUpdate() > 0);
        }catch (SQLException throwables){
            throwables.printStackTrace();
        }finally {
            DruidUtil.close(conn,state,null);
        }
        return false;
    }

    /**
     * 用户的修改
     *
     * @param id      要修改用户的id
     * @param newUser 新的用户对象
     * @return 修改的结果
     */
    @Override
    public boolean update(int id, User newUser) {
        Connection conn = DruidUtil.getConnection();
        PreparedStatement state = null;
        try {
            state = conn.prepareStatement(SQL_UPDATE);
            state.setString(1,newUser.getUserName());
            state.setString(2,newUser.getUserPhone());
            state.setString(3,newUser.getUserIdNumber());
            state.setString(4,newUser.getUserPassword());
            state.setInt(5,id);
            return state.executeUpdate() > 0;
        }catch (SQLException throwables){
            throwables.printStackTrace();
        }finally {
            DruidUtil.close(conn,state,null);
        }
        return false;
    }

    /**
     * 更新登录时间
     *
     * @param id
     * @return
     */
    @Override
    public boolean updateLoginTime(int id) {
        Connection conn = DruidUtil.getConnection();
        PreparedStatement state = null;
        try {
            state = conn.prepareStatement(SQL_UPDATE_LOGIN_TIME);
            state.setInt(1,id);
            return state.executeUpdate() > 0;
        }catch (SQLException throwables){
            throwables.printStackTrace();
        }finally {
            DruidUtil.close(conn,state,null);
        }
        return false;
    }

    /**
     * 根据id,删除单个用户信息
     *
     * @param id 要删除的用户信息
     * @return 删除结果
     */
    @Override
    public boolean delete(int id) {
        Connection conn = DruidUtil.getConnection();
        PreparedStatement state = null;
        try {
            state = conn.prepareStatement(SQL_DELETE);
            state.setInt(1, id);
            return state.executeUpdate() > 0;
        }catch (SQLException throwables){
            throwables.printStackTrace();
        }finally {
            DruidUtil.close(conn,state,null);
        }
        return false;
    }
}

10 service层编写

10.1 ExpressService

package com.wangjiawei.service;

import com.wangjiawei.bean.Express;
import com.wangjiawei.dao.BaseExpressDao;
import com.wangjiawei.dao.imp.ExpressDaoMysql;
import com.wangjiawei.exception.DuplicateCodeException;
import com.wangjiawei.util.RandomUtil;

import java.util.List;
import java.util.Map;

/**
 * 2 * @Author: 小王同学
 * 3 * @Date: 2020/10/4 14:03
 * 4
 */
public class ExpressService {
    
    

    private static BaseExpressDao dao = new ExpressDaoMysql();

    /**
     * 用于查询数据库中的全部快递(总数,当日新增)
     * 待取件快递(总数,当日新增)
     *
     * @return [{size:总数, day:新增},{size:总数, day:新增}]
     */
    public static List<Map<String, Integer>> console() {
    
    
        return dao.console();
    }

    /**
     * 查询所有快递
     *
     * @param limit      是否分页的标记,true:分页,false:查询所有
     * @param offset     sql语句的起始索引
     * @param pageNumber 每一页查询的数量
     * @return 快递的集合
     */
    public static List<Express> findAll(boolean limit, int offset, int pageNumber) {
    
    
        return dao.findAll(limit, offset, pageNumber);
    }

    /**
     * 根据快递单号查询快递信息
     *
     * @param number 单号
     * @return 查询的快递信息,单号不存在时返回null
     */
    public static Express findByNumber(String number) {
    
    
        return dao.findByNumber(number);
    }

    /**
     * 根据快递单号查询快递信息
     *
     * @param code 取件码
     * @return 查询的快递信息,取件码不存在时返回null
     */
    public static Express findByCode(String code) {
    
    
        return dao.findByCode(code);
    }

    /**
     * 根据用户手机号查询所有快递
     *
     * @param userPhone 手机号
     * @return 查询的快递信息,手机号不存在时返回null
     */
    public static List<Express> findByUserPhone(String userPhone) {
    
    
        return dao.findByUserPhone(userPhone);
    }

    /**
     * 根据录入人手机号查询录入的所有记录
     *
     * @param sysPhone 手机号
     * @return 查询的快递信息,手机号不存在时返回null
     */
    public static List<Express> findBySysPhone(String sysPhone) {
    
    
        return dao.findBySysPhone(sysPhone);
    }

    /**
     * 快递的录入
     *
     * @param e 要录入的对象
     * @return 录入的结果
     */
    public static boolean insert(Express e) {
    
    
        // 生成取件码
        e.setCode(RandomUtil.getCode() + "");
        try {
    
    
            return dao.insert(e);
        } catch (DuplicateCodeException duplicateCodeException) {
    
    
            // 取件码重复
            return insert(e);
        }
    }

    /**
     * 快递的修改
     *
     * @param id         要修改的快递id
     * @param newExpress 新的快递对象(number, company, username, userPhone)
     * @return 修改的结果
     */
    public static boolean update(int id, Express newExpress) {
    
    
        if (newExpress.getUserPhone() != null){
    
    
            // 手机号码变了
            dao.delete(id);
            return insert(newExpress);
        }else{
    
    
            boolean update = dao.update(id, newExpress);
            Express e = dao.findByNumber(newExpress.getNumber());
            if (newExpress.getStatus() == 1){
    
    
                // 更改为已取件
                updateStatus(e.getCode());
            }
            return update;
        }
    }

    /**
     * 更改快递状态为1,表示取件完成
     *
     * @param code@return 修改的结果
     */
    public static boolean updateStatus(String code) {
    
    
        return dao.updateStatus(code);
    }

    /**
     * 根据id,删除单个快递信息
     *
     * @param id 要删除的快递信息
     * @return 删除结果
     */
    public static boolean delete(int id) {
    
    
        return dao.delete(id);
    }
}

10.2 快递员service层实现

package com.wangjiawei.service;

import com.wangjiawei.bean.Courier;
import com.wangjiawei.dao.BaseCourierDao;
import com.wangjiawei.dao.imp.CourierDaoMysql;

import java.util.List;
import java.util.Map;

/**
 * 2 * @Author: 小王同学
 * 3 * @Date: 2020/10/8 16:52
 * 4
 */
public class CourierService{
    
    

    private static BaseCourierDao dao = new CourierDaoMysql();


    /**
     * 用于查询数据库中的全部快递快递员(总数,当日新增)
     * 快递员(总数,当日新增)
     *
     * @return [{size:总数, day:新增}]
     */
    public static List<Map<String, Integer>> console() {
    
    
        return dao.console();
    }

    /**
     * 查询所有快递员
     *
     * @param limit      是否分页的标记,true:分页,false:查询所有
     * @param offset     sql语句的起始索引
     * @param pageNumber 每一页查询的数量
     * @return 快递员的集合
     */
    public static List<Courier> findAll(boolean limit, int offset, int pageNumber) {
    
    
        return dao.findAll(limit, offset, pageNumber);
    }

    /**
     * 根据id查快递员
     *
     * @param id
     * @return 查到的快递员,id不存在时返回null
     */
    public static Courier findById(int id) {
    
    
        return dao.findById(id);
    }

    /**
     * 根据姓名查快递员
     *
     * @param courierName 姓名
     * @return 查到的快递员,courierName不存在时返回null
     */
    public static Courier findByName(String courierName) {
    
    
        return dao.findByName(courierName);
    }

    /**
     * 根据手机号查快递员
     *
     * @param courierPhone 手机号
     * @return 查到的快递员,courierPhone不存在时返回null
     */
    public static Courier findByPhone(String courierPhone) {
    
    
        return dao.findByPhone(courierPhone);
    }

    /**
     * 根据身份证号查快递员
     *
     * @param courierIdNumber 身份证号
     * @return 查到的快递员,courierIdNumber不存在时返回null
     */
    public static Courier findByIdNumber(String courierIdNumber) {
    
    
        return dao.findByIdNumber(courierIdNumber);
    }

    /**
     * 快递员的录入
     *
     * @param c 要录入的对象
     * @return 录入的结果
     */
    public static boolean insert(Courier c) {
    
    
        return dao.insert(c);
    }

    /**
     * 快递员的修改
     *
     * @param id         要修改的快递员id
     * @param newCourier 新的快递员对象
     * @return 修改的结果
     */
    public static boolean update(int id, Courier newCourier) {
    
    
        return dao.update(id,newCourier);
    }

    /**
     * 根据id,删除单个快递员信息
     *
     * @param id 要删除的快递员信息
     * @return 删除结果
     */
    public static boolean delete(int id) {
    
    
        return dao.delete(id);
    }

    /**
     * 派件数修改
     * @param id 快递员id
     * @param increment 新增的派件数
     * @return 是否修改成功
     */
    public static boolean updateSendNumber(int id, int increment){
    
    
        return dao.updateSendNumber(id, increment);
    }

    /**
     * 更新登陆时间
     * @param id
     * @return
     */
    public static boolean updateLoginTime(int id){
    
    
        return dao.updateLoginTime(id);
    }
}

10.3 用户service层实现

package com.wangjiawei.service;

import com.wangjiawei.bean.User;
import com.wangjiawei.dao.BaseUserDao;
import com.wangjiawei.dao.imp.UserDaoMysql;

import java.util.List;
import java.util.Map;

/**
 * 2 * @Author: 小王同学
 * 3 * @Date: 2020/10/9 14:02
 * 4
 */
public class UserService {
    
    

    private static BaseUserDao dao = new UserDaoMysql();


    /**
     * 用于查询数据库中的全部用户(总数,当日新增)
     *
     * @return [{size:总数, day:新增}]
     */
    public List<Map<String, Integer>> console() {
    
    
        return dao.console();
    }

    /**
     * 查询所有用户
     *
     * @param limit      是否分页的标记,true:分页,false:查询所有
     * @param offset     sql语句的起始索引
     * @param pageNumber 每一页查询的数量
     * @return 用户的集合
     */
    public List<User> findAll(boolean limit, int offset, int pageNumber) {
    
    
        return dao.findAll(limit, offset, pageNumber);
    }

    /**
     * 根据用户名查询用户
     *
     * @param userName 用户名
     * @return
     */
    public List<User> findByName(String userName) {
    
    
        return dao.findByName(userName);
    }

    /**
     * 根据身份证号查询用户
     *
     * @param userIdNumber 身份证号
     * @return 查询结果
     */
    public User findByIdNumber(String userIdNumber) {
    
    
        return dao.findByIdNumber(userIdNumber);
    }

    /**
     * 根据手机号查询用户
     *
     * @param userPhone 手机号
     * @return
     */
    public User findByUserPhone(String userPhone) {
    
    
        return dao.findByUserPhone(userPhone);
    }

    /**
     * 用户录入
     *
     * @param u 要录入的对象
     * @return 录入的结果
     */
    public boolean insert(User u) {
    
    
        return dao.insert(u);
    }

    /**
     * 用户的修改
     *
     * @param id      要修改用户的id
     * @param newUser 新的用户对象
     * @return 修改的结果
     */
    public boolean update(int id, User newUser) {
    
    
        return dao.update(id, newUser);
    }

    /**
     * 更新登录时间
     *
     * @param id
     * @return
     */
    public boolean updateLoginTime(int id) {
    
    
        return dao.updateLoginTime(id);
    }

    /**
     * 根据id,删除单个用户信息
     *
     * @param id 要删除的用户信息
     * @return 删除结果
     */
    public boolean delete(int id) {
    
    
        return dao.delete(id);
    }
}

11 阿里云短信集成

创建SMSUtil:

package com.wangjiawei.util;

import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.google.gson.Gson;

import java.util.HashMap;

/**
 * 2 * @Author: 小王同学
 * 3 * @Date: 2020/10/5 11:19
 * 4
 */
public class SMSUtil {
    
    
    public static boolean send(String phoneNumber,String code) {
    
    
        DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", "LTAI4GKsiFzUmLZ8Qnx1Sfza", "jUhIqqk3wwvhm2T1HOUVbCmIOWNE0O");
        IAcsClient client = new DefaultAcsClient(profile);

        CommonRequest request = new CommonRequest();
        request.setSysMethod(MethodType.POST);
        request.setSysDomain("dysmsapi.aliyuncs.com");
        request.setSysVersion("2017-05-25");
        request.setSysAction("SendSms");
        request.putQueryParameter("RegionId", "cn-hangzhou");
        request.putQueryParameter("PhoneNumbers", phoneNumber);
        request.putQueryParameter("SignName", "快递e栈");
        request.putQueryParameter("TemplateCode", "SMS_204115757");
        request.putQueryParameter("TemplateParam", "{\"code\":\""+ code +"\"}");
        try {
    
    
            CommonResponse response = client.getCommonResponse(request);
            System.out.println(response.getData());
            String json = response.getData();
            Gson g = new Gson();
            HashMap result = g.fromJson(json, HashMap.class);
            if("OK".equals(result.get("Message"))) {
    
    
                return true;
            }else{
    
    
                System.out.println("短信发送失败,原因:"+result.get("Message"));
            }
        } catch (ServerException e) {
    
    
            e.printStackTrace();
        } catch (ClientException e) {
    
    
            e.printStackTrace();
        }
        return false;
    }
}

把发送短信的功能集成到ExpressService的insert方法中:

public static boolean insert(Express e) {
    
    
    // 生成取件码
    e.setCode(RandomUtil.getCode() + "");
    try {
    
    
        boolean flag =  dao.insert(e);
        if (flag){
    
    
            // 录入成功,发送短信
            SMSUtil.send(e.getUserPhone(), e.getCode());
        }
        return flag;
    } catch (DuplicateCodeException duplicateCodeException) {
    
    
        // 取件码重复
        return insert(e);
    }
}

12 控制台部分

12.1 管理器

12.1.1 快递管理器 ExpressController

package com.wangjiawei.controller;

import com.wangjiawei.bean.Express;
import com.wangjiawei.bean.Message;
import com.wangjiawei.mvc.ResponseBody;
import com.wangjiawei.service.ExpressService;
import com.wangjiawei.util.JSONUtil;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;

/**
 * 2 * @Author: 小王同学
 * 3 * @Date: 2020/10/5 12:38
 * 4
 */
public class ExpressController {
    
    

    @ResponseBody("/express/console.do")
    public String console(HttpServletRequest request, HttpServletResponse response){
    
    
        List<Map<String, Integer>> data = ExpressService.console();
        Message msg = new Message();
        if (data.size() == 0){
    
    
            msg.setStatus(-1);
        }else {
    
    
            msg.setStatus(0);
        }
        msg.setData(data);
        String json = JSONUtil.toJSON(msg);
        return json;
    }
}

12.1.2 快递员管理器CourierController

package com.wangjiawei.controller;

import com.wangjiawei.bean.Message;
import com.wangjiawei.mvc.ResponseBody;
import com.wangjiawei.service.CourierService;
import com.wangjiawei.service.ExpressService;
import com.wangjiawei.util.JSONUtil;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;

/**
 * 2 * @Author: 小王同学
 * 3 * @Date: 2020/10/8 18:40
 * 4
 */
public class CourierController {
    
    

    @ResponseBody("/courier/console.do")
    public String console(HttpServletRequest request, HttpServletResponse response){
    
    
        List<Map<String, Integer>> data = CourierService.console();
        Message msg = new Message();
        if (data.size() == 0){
    
    
            msg.setStatus(-1);
        }else {
    
    
            msg.setStatus(0);
        }
        msg.setData(data);
        String json = JSONUtil.toJSON(msg);
        return json;
    }  
}

12.1.3 用户管理器

package com.wangjiawei.controller;

import com.wangjiawei.bean.Message;
import com.wangjiawei.mvc.ResponseBody;
import com.wangjiawei.service.CourierService;
import com.wangjiawei.service.UserService;
import com.wangjiawei.util.JSONUtil;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;

/**
 * 2 * @Author: 小王同学
 * 3 * @Date: 2020/10/9 14:07
 * 4
 */
public class UserController {
    
    
    @ResponseBody("/user/console.do")
    public String console(HttpServletRequest request, HttpServletResponse response){
    
    
        List<Map<String, Integer>> data = UserService.console();
        Message msg = new Message();
        if (data.size() == 0){
    
    
            msg.setStatus(-1);
        }else {
    
    
            msg.setStatus(0);
        }
        msg.setData(data);
        String json = JSONUtil.toJSON(msg);
        return json;
    }
}

12.2 对应的前端代码admin/views/user/console.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <link rel="stylesheet" href="../assets/css/layui.css">
    <link rel="stylesheet" href="../assets/css/view.css"/>
    <script src="../assets/echarts.min.js"></script>
    <script src="../../qrcode/jquery2.1.4.js"></script>
    <title></title>
</head>
<body class="layui-view-body">
    <div class="layui-content">
        <div class="layui-row layui-col-space20">
            <div class="layui-col-sm6 layui-col-md6">
                <div class="layui-card">
                    <div class="layui-card-body chart-card">
                        <div class="chart-header">
                            <div class="metawrap">
                                <div class="meta">
                                    <span>用户人数</span>
                                </div>
                                <div id="user_size" class="total">-</div>
                            </div>
                        </div>
                        <div class="chart-body">
                            <div class="contentwrap">
                            </div>
                        </div>
                        <div class="chart-footer">
                            <div class="field">
                                <span>日注册量</span>
                                <span id="user_day">-</span>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <div class="layui-col-sm6 layui-col-md6">
                <div class="layui-card">
                    <div class="layui-card-body chart-card">
                        <div class="chart-header">
                            <div class="metawrap">
                                <div class="meta">
                                    <span>快递员人数</span>
                                </div>
                                <div id="courier_size" class="total">-</div>
                            </div>
                        </div>
                        <div class="chart-body">
                            <div class="contentwrap">
                            </div>
                        </div>
                        <div class="chart-footer">
                            <div class="field">
                                <span>日注册量</span>
                                <span id="courier_day">-</span>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <div class="layui-col-sm6 layui-col-md6">
                <div class="layui-card">
                    <div class="layui-card-body chart-card">
                        <div class="chart-header">
                            <div class="metawrap">
                                <div class="meta">
                                    <span>总快件数</span>
                                </div>
                                <div id="data1_size" class="total">-</div>
                            </div>
                        </div>
                        <div class="chart-body">
                            <div class="contentwrap">
                            </div>
                        </div>
                        <div class="chart-footer">
                            <div class="field">
                                <span>日派单量</span>
                                <span id="data1_day">-</span>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <div class="layui-col-sm6 layui-col-md6">
                <div class="layui-card">
                    <div class="layui-card-body chart-card">
                        <div class="chart-header">
                            <div class="metawrap">
                                <div class="meta">
                                    <span>待取件数</span>
                                </div>
                                <div id="data2_size" class="total">-</div>
                            </div>
                        </div>
                        <div class="chart-body">
                            <div class="contentwrap">
                            </div>
                        </div>
                        <div class="chart-footer">
                            <div class="field">
                                <span>新增数量</span>
                                <span id="data2_day">-</span>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
           
            <div class="layui-col-sm12 layui-col-md12">
                <div class="layui-card">
                    <div class="layui-tab layui-tab-brief">
                        <ul class="layui-tab-title">
                            <li class="layui-this">实时快件区域分布图</li>
                        </ul>
                        <div class="layui-tab-content">
                            <div class="layui-tab-item layui-show">
                               <iframe src="map.html" style="width:100%;height:600px;"></iframe>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <script src="../assets/layui.all.js"></script>
    <script>
     var element = layui.element;
    </script>

    <script>
        $(function () {
     
     
            //1.    ajax与服务器交互
            // 地址最左边的斜杠表示从根目录开始的路径
            $.post("/express/console.do",null,function(data){
     
     
                if (data.status == 0){
     
     
                    // [{size:总数, day:新增},{size:总数, day:新增}]
                    $("#data1_size").html(data.data[0].data1_size);
                    $("#data1_day").html(data.data[0].data1_day);
                    $("#data2_size").html(data.data[1].data2_size);
                    $("#data2_day").html(data.data[1].data2_day);
                }
            },"JSON");

            $.post("/courier/console.do",null,function (data) {
     
     
                $("#courier_size").html(data.data[0].data_size);
                $("#courier_day").html(data.data[0].data_day);
            },"JSON");

            $.post("/user/console.do",null,function (data) {
     
     
                $("#user_size").html(data.data[0].data_size);
                $("#user_day").html(data.data[0].data_day);
            },"JSON");

        });
    </script>
</body>
</html>

13 分页列表

13.1 快递列表

存储分页相关数据的类:(可以被bootstrap-table识别)

package com.wangjiawei.bean;

import java.util.ArrayList;
import java.util.List;

/**
 * 2 * @Author: 小王同学
 * 3 * @Date: 2020/10/5 19:55
 * 4
 */
public class ResultData<T> {
    
    
    /**
     * 每次查询的数据集合
      */
    private List<T> rows = new ArrayList<>();

    /**
     * 总数量
     */
    private int total;

    public List<T> getRows() {
    
    
        return rows;
    }

    public void setRows(List<T> rows) {
    
    
        this.rows = rows;
    }

    public int getTotal() {
    
    
        return total;
    }

    public void setTotal(int total) {
    
    
        this.total = total;
    }
}

相应的ExpressController中添加list方法,用于分页查询:

@ResponseBody("/express/list.do")
public String list(HttpServletRequest request, HttpServletResponse response){
    
    
    // 获取查询数据的起始索引值
    int offset = Integer.parseInt(request.getParameter("offset"));
    // 获取当前页要查询的数据量
    int pageNumber = Integer.parseInt(request.getParameter("pageNumber"));
    // 查询
    List<Express> list = ExpressService.findAll(true, offset, pageNumber);
    List<Map<String, Integer>> console = ExpressService.console();
    Integer total = console.get(0).get("data1_size");
    // 将集合封装为 bootstrap-table识别的格式
    ResultData<Express> data = new ResultData<>();
    data.setRows(list);
    data.setTotal(total);
    String json = JSONUtil.toJSON(data);
    return json;
}

在前端配置bootsrtap来自动实现分页:

<!DOCTYPE html>
<html>
   <head>
      <meta charset="utf-8">
      <title></title>
      <link rel="stylesheet" type="text/css" href="../../css/reset.css"/>
      <link rel="stylesheet" type="text/css" href="../../css/list.css"/>
      <link href="https://cdn.bootcdn.net/ajax/libs/bootstrap-table/1.17.1/bootstrap-table.min.css" rel="stylesheet">
      <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
      <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
      <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
      <script src="https://cdn.bootcdn.net/ajax/libs/bootstrap-table/1.17.1/bootstrap-table.min.js"></script>
      <script src="https://cdn.bootcdn.net/ajax/libs/bootstrap-table/1.17.1/locale/bootstrap-table-zh-CN.min.js"></script>
   </head>
   <body>

      <table id="express_list"></table>

      <script>
         $(function () {
     
     
            $("#express_list").bootstrapTable({
     
     
               url:"/express/list.do",    // 数据地址
               striped:true,  // 是否显示行的间隔
               pageNumber:1,  // 初始化加载第几页
               pagination:true,   // 是否分页
               sidePagination:'server',
               pageSize:5,
               pageList:[5,10,20],    // 允许选择的每页显示条目数
               showRefresh:true,  // 显示刷新按钮
               queryParams:function(params){
     
       // 给服务器发参数
                  var temp = {
     
     
                     offset:params.offset,
                     pageNumber:params.limit
                  };
                  return temp;
               },
               columns:[  // 配置有哪些列
                  {
     
     
                     title:"编号",
                     field:"id",
                     sortable:false
                  },
                  {
     
     
                     title:"单号",
                     field:"number",
                     sortable:false
                  },
                  {
     
     
                     title:"姓名",
                     field:"username",
                     sortable:false
                  },
                  {
     
     
                     title:"电话",
                     field:"userPhone",
                     sortable:false
                  },
                  {
     
     
                     title:"快递公司",
                     field:"company",
                     sortable:false
                  },
                  {
     
     
                     title:"取件码",
                     field:"code",
                     sortable:false
                  },
                  {
     
     
                     title:"入库时间",
                     field:"inTime",
                     sortable:false
                  },
                  {
     
     
                     title:"出库时间",
                     field:"outTime",
                     sortable:false
                  },
                  {
     
     
                     title:"状态",
                     field:"status",
                     sortable:false
                  },
                  {
     
     
                     title:"录入人电话",
                     field:"sysPhone",
                     sortable:false
                  }
               ]
            });
         });
      </script>
   </body>
</html>

展示效果如下:
在这里插入图片描述
 为了使得入库时间和出库时间以及状态显示变得更易懂,单独创建一个快递类用于分页显示,这个快递类的不同之处在于这三个变量改为字符串形式:

package com.wangjiawei.bean;

import java.sql.Timestamp;

/**
 * 2 * @Author: 小王同学
 * 3 * @Date: 2020/10/6 10:36
 * 4
 */
public class BootStrapTableExpress {
    
    
    private int id;
    private String number;
    private String username;
    private String userPhone;
    private String company;
    private String code;
    private String inTime;
    private String outTime;
    private String status;
    private String sysPhone;

    // 构造方法,set,get省略
}

创建完成新类之后,改写ExpressController中的list方法:

@ResponseBody("/express/list.do")
public String list(HttpServletRequest request, HttpServletResponse response){
    
    
    // 获取查询数据的起始索引值
    int offset = Integer.parseInt(request.getParameter("offset"));
    // 获取当前页要查询的数据量
    int pageNumber = Integer.parseInt(request.getParameter("pageNumber"));
    // 查询
    List<Express> list = ExpressService.findAll(true, offset, pageNumber);
    List<BootStrapTableExpress> list2 = new ArrayList<>();
    for (Express e:list){
    
    
        String inTime = DateFormatUtil.format(e.getInTime());
        String outTime = e.getOutTime()==null?"未出库":DateFormatUtil.format(e.getOutTime());
        String status = e.getStatus() == 0 ? "待取件":"已取件";
        String code = e.getCode()==null ? "已取件":e.getCode();
        BootStrapTableExpress e2 = new BootStrapTableExpress(e.getId(),e.getNumber(),e.getUsername(),e.getUserPhone(),e.getCompany(),code,inTime,outTime,status,e.getSysPhone());
        list2.add(e2);
    }
    List<Map<String, Integer>> console = ExpressService.console();
    Integer total = console.get(0).get("data1_size");
    // 将集合封装为 bootstrap-table识别的格式
    ResultData<BootStrapTableExpress> data = new ResultData<>();
    data.setRows(list2);
    data.setTotal(total);
    String json = JSONUtil.toJSON(data);
    return json;
}

在这里插入图片描述

13.2 快递员列表

定义专门用于网页展示的类:

package com.wangjiawei.bean;

import java.sql.Timestamp;

/**
 * 2 * @Author: 小王同学
 * 3 * @Date: 2020/10/8 19:54
 * 4
 */
public class BootStrapTableCourier {
    
    
    private int id;
    private String courierName;
    private String courierPhone;
    private String courierIdNumber;
    private String courierPassword;
    private String courierSendNumber;
    private String enrollTime;
    private String loginTime;
    
    // 构造方法,set,get省略
}

快递员控制器CourierController中添加list方法:

@ResponseBody("/courier/list.do")
public String list(HttpServletRequest request, HttpServletResponse response){
    
    
    int offset = Integer.parseInt(request.getParameter("offset"));
    // 获取当前页要查询的数据量
    int pageNumber = Integer.parseInt(request.getParameter("pageNumber"));
    List<Courier> list = CourierService.findAll(true, offset, pageNumber);
    List<BootStrapTableCourier> list2 = new ArrayList<>();
    for (Courier c : list){
    
    
        String enrollTime = DateFormatUtil.format(c.getEnrollTime());
        String loginTime = c.getLoginTime()==null?"未登录":DateFormatUtil.format(c.getLoginTime());
        String sendNumber = null;
        int courierSendNumber = c.getCourierSendNumber();
        if (courierSendNumber <= 10000){
    
    
            sendNumber = courierSendNumber + "";
        }else{
    
    
            sendNumber = courierSendNumber/10000 + "w+";
        }
        BootStrapTableCourier c2 = new BootStrapTableCourier(c.getId(),c.getCourierName(),c.getCourierPhone(),"******",c.getCourierPassword(),sendNumber,enrollTime,loginTime);
        list2.add(c2);
    }
    List<Map<String, Integer>> console = CourierService.console();
    Integer total = console.get(0).get("data_size");
    ResultData<BootStrapTableCourier> data = new ResultData<>();
    data.setRows(list2);
    data.setTotal(total);
    String json = JSONUtil.toJSON(data);
    return json;
}

对应的前端代码list.html:

<!DOCTYPE html>
<html>
   <head>
      <meta charset="utf-8">
      <title></title>
      <link rel="stylesheet" type="text/css" href="../../css/reset.css"/>
      <link rel="stylesheet" type="text/css" href="../../css/list.css"/>
      <link href="https://cdn.bootcdn.net/ajax/libs/bootstrap-table/1.17.1/bootstrap-table.min.css" rel="stylesheet">
      <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
      <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
      <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
      <script src="https://cdn.bootcdn.net/ajax/libs/bootstrap-table/1.17.1/bootstrap-table.min.js"></script>
      <script src="https://cdn.bootcdn.net/ajax/libs/bootstrap-table/1.17.1/locale/bootstrap-table-zh-CN.min.js"></script>
   </head>
   <body>

   <table id="courier_list"></table>

   <script>
      $(function () {
     
     
         $("#courier_list").bootstrapTable({
     
     
            url:"/courier/list.do",
            striped:true,  // 是否显示行的间隔
            pageNumber:1,  // 初始化加载第几页
            pagination:true,   // 是否分页
            sidePagination:'server',
            pageSize:5,
            pageList:[5,10,20],    // 允许选择的每页显示条目数
            showRefresh:true,  // 显示刷新按钮
            queryParams: function (params) {
     
        // 给服务器发参数
               var temp = {
     
     
                  offset:params.offset,
                  pageNumber:params.limit
               };
               return temp;
            },
            columns:[  // 配置有哪些列
               {
     
     
                  title:"编号",
                  field:"id"
               },
               {
     
     
                  title:"姓名",
                  field:"courierName"
               },
               {
     
     
                  title:"手机号码",
                  field:"courierPhone"
               },
               {
     
     
                  title:"身份证",
                  field:"courierIdNumber"
               },
               {
     
     
                  title:"密码",
                  field:"courierPassword"
               },
               {
     
     
                  title:"派件数",
                  field:"courierSendNumber"
               },
               {
     
     
                  title:"注册时间",
                  field:"enrollTime"
               },
               {
     
     
                  title:"上次登录时间",
                  field:"loginTime"
               }
            ]
         });
      });
   </script>
   </body>
</html>

13.3 用户列表

定义专门用于网页展示的类:

public class BootStrapTableUser {
    
    
    private int id;
    private String userName;
    private String userPhone;
    private String userIdNumber;
    private String userPassword;
    private String enrollTime;
    private String loginTime;
    
    // 构造方法,set,get省略
}

用户控制器UserController中添加list方法:

@ResponseBody("/user/list.do")
public String list(HttpServletRequest request, HttpServletResponse response){
    
    
    // 获取查询数据的起始索引值
    int offset = Integer.parseInt(request.getParameter("offset"));
    // 获取当前页要查询的数据量
    int pageNumber = Integer.parseInt(request.getParameter("pageNumber"));
    // 查询
    List<User> list = UserService.findAll(true, offset, pageNumber);
    List<BootStrapTableUser> list2 = new ArrayList<>();
    for(User u : list){
    
    
        String enrollTime = DateFormatUtil.format(u.getEnrollTime());
        String loginTime = u.getLoginTime()==null?"未登录":DateFormatUtil.format(u.getLoginTime());
        BootStrapTableUser u2 = new BootStrapTableUser(u.getId(),u.getUserName(),u.getUserPhone(),u.getUserIdNumber(),"******",enrollTime,loginTime);
        list2.add(u2);
    }
    List<Map<String, Integer>> console = UserService.console();
    Integer total = console.get(0).get("data_size");
    // 将集合封装为 bootstrap-table识别的格式
    ResultData<BootStrapTableUser> data = new ResultData<>();
    data.setRows(list2);
    data.setTotal(total);
    String json = JSONUtil.toJSON(data);
    return json;
}

对应的前端代码 list.html:

<!DOCTYPE html>
<html>
   <head>
      <meta charset="utf-8">
      <title></title>
      <link rel="stylesheet" type="text/css" href="../../../../css/reset.css"/>
      <link rel="stylesheet" type="text/css" href="../../css/list.css"/>
      <link href="https://cdn.bootcdn.net/ajax/libs/bootstrap-table/1.17.1/bootstrap-table.min.css" rel="stylesheet">
      <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
      <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
      <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
      <script src="https://cdn.bootcdn.net/ajax/libs/bootstrap-table/1.17.1/bootstrap-table.min.js"></script>
      <script src="https://cdn.bootcdn.net/ajax/libs/bootstrap-table/1.17.1/locale/bootstrap-table-zh-CN.min.js"></script>
   </head>
   <body>
      <table id="user_list"></table>
      <script>
         $(function () {
     
     
            $("#user_list").bootstrapTable({
     
     
               url:"/user/list.do",    // 数据地址
               striped:true,  // 是否显示行的间隔
               pageNumber:1,  // 初始化加载第几页
               pagination:true,   // 是否分页
               sidePagination:'server',
               pageSize:5,
               pageList:[5,10,20],    // 允许选择的每页显示条目数
               showRefresh:true,  // 显示刷新按钮
               queryParams:function(params){
     
       // 给服务器发参数
                  var temp = {
     
     
                     offset:params.offset,
                     pageNumber:params.limit
                  };
                  return temp;
               },
               columns:[  // 配置有哪些列
                  {
     
     
                     title:"编号",
                     field:"id",
                  },
                  {
     
     
                     title:"昵称",
                     field:"userName",
                  },
                  {
     
     
                     title:"手机号码",
                     field:"userPhone",
                  },
                  {
     
     
                     title:"密码",
                     field:"userPassword",
                  },
                  {
     
     
                     title:"注册时间",
                     field:"enrollTime",
                  },
                  {
     
     
                     title:"登录时间",
                     field:"loginTime",
                  }
               ]
            });
         });
      </script>
   </body>
</html>

14 增删改查

14.1 快递相关

14.1.1 快递录入

express/add.html
前端页面向后台传入number,company,username,userPhone

新建工具类,根据session获取当前管理员的用户名与手机号:

package com.wangjiawei.util;

import javax.servlet.http.HttpSession;

/**
 * 2 * @Author: 小王同学
 * 3 * @Date: 2020/10/6 11:32
 * 4
 */
public class UserUtil {
    
    

    public static String getUserName(HttpSession session){
    
    
        return "";
    }

    public static String getUserPhone(HttpSession session){
    
    
        // TODO: 还没有编写柜子端,未存储任何录入人信息
        return "";
    }
}

ExpressController中添加insert方法:

@ResponseBody("/express/insert.do")
public String insert(HttpServletRequest request, HttpServletResponse response){
    
    
    String number = request.getParameter("number");
    String company = request.getParameter("company");
    String username = request.getParameter("username");
    String userPhone = request.getParameter("userPhone");

    Express e = new Express(number, username, userPhone, company, UserUtil.getUserPhone(request.getSession()));

    boolean flag = ExpressService.insert(e);

    Message msg = new Message();

    if (flag){
    
    
        msg.setStatus(0);
        msg.setResult("快递录入成功");
    }else{
    
    
        msg.setStatus(-1);
        msg.setResult("快递录入失败");
    }
    String json = JSONUtil.toJSON(msg);
    return json;
}

对应的前端代码:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <link rel="stylesheet" href="../../assets/css/layui.css">
    <link rel="stylesheet" href="../../assets/css/view.css"/>
    <title></title>
</head>
<body class="layui-view-body">
    <div class="layui-content">
        <div class="layui-row">
            <div class="layui-card">
                <div class="layui-card-header">录入快件</div>
                <form id="form" class="layui-form layui-card-body">
                  <div class="layui-form-item">
                    <label class="layui-form-label">单号</label>
                    <div class="layui-input-block">
                      <input type="text" name="code" required  lay-verify="required" placeholder="请输入快递单号" autocomplete="off" class="layui-input">
                    </div>
                  </div>
                  <div class="layui-form-item">
                    <label class="layui-form-label">快递公司</label>
                    <div class="layui-input-block">
                      <select name="company" lay-verify="" lay-search>
                  <option >安能快递</option><option >安能物流</option><option >澳大利亚邮政</option><option >阿根廷邮政</option><option >爱沙尼亚邮政</option><option >阿联酋邮政</option><option >奥地利邮政</option><option >阿尔巴尼亚邮政</option><option >Aramex</option><option >巴西邮政</option><option >比利时邮政</option><option >百世快运</option><option >波兰邮政</option><option >白俄罗斯邮政</option><option >保加利亚邮政</option><option >巴基斯坦邮政</option><option >百福东方</option><option >包裹信件</option><option >晟邦物流</option><option >城市100</option><option >City-Link</option><option >COE</option><option >传喜物流</option><option >德邦快递</option><option >大田物流</option><option >递四方</option><option >DHL德国</option><option >DHL全球</option><option >DHL中国</option><option >EMS</option><option >EMS国际</option><option >EMS经济快递</option><option >FedEx中国</option><option >FedEx国际</option><option >FedEx美国</option><option >飞豹快递</option><option >凡宇快递</option><option >飞远配送</option><option >飞远(爱彼西)</option><option >法国邮政</option><option >芬兰邮政</option><option >国通快递</option><option >postco</option><option >百世快递</option><option >恒路物流</option><option >黄马甲配送</option><option >黑猫宅急便</option><option >华企快运</option><option >韩国邮政</option><option >佳吉快运</option><option >京东快递</option><option >佳怡物流</option><option "jinguangsudikuaijian">京广速递</option><option >日本邮政</option><option >筋斗云物流</option><option >捷克邮政</option><option >嘉里大通</option><option >加运美</option><option >快捷快递</option><option >跨越速运</option><option >克罗地亚邮政</option><option >联昊通</option><option >龙邦速递</option><option >黎巴嫩邮政</option><option >民航快递</option><option >秘鲁邮政</option><option >毛里求斯邮政</option><option >马耳他邮政</option><option >摩尔多瓦邮政</option><option >马其顿邮政</option><option >民邦快递</option><option "szml56">明亮物流</option><option >挪威邮政</option><option >南非邮政</option><option >OnTrac</option><option >葡萄牙邮政</option><option >全峰快递</option><option >全一快递</option><option >如风达</option><option >申通快递</option><option selected="selected">顺丰速运</option><option >速尔快递</option><option >盛丰物流</option><option >圣安物流</option><option >盛辉物流</option><option >瑞士邮政</option><option >苏宁快递</option><option >斯洛伐克邮政</option><option >沙特邮政</option><option >斯洛文尼亚邮政</option><option >塞尔维亚邮政</option><option >天天快递</option><option >天地华宇</option><option >土耳其邮政</option><option >泰国邮政</option><option >TNT</option><option >UPS</option><option >USPS</option><option >万象物流</option><option >乌克兰邮政</option><option >万家物流</option><option >信丰物流</option><option >新邦物流</option><option >西班牙邮政</option><option >匈牙利邮政</option><option >圆通速递</option><option >韵达快递</option><option >优速物流</option><option >银捷速递</option><option >远成物流</option><option >运通中港快递</option><option >邮政国内小包</option><option >英国皇家邮政</option><option >意大利邮政</option><option >印度邮政</option><option >亚美尼亚邮政</option><option >越丰物流</option><option >亚风速递</option><option >邮政国际包裹</option><option >中通快递</option><option >宅急送</option><option >中铁物流</option><option >增益速递</option><option >中铁快运</option><option >芝麻开门</option><option >中国邮政</option><option >智利邮政</option><option >中速快递</option>
               </select>

                    </div>
                  </div>
                  <div class="layui-form-item">
                    <label class="layui-form-label">收件人姓名</label>
                    <div class="layui-input-block">
                      <input type="text" name="username" required  lay-verify="required" placeholder="请输入收货人姓名" autocomplete="off" class="layui-input">
                    </div>
                  </div>
                  <div class="layui-form-item">
                    <label class="layui-form-label">手机号码</label>
                    <div class="layui-input-block">
                      <input type="text" name="phonenumber" required  lay-verify="required" placeholder="请输入手机号码" autocomplete="off" class="layui-input">
                    </div>
                  </div>
                  <div class="layui-form-item">
                    <div class="layui-input-block">
                      <button class="layui-btn layui-btn-blue" lay-submit lay-filter="formDemo">立即提交</button>
                      <button type="reset" class="layui-btn layui-btn-primary">重置</button>
                    </div>
                  </div>
                </form>  
            </div>
        </div>
    </div>
    <script src="../../assets/layui.all.js"></script>
    <script src="/qrcode/jquery2.1.4.js"></script>
    <script src="/layer/layer.js"></script>
    <script>
      var form = layui.form
        ,layer = layui.layer;
    </script>
    <script>
        $(function () {
     
     
            $("#form").submit(function () {
     
     
                var windowId = layer.load();
                var number = $("input:eq(0)").val();
                var company = $("input:eq(1)").val();
                var username = $("input:eq(2)").val();
                var userPhone = $("input:eq(3)").val();

                $.post("/express/insert.do",{
     
     
                    number:number,
                    company:company,
                    username:username,
                    userPhone:userPhone
                }, function (data) {
     
     
                    layer.close(windowId);
                    layer.msg(data.result);
                    if (data.status == 0){
     
     
                        // 录入成功,恢复默认
                        $("input").val("");
                        $("input:eq(1)").val("顺丰速运");
                    }else{
     
     
                        // 录入失败
                    }
                });
                return false;
            });
        });
    </script>
</body>
</html>

14.1.2 删除和修改

  删除和修改之前,要先根据快递单号查询出来这个快递,再进行相应的操作。
查询相关的ExpressController中的方法find:

@ResponseBody("/express/find.do")
public String find(HttpServletRequest request, HttpServletResponse response){
    
    
    String number = request.getParameter("number");
    Express e = ExpressService.findByNumber(number);
    Message msg = new Message();

    if (e == null){
    
    
        msg.setStatus(-1);
        msg.setResult("单号不存在");
    }else {
    
    
        msg.setStatus(0);
        msg.setResult("查询成功");
        msg.setData(e);
    }

    String json = JSONUtil.toJSON(msg);
    return json;

}

更新相关的ExpressController中的方法update:

@ResponseBody("/express/update.do")
public String update(HttpServletRequest request, HttpServletResponse response){
    
    
    int id = Integer.parseInt(request.getParameter("id"));
    String number = request.getParameter("number");
    String company = request.getParameter("company");
    String username = request.getParameter("username");
    String userPhone = request.getParameter("userPhone");
    int status = Integer.parseInt(request.getParameter("status"));

    Express newExpress = new Express();
    newExpress.setNumber(number);
    newExpress.setCompany(company);
    newExpress.setUsername(username);
    newExpress.setUserPhone(userPhone);
    newExpress.setStatus(status);
    Message msg = new Message();
    boolean flag = ExpressService.update(id, newExpress);
    if (flag){
    
    
        msg.setStatus(0);
        msg.setResult("修改成功");
    }else {
    
    
        msg.setStatus(-1);
        msg.setResult("修改失败");
    }
    String json = JSONUtil.toJSON(msg);
    return json;
}

删除相关的ExpressController中的方法delete:

@ResponseBody("/express/delete.do")
public String delete(HttpServletRequest request, HttpServletResponse response){
    
    
    int id = Integer.parseInt(request.getParameter("id"));
    boolean flag = ExpressService.delete(id);
    Message msg = new Message();
    if (flag){
    
    
        msg.setStatus(0);
        msg.setResult("删除成功");
    }else {
    
    
        msg.setStatus(-1);
        msg.setResult("删除失败");
    }
    String json = JSONUtil.toJSON(msg);
    return json;
}

更新界面update.html:

<!DOCTYPE html>
<html>
   <head>
      <meta charset="utf-8">
      <title></title>
      <link rel="stylesheet" type="text/css" href="../../css/reset.css"/>
      <link rel="stylesheet" type="text/css" href="../../css/add.css"/>
      <style>
         .layui-layer-content{
     
     
            color: #fff;
         }
      </style>
   </head>
   <body>
      <div id="app">
         <div class="header">
            <span>修改快递信息</span>
         </div>
         <div class="content">
            <table>    
               <tr>
                  <td class="text-right">运单号</td><td class="content_right"><input id="number" class="input inline-input" placeholder="请输入运单号码"> <span id="find" class="btn btn-info">立即查找</span></td>
               </tr>
            </table>
         </div>
         
         
         <div class="header">
            <span>查找信息如下</span>
         </div>
         <div class="content">
            <table>
               <tr>
                  <td class="text-right">快递单号</td><td class="content_right"><input class="input" placeholder="请输入姓名"></td>
               </tr>
               <tr>
                  <td class="text-right">快递公司</td><td class="content_right"><input class="input" placeholder="请输入姓名"></td>
               </tr>
               <tr>
                  <td class="text-right">收货人姓名</td><td class="content_right"><input class="input" placeholder="请输入姓名"></td>
               </tr>
               <tr>
                  <td class="text-right">手机号码</td><td class="content_right"><input class="input" placeholder="请输入姓名"></td>
               </tr>
               <tr>
                  <td class="text-right">快递状态</td><td class="content_right"><input type="radio" name="status" class="status" value="1">已签收  <input name="status" type="radio" class="status" value="0">未签收</td>
               </tr>
               <tr>
                  <td></td><td class="content_right"><span id="update" class="btn btn-info">立即修改</span> <span class="btn">重置</span> </td>
               </tr>
            </table>
         </div>
      </div>
   </body>

   <script src="/qrcode/jquery2.1.4.js"></script>
   <script src="/layer/layer.js"></script>
   <script>
      $(".header:eq(1), .content:eq(1)").hide();
      var expressId = null;
      var g_userPhone = null;
      $(function () {
     
     
         $("#find").click(function () {
     
     
            var windowId = layer.load();
            var number = $("#number").val();
            $.getJSON("/express/find.do",{
     
     number:number},function (data) {
     
     
               layer.close(windowId);
               // {
     
     
               //     "status": 0,
               //        "result": "查询成功",
               //        "data": {
     
     
               //           "id": 2,
               //                 "number": "124",
               //                 "username": "张三",
               //                 "userPhone": "13843838438",
               //                 "company": "京东快递",
               //                 "code": "213456",
               //                 "inTime": "Oct 3, 2020 2:34:30 PM",
               //                 "status": 0,
               //                 "sysPhone": "18888888888"
               //        }
               // }
               layer.msg(data.result);
               if (data.status == 0){
     
     
                  // 淡入效果
                  $(".header:eq(1), .content:eq(1)").fadeIn(1000);
                  expressId = data.data.id;
                  g_userPhone = data.data.userPhone;
                  $("input:eq(1)").val(data.data.number);
                  $("input:eq(2)").val(data.data.company);
                  $("input:eq(3)").val(data.data.username);
                  $("input:eq(4)").val(data.data.userPhone);
                  if (data.data.status == 0){
     
     
                     // 未签收
                     $(".status:eq(1)").prop("checked", true);
                  }else {
     
     
                     // 已签收
                     $(".status:eq(0)").prop("checked", true);
                  }
               }
            });
         });

         $("#update").click(function () {
     
     
            var windowId = layer.load();
            var number = $("input:eq(1)").val();
            var company = $("input:eq(2)").val();
            var username = $("input:eq(3)").val();
            var userPhone = $("input:eq(4)").val();
            var status = $(".status:checked").val();

            var express = {
     
     
               id:expressId,
               number:number,
               company:company,
               username:username,
               status:status
            };

            if (userPhone != g_userPhone){
     
     
               express.userPhone = userPhone;
            }

            console.log(express);

            $.getJSON("/express/update.do",express,function (data) {
     
     
               layer.close(windowId);
               layer.msg(data.result);
               if (data.status == 0){
     
     
                  // 修改成功
                  $(".header:eq(1), .content:eq(1)").hide();
               }
            });
         });
      });
   </script>
</html>

删除界面delete.html:

<!DOCTYPE html>
<html>
   <head>
      <meta charset="utf-8">
      <title></title>
      <link rel="stylesheet" type="text/css" href="../../css/reset.css"/>
      <link rel="stylesheet" type="text/css" href="../../css/add.css"/>
      <style>
         /*单独设置弹窗字体颜色使其显示*/
         .layui-layer-content{
     
     
            color: #fff;
         }
      </style>
   </head>
   <body>
      <div id="app">
         <div class="header">
            <span>删除快递信息</span>
         </div>
         <div class="content">
            <table>    
               <tr>
                  <td class="text-right">运单号</td><td class="content_right"><input id="number" class="input inline-input" placeholder="请输入运单号码"> <span id="find" class="btn btn-info">立即查找</span></td>
               </tr>
            </table>
         </div>
         
         
         <div class="header">
            <span>查找信息如下</span>
         </div>
         <div class="content">
            <table>
               <tr>
                  <td class="text-right">快递单号</td><td class="content_right"><input class="input" placeholder="请输入姓名"></td>
               </tr>
               <tr>
                  <td class="text-right">快递公司</td><td class="content_right"><input class="input" placeholder="请输入姓名"></td>
               </tr>
               <tr>
                  <td class="text-right">收货人姓名</td><td class="content_right"><input class="input" placeholder="请输入姓名"></td>
               </tr>
               <tr>
                  <td class="text-right">手机号码</td><td class="content_right"><input class="input" placeholder="请输入姓名"></td>
               </tr>
               <tr>
                  <td class="text-right">快递状态</td><td class="content_right" id="status">已签收</td>
               </tr>
               <tr>
                  <td></td><td class="content_right"><span id="delete" class="btn btn-info">立即删除</span></td>
               </tr>
            </table>
         </div>
      </div>
   </body>

   <script src="/qrcode/jquery2.1.4.js"></script>
   <script src="/layer/layer.js"></script>
   <script>
      $(".header:eq(1), .content:eq(1)").hide();
      var expressId = null;
      $(function () {
     
     
         $("#find").click(function () {
     
     
            var windowId = layer.load();
            var number = $("#number").val();
            $.getJSON("/express/find.do",{
     
     number:number},function (data) {
     
     
               layer.close(windowId);
               // {
     
     
               //     "status": 0,
               //        "result": "查询成功",
               //        "data": {
     
     
               //           "id": 2,
               //                 "number": "124",
               //                 "username": "张三",
               //                 "userPhone": "13843838438",
               //                 "company": "京东快递",
               //                 "code": "213456",
               //                 "inTime": "Oct 3, 2020 2:34:30 PM",
               //                 "status": 0,
               //                 "sysPhone": "18888888888"
               //        }
               // }
               layer.msg(data.result);
               if (data.status == 0){
     
     
                  // 淡入效果
                  $(".header:eq(1), .content:eq(1)").fadeIn(1000);
                  expressId = data.data.id;
                  $("input:eq(1)").val(data.data.number);
                  $("input:eq(2)").val(data.data.company);
                  $("input:eq(3)").val(data.data.username);
                  $("input:eq(4)").val(data.data.userPhone);
                  $("input:eq(1),input:eq(2),input:eq(3),input:eq(4)").prop("disabled",true)
                  if (data.data.status == 0){
     
     
                     // 未签收
                     $("#status").html("未签收");
                  }else {
     
     
                     // 已签收
                     $("#status").html("已签收");
                  }
               }
            });
         });

         $("#delete").click(function () {
     
     
            if (confirm("确定要删除吗?")){
     
     
               var windowId = layer.load();
               $.getJSON("/express/delete.do",{
     
     id:expressId},function (data) {
     
     
                  layer.close(windowId);
                  layer.msg(data.result);
                  if (data.status == 0){
     
     
                     $(".header:eq(1), .content:eq(1)").hide();
                  }
               });
            }
         });
      });
   </script>
</html>

14.2 快递员相关

14.2.1 快递员录入

CourierController中添加insert方法:

@ResponseBody("/courier/insert.do")
public String insert(HttpServletRequest request, HttpServletResponse response){
    
    
    String courierName = request.getParameter("courierName");
    String courierPhone = request.getParameter("courierPhone");
    String courierIdNumber = request.getParameter("courierIdNumber");
    String courierPassword = request.getParameter("courierPassword");
    Courier c = new Courier(courierName,courierPhone,courierIdNumber,courierPassword);
    boolean flag = CourierService.insert(c);
    Message msg = new Message();
    if (flag){
    
    
        msg.setStatus(0);
        msg.setResult("快递员录入成功");
    }else {
    
    
        msg.setStatus(-1);
        msg.setResult("快递员录入失败");
    }
    String json = JSONUtil.toJSON(msg);
    return json;
}

对应的前端代码:

<!DOCTYPE html>
<html>
   <head>
      <meta charset="utf-8">
      <title></title>
      <link rel="stylesheet" type="text/css" href="../../css/reset.css"/>
      <link rel="stylesheet" type="text/css" href="../../css/add.css"/>
      <style>
         .layui-layer-content{
     
     
            color: #fff;
         }
         #add_btn{
     
     
            cursor: pointer;
         }
         #reset_btn{
     
     
            cursor: pointer;
         }
      </style>
   </head>
   <body>
      <div id="app">
         <div class="header">
            <span>添加快递员</span>
         </div>
         <div class="content">
            <table>
               <tr>
                  <td class="text-right">姓名</td><td class="content_right"><input class="input" placeholder="请输入姓名"></td>
               </tr>
               <tr>
                  <td class="text-right">手机号码</td><td class="content_right"><input class="input" placeholder="请输入手机号码"></td>
               </tr>
               <tr>
                  <td class="text-right">身份证号码</td><td class="content_right"><input class="input" placeholder="请输入身份证号码"></td>
               </tr>
               <tr>
                  <td class="text-right">密码</td><td class="content_right"><input class="input" placeholder="请输入密码"></td>
               </tr>
               <tr>
                  <td></td><td class="content_right"><span id="add_btn" class="btn btn-info">立即提交</span> <span id="reset_btn" class="btn">重置</span> </td>
               </tr>
            </table>
         </div>
      </div>
      <script src="../../assets/layui.all.js"></script>
      <script src="/qrcode/jquery2.1.4.js"></script>
      <script src="/layer/layer.js"></script>
      <script>
         $(function () {
     
     
            $("#add_btn").click(function () {
     
     
               var windowId = layer.load();
               var courierName = $("input:eq(0)").val();
               var courierPhone = $("input:eq(1)").val();
               var courierIdNumber = $("input:eq(2)").val();
               var courierPassword = $("input:eq(3)").val();

               $.post("/courier/insert.do",{
     
     
                  courierName:courierName,
                  courierPhone:courierPhone,
                  courierIdNumber:courierIdNumber,
                  courierPassword:courierPassword
               },function (data) {
     
     
                  layer.close(windowId);
                  layer.msg(data.result);
                  if (data.status == 0){
     
     
                     // 录入成功,恢复默认
                     $("input").val("");
                  }
               });
            });

            $("#reset_btn").click(function () {
     
     
               $("input").val("");
            });
         });
      </script>
   </body>
</html>

14.2.2 删除和修改

先查询然后再删除和修改:
查询相关的CourierController中的方法find:

@ResponseBody("/courier/find.do")
public String find(HttpServletRequest request, HttpServletResponse response){
    
    
    String courierPhone = request.getParameter("courierPhone");
    Courier c = CourierService.findByPhone(courierPhone);
    Message msg = new Message();

    if (c == null){
    
    
        msg.setStatus(-1);
        msg.setResult("手机号不存在");
    }else {
    
    
        msg.setStatus(0);
        msg.setResult("查询成功");
        msg.setData(c);
    }

    String json = JSONUtil.toJSON(msg);
    return json;
}

更新相关的CourierController中的方法update:

@ResponseBody("/courier/update.do")
public String update(HttpServletRequest request, HttpServletResponse response){
    
    
    int id = Integer.parseInt(request.getParameter("id"));
    String courierName = request.getParameter("courierName");
    String courierPhone = request.getParameter("courierPhone");
    String courierIdNumber = request.getParameter("courierIdNumber");
    String courierPassword = request.getParameter("courierPassword");

    Courier newCourier = new Courier(courierName,courierPhone,courierIdNumber,courierPassword);
    Message msg = new Message();
    boolean flag = CourierService.update(id, newCourier);
    if (flag){
    
    
        msg.setStatus(0);
        msg.setResult("修改成功");
    }else {
    
    
        msg.setStatus(-1);
        msg.setResult("修改失败");
    }
    String json = JSONUtil.toJSON(msg);
    return json;
}

删除相关的CourierController中的方法delete:

@ResponseBody("/courier/delete.do")
public String delete(HttpServletRequest request, HttpServletResponse response){
    
    
    int id = Integer.parseInt(request.getParameter("id"));
    boolean flag = CourierService.delete(id);
    Message msg = new Message();
    if (flag){
    
    
        msg.setStatus(0);
        msg.setResult("删除成功");
    }else {
    
    
        msg.setStatus(-1);
        msg.setResult("删除失败");
    }
    String json = JSONUtil.toJSON(msg);
    return json;
}

更新界面update.html:

<!DOCTYPE html>
<html>
   <head>
      <meta charset="utf-8">
      <title></title>
      <link rel="stylesheet" type="text/css" href="../../css/reset.css"/>
      <link rel="stylesheet" type="text/css" href="../../css/add.css"/>
      <style>
         .layui-layer-content{
     
     
            color: #fff;
         }
         #find,#update_btn,#reset_btn{
     
     
            cursor: pointer;
         }
      </style>
   </head>
   <body>
      <div id="app">
         <div class="header">
            <span>修改快递员</span>
         </div>
         <div class="content">
            <table>    
               <tr>
                  <td class="text-right">手机号码</td><td class="content_right"><input id="courierPhone" class="input inline-input" placeholder="请输入手机号码"> <span id="find" class="btn btn-info">立即查找</span></td>
               </tr>
            </table>
         </div>
         
         
         <div class="header">
            <span>查找信息如下</span>
         </div>
         <div class="content">
            <table>
               <tr>
                  <td class="text-right">姓名</td><td class="content_right"><input class="input" placeholder="请输入姓名"></td>
               </tr>
               <tr>
                  <td class="text-right">手机号码</td><td class="content_right"><input class="input" placeholder="请输入手机号码"></td>
               </tr>
               <tr>
                  <td class="text-right">身份证号码</td><td class="content_right"><input class="input" placeholder="请输入身份证号码"></td>
               </tr>
               <tr>
                  <td class="text-right">密码</td><td class="content_right"><input class="input" placeholder="请输入密码"></td>
               </tr>
               <tr>
                  <td></td><td class="content_right"><span id="update_btn" class="btn btn-info">立即修改</span> <span id="reset_btn" class="btn">重置</span> </td>
               </tr>
            </table>
         </div>
      </div>
   </body>

   <script src="/qrcode/jquery2.1.4.js"></script>
   <script src="/layer/layer.js"></script>
   <script>
      $(".header:eq(1), .content:eq(1)").hide();
      var courierId = null;
      $(function () {
     
     
         $("#find").click(function () {
     
     
            var windowId = layer.load();
            var courierPhone = $("#courierPhone").val();
            $.getJSON("/courier/find.do",{
     
     courierPhone:courierPhone},function (data) {
     
     
               layer.close(windowId);
               // {
     
     
               //     "status": 0,
               //        "result": "查询成功",
               //        "data": {
     
     
               //           "id": 1003,
               //           "courierName": "快递王五",
               //           "courierPhone": "18373110779",
               //           "courierIdNumber": "411303111111111113",
               //           "courierPassword": "123",
               //           "courierSendNumber": 111111,
               //           "enrollTime": "Oct 8, 2020 7:50:24 PM",
               //           "loginTime": "Oct 8, 2020 7:50:23 PM"
               //        }
               // }
               layer.msg(data.result);
               if (data.status == 0){
     
     
                  // 淡入效果
                  $(".header:eq(1), .content:eq(1)").fadeIn(1000);
                  courierId = data.data.id;
                  $("input:eq(1)").val(data.data.courierName);
                  $("input:eq(2)").val(data.data.courierPhone);
                  $("input:eq(3)").val(data.data.courierIdNumber);
                  $("input:eq(4)").val(data.data.courierPassword);
               }
            });
         });

         $("#update_btn").click(function () {
     
     
            var windowId = layer.load();
            var courierName = $("input:eq(1)").val();
            var courierPhone = $("input:eq(2)").val();
            var courierIdNumber = $("input:eq(3)").val();
            var courierPassword = $("input:eq(4)").val();

            var courier = {
     
     
               id:courierId,
               courierName:courierName,
               courierPhone:courierPhone,
               courierIdNumber:courierIdNumber,
               courierPassword:courierPassword
            }

            console.log(courier);

            $.getJSON("/courier/update.do", courier, function (data) {
     
     
               layer.close(windowId);
               layer.msg(data.result);
               if (data.status == 0){
     
     
                  // 修改成功
                  $(".header:eq(1), .content:eq(1)").hide();
               }
            });
         });
      });

   </script>
</html>

删除界面delete.html:

<!DOCTYPE html>
<html>
   <head>
      <meta charset="utf-8">
      <title></title>
      <link rel="stylesheet" type="text/css" href="../../css/reset.css"/>
      <link rel="stylesheet" type="text/css" href="../../css/add.css"/>
      <style>
         /*单独设置弹窗字体颜色使其显示*/
         .layui-layer-content{
     
     
            color: #fff;
         }
         #find,#delete_btn,#reset_btn{
     
     
            cursor: pointer;
         }
      </style>
   </head>
   <body>
      <div id="app">
         <div class="header">
            <span>删除快递员</span>
         </div>
         <div class="content">
            <table>    
               <tr>
                  <td class="text-right">手机号码</td><td class="content_right"><input id="courierPhone" class="input inline-input" placeholder="请输入手机号码"> <span id="find" class="btn btn-info">立即查找</span></td>
               </tr>
            </table>
         </div>
         
         
         <div class="header">
            <span>查找信息如下</span>
         </div>
         <div class="content">
            <table>
               <tr>
                  <td class="text-right">姓名</td><td class="content_right"><input class="input" placeholder="请输入姓名"></td>
               </tr>
               <tr>
                  <td class="text-right">手机号码</td><td class="content_right"><input class="input" placeholder="请输入手机号码"></td>
               </tr>
               <tr>
                  <td class="text-right">身份证号码</td><td class="content_right"><input class="input" placeholder="请输入身份证号码"></td>
               </tr>
               <tr>
                  <td class="text-right">密码</td><td class="content_right"><input class="input" placeholder="请输入密码"></td>
               </tr>
               <tr>
                  <td></td><td class="content_right"><span id="delete_btn" class="btn btn-info">立即删除</span> <span id="reset_btn" class="btn">重置</span> </td>
               </tr>
            </table>
         </div>
      </div>
   </body>
   <script src="/qrcode/jquery2.1.4.js"></script>
   <script src="/layer/layer.js"></script>
   <script>
      $(".header:eq(1), .content:eq(1)").hide();
      var courierId = null;
      $(function () {
     
     
         $("#find").click(function () {
     
     
            var windowId = layer.load();
            var courierPhone = $("#courierPhone").val();
            $.getJSON("/courier/find.do",{
     
     courierPhone:courierPhone},function (data) {
     
     
               layer.close(windowId);
               layer.msg(data.result);
               if (data.status == 0){
     
     
                  // 淡入效果
                  $(".header:eq(1), .content:eq(1)").fadeIn(1000);
                  courierId = data.data.id;
                  $("input:eq(1)").val(data.data.courierName);
                  $("input:eq(2)").val(data.data.courierPhone);
                  $("input:eq(3)").val(data.data.courierIdNumber);
                  $("input:eq(4)").val(data.data.courierPassword);
               }
            });
         });

         $("#delete_btn").click(function () {
     
     
            if (confirm("确定要删除吗?")){
     
     
               var windowId = layer.load();
               $.getJSON("/courier/delete.do",{
     
     id:courierId},function (data) {
     
     
                  layer.close(windowId);
                  layer.msg(data.result);
                  if (data.status == 0){
     
     
                     $(".header:eq(1), .content:eq(1)").hide();
                  }
               });
            }
         });
      });
   </script>
</html>

14.3 用户相关

14.3.1 用户录入

UserController中添加insert方法:

@ResponseBody("/user/insert.do")
public String insert(HttpServletRequest request, HttpServletResponse response){
    
    
    String userName = request.getParameter("userName");
    String userPhone = request.getParameter("userPhone");
    String userIdNumber = request.getParameter("userIdNumber");
    String userPassword = request.getParameter("userPassword");
    User u = new User(userName, userPhone, userIdNumber, userPassword);
    boolean flag = UserService.insert(u);
    Message msg = new Message();
    if (flag){
    
    
        msg.setStatus(0);
        msg.setResult("用户录入成功");
    }else{
    
    
        msg.setStatus(-1);
        msg.setResult("用户录入失败");
    }
    String json = JSONUtil.toJSON(msg);
    return json;
}

对应的前端代码:

<!DOCTYPE html>
<html>
   <head>
      <meta charset="utf-8">
      <title></title>
      <link rel="stylesheet" type="text/css" href="../../css/reset.css"/>
      <link rel="stylesheet" type="text/css" href="../../css/add.css"/>
      <style>
         .layui-layer-content{
     
     
            color: #fff;
         }
         #add_btn{
     
     
            cursor: pointer;
         }
         #reset_btn{
     
     
            cursor: pointer;
         }
      </style>
   </head>
   <body>
      <div id="app">
         <div class="header">
            <span>添加用户</span>
         </div>
         <div class="content">
            <table>
               <tr>
                  <td class="text-right">姓名</td><td class="content_right"><input class="input" placeholder="请输入姓名"></td>
               </tr>
               <tr>
                  <td class="text-right">手机号码</td><td class="content_right"><input class="input" placeholder="请输入手机号码"></td>
               </tr>
               <tr>
                  <td class="text-right">身份证号码</td><td class="content_right"><input class="input" placeholder="请输入身份证号码"></td>
               </tr>
               <tr>
                  <td class="text-right">密码</td><td class="content_right"><input class="input" placeholder="请输入密码"></td>
               </tr>
               <tr>
                  <td></td><td class="content_right"><span id="add_btn" class="btn btn-info">立即提交</span> <span id="reset_btn" class="btn">重置</span> </td>
               </tr>
            </table>
         </div>
      </div>
      <script src="../../assets/layui.all.js"></script>
      <script src="/qrcode/jquery2.1.4.js"></script>
      <script src="/layer/layer.js"></script>
      <script>

         function checkName(){
     
     
            var userName = $("input:eq(0)").val();
            if (userName == null || userName.length == 0){
     
     
               alert("用户名有误");
               console.log("false");
               return false;
            }
            console.log("true");
            return true;
         }

         function checkPhone(){
     
     
            var userPhone = $("input:eq(1)").val();
            var reg = /^1[3456789]\d{9}$/;
            if (!reg.test(userPhone)){
     
     
               alert("手机号码有误");
               console.log("false");
               return false;
            }
            console.log("true");
            return true;
         }

         function checkIdNumber(){
     
     
            var userIdNumber = $("input:eq(2)").val();
            var reg = /^[1-9]\d{5}(18|19|20|(3\d))\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/;
            if (!reg.test(userIdNumber)){
     
     
               alert("身份证号码有误");
               console.log("false");
               return false;
            }
            console.log("true");
            return true;
         }

         function checkPassword(){
     
     
            var userPassword = $("input:eq(3)").val();
            var reg = /^\w{3,20}$/;
            if (!reg.test(userPassword)){
     
     
               alert("密码有误");
               console.log("false");
               return false;
            }
            console.log("true");
            return true;
         }


         $(function () {
     
     
            $("#add_btn").click(function () {
     
     
               if (checkName() && checkPhone() && checkPassword() && checkIdNumber()){
     
     
                  var windowId = layer.load();
                  var userName = $("input:eq(0)").val();
                  var userPhone = $("input:eq(1)").val();
                  var userIdNumber = $("input:eq(2)").val();
                  var userPassword = $("input:eq(3)").val();

                  $.post("/user/insert.do",{
     
     
                     userName:userName,
                     userPhone:userPhone,
                     userIdNumber:userIdNumber,
                     userPassword:userPassword
                  },function (data) {
     
     
                     layer.close(windowId);
                     layer.msg(data.result);
                     if (data.status == 0){
     
     
                        // 录入成功,恢复默认
                        $("input").val("");
                     }
                  });
               }
            });

            $("#reset_btn").click(function () {
     
     
               $("input").val("");
            });
         });
      </script>
   </body>
</html>

14.3.2 删除和修改

先查询然后再删除和修改:
查询相关的UserController中的方法find:

@ResponseBody("/user/find.do")
public String find(HttpServletRequest request, HttpServletResponse response){
    
    
    String userPhone = request.getParameter("userPhone");
    User u = UserService.findByUserPhone(userPhone);
    Message msg = new Message();
    if (u == null){
    
    
        msg.setStatus(-1);
        msg.setResult("手机号不存在");
    }else {
    
    
        msg.setStatus(0);
        msg.setResult("查询成功");
        msg.setData(u);
    }
    String json = JSONUtil.toJSON(msg);
    return json;
}

更新相关的UserController中的方法update:

@ResponseBody("/user/update.do")
public String update(HttpServletRequest request, HttpServletResponse response){
    
    
    int id = Integer.parseInt(request.getParameter("id"));
    String userName = request.getParameter("userName");
    String userPhone = request.getParameter("userPhone");
    String userIdNumber = request.getParameter("userIdNumber");
    String userPassword = request.getParameter("userPassword");
    User newUser = new User(userName,userPhone,userIdNumber,userPassword);
    Message msg = new Message();
    boolean flag = UserService.update(id, newUser);
    if (flag){
    
    
        msg.setStatus(0);
        msg.setResult("修改成功");
    }else {
    
    
        msg.setStatus(-1);
        msg.setResult("修改失败");
    }
    String json = JSONUtil.toJSON(msg);
    return json;
}

删除相关的UserController中的方法delete:

@ResponseBody("/user/delete.do")
public String delete(HttpServletRequest request, HttpServletResponse response){
    
    
    int id = Integer.parseInt(request.getParameter("id"));
    boolean flag = CourierService.delete(id);
    Message msg = new Message();
    if (flag){
    
    
        msg.setStatus(0);
        msg.setResult("删除成功");
    }else {
    
    
        msg.setStatus(-1);
        msg.setResult("删除失败");
    }
    String json = JSONUtil.toJSON(msg);
    return json;
}

更新界面update.html:

<!DOCTYPE html>
<html>
   <head>
      <meta charset="utf-8">
      <title></title>
      <link rel="stylesheet" type="text/css" href="../../css/reset.css"/>
      <link rel="stylesheet" type="text/css" href="../../css/add.css"/>
      <style>
         .layui-layer-content{
     
     
            color: #fff;
         }
         #find,#update_btn,#reset_btn{
     
     
            cursor: pointer;
         }
      </style>
   </head>
   <body>
      <div id="app">
         <div class="header">
            <span>修改快递员</span>
         </div>
         <div class="content">
            <table>    
               <tr>
                  <td class="text-right">手机号码</td><td class="content_right"><input id="userPhone" class="input inline-input" placeholder="请输入手机号码"> <span id="find" class="btn btn-info">立即查找</span></td>
               </tr>
            </table>
         </div>
         
         
         <div class="header">
            <span>查找信息如下</span>
         </div>
         <div class="content">
            <table>
               <tr>
                  <td class="text-right">姓名</td><td class="content_right"><input class="input" placeholder="请输入姓名"></td>
               </tr>
               <tr>
                  <td class="text-right">手机号码</td><td class="content_right"><input class="input" placeholder="请输入手机号码"></td>
               </tr>
               <tr>
                  <td class="text-right">身份证号码</td><td class="content_right"><input class="input" placeholder="请输入身份证号码"></td>
               </tr>
               <tr>
                  <td class="text-right">密码</td><td class="content_right"><input class="input" placeholder="请输入密码"></td>
               </tr>
               <tr>
                  <td></td><td class="content_right"><span id="update_btn" class="btn btn-info">立即修改</span> <span id="reset_btn" class="btn">重置</span> </td>
               </tr>
            </table>
         </div>
      </div>
   </body>

   <script src="/qrcode/jquery2.1.4.js"></script>
   <script src="/layer/layer.js"></script>
   <script>
      $(".header:eq(1), .content:eq(1)").hide();
      var userId = null;
      $(function () {
     
     
         $("#find").click(function () {
     
     
            var windowId = layer.load();
            var userPhone = $("#userPhone").val();
            $.getJSON("/user/find.do",{
     
     userPhone:userPhone},function (data) {
     
     
               layer.close(windowId);
               // {
     
     
               //     "status": 0,
               //        "result": "查询成功",
               //        "data": {
     
     
               //        "id": 1,
               //           "userName": "陈二",
               //           "userPhone": "13838438438",
               //           "userIdNumber": "411000000000000000",
               //           "userPassword": "123",
               //           "enrollTime": "Oct 9, 2020 9:46:21 AM",
               //           "loginTime": "Oct 9, 2020 9:46:43 AM"
               //        }
               // }
               layer.msg(data.result);
               if (data.status == 0){
     
     
                  // 淡入效果
                  $(".header:eq(1), .content:eq(1)").fadeIn(1000);
                  userId = data.data.id;
                  $("input:eq(1)").val(data.data.userName);
                  $("input:eq(2)").val(data.data.userPhone);
                  $("input:eq(3)").val(data.data.userIdNumber);
                  $("input:eq(4)").val(data.data.userPassword);
               }
            });

            $("#update_btn").click(function () {
     
     
               var windowId = layer.load();
               var userName = $("input:eq(1)").val();
               var userPhone = $("input:eq(2)").val();
               var userIdNumber = $("input:eq(3)").val();
               var userPassword = $("input:eq(4)").val();

               var user = {
     
     
                  id:userId,
                  userName:userName,
                  userPhone:userPhone,
                  userIdNumber:userIdNumber,
                  userPassword:userPassword
               }

               console.log(user);

               $.getJSON("/user/update.do", user, function (data) {
     
     
                  layer.close(windowId);
                  layer.msg(data.result);
                  if (data.status == 0){
     
     
                     // 修改成功
                     $(".header:eq(1), .content:eq(1)").hide();
                  }
               });

            });

         });
      });
   </script>
</html>

删除界面delete.html:

<!DOCTYPE html>
<html>
   <head>
      <meta charset="utf-8">
      <title></title>
      <link rel="stylesheet" type="text/css" href="../../../../css/reset.css"/>
      <link rel="stylesheet" type="text/css" href="../../css/add.css"/>
      <style>
         /*单独设置弹窗字体颜色使其显示*/
         .layui-layer-content{
     
     
            color: #fff;
         }
         #find,#delete_btn{
     
     
            cursor: pointer;
         }
      </style>
   </head>
   <body>
      <div id="app">
         <div class="header">
            <span>删除快递员</span>
         </div>
         <div class="content">
            <table>    
               <tr>
                  <td class="text-right">手机号码</td><td class="content_right"><input id="userPhone" class="input inline-input" placeholder="请输入手机号码"> <span id="find" class="btn btn-info">立即查找</span></td>
               </tr>
            </table>
         </div>
         
         
         <div class="header">
            <span>查找信息如下</span>
         </div>
         <div class="content">
            <table>
               <tr>
                  <td class="text-right">姓名</td><td class="content_right"><input class="input" placeholder="请输入姓名"></td>
               </tr>
               <tr>
                  <td class="text-right">手机号码</td><td class="content_right"><input class="input" placeholder="请输入手机号码"></td>
               </tr>
               <tr>
                  <td class="text-right">身份证号码</td><td class="content_right"><input class="input" placeholder="请输入身份证号码"></td>
               </tr>
               <tr>
                  <td class="text-right">密码</td><td class="content_right"><input class="input" placeholder="请输入密码"></td>
               </tr>
               <tr>
                  <td></td><td class="content_right"><span id="delete_btn" class="btn btn-info">立即删除</span> </td>
               </tr>
            </table>
         </div>
      </div>
   </body>
   <script src="/qrcode/jquery2.1.4.js"></script>
   <script src="/layer/layer.js"></script>
   <script>
      $(".header:eq(1), .content:eq(1)").hide();
      var userId = null;
      $(function () {
     
     
         $("#find").click(function () {
     
     
            var windowId = layer.load();
            var userPhone = $("#userPhone").val();
            $.getJSON("/user/find.do",{
     
     userPhone:userPhone}, function (data) {
     
     
               layer.close(windowId);
               layer.msg(data.result);
               if (data.status == 0){
     
     
                  // 淡入效果
                  $(".header:eq(1), .content:eq(1)").fadeIn(1000);
                  userId = data.data.id;
                  $("input:eq(1)").val(data.data.userName);
                  $("input:eq(2)").val(data.data.userPhone);
                  $("input:eq(3)").val(data.data.userIdNumber);
                  $("input:eq(4)").val(data.data.userPassword);
               }
            });
         });

         $("#delete_btn").click(function () {
     
     
            if (confirm("确定要删除吗?")){
     
     
               var windowId = layer.load();
               $.getJSON("/user/delete.do",{
     
     id:userId},function (data) {
     
     
                  layer.close(windowId);
                  layer.msg(data.result);
                  if (data.status == 0){
     
     
                     $(".header:eq(1), .content:eq(1)").hide();
                  }
               });
            }
         });
      });
   </script>
</html>

15 权限控制

AdminController中把登陆成功的用户存到session里:

@ResponseBody("/admin/login.do")
public String login(HttpServletRequest request, HttpServletResponse response){
    
    
    String username = request.getParameter("username");
    String password = request.getParameter("password");
    boolean result = AdminService.login(username, password);
    // 准备不同的返回数据
    Message msg = null;
    if (result){
    
    
        // {status:0, result:"登录成功"}
        msg = new Message(0, "登录成功");
        // 登录时间和ip的更新
        Date date = new Date();
        String ip = request.getRemoteAddr();
        AdminService.updateLoginTimeAndIp(username, date, ip);
        // 把用户名存到session中
        request.getSession().setAttribute("adminUserName",username);
    }else {
    
    
        // {status:-1, result:"登录失败"}
        msg = new Message(-1, "登录失败");
    }
    String json = JSONUtil.toJSON(msg);
    return json;
}

编写权限控制所需的过滤器:

package com.wangjiawei.filter;

import com.wangjiawei.util.UserUtil;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 2 * @Author: 小王同学
 * 3 * @Date: 2020/10/7 13:42
 * 4
 */
@WebFilter({
    
    "/admin/index.html","/admin/views/*","/express/*"})
public class AccessControllerFilter implements Filter {
    
    
    @Override
    public void destroy() {
    
    
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
    
    
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        String userName = UserUtil.getUserName(request.getSession());
        if (userName != null) {
    
    
            chain.doFilter(req, resp);
        } else {
    
    
            response.sendError(404, "很遗憾,权限不足");
        }

    }

    @Override
    public void init(FilterConfig config) throws ServletException {
    
    

    }

}

猜你喜欢

转载自blog.csdn.net/HNU_Csee_wjw/article/details/109035720
今日推荐