前言

项目的代码已经上传到了我的gitee仓库:https://gitee.com/niaoxi_git/ezhan/

后台

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

微信端

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

1.项目涉及技术点

html、css、js、Jquery、bootstrap、layui、layer、ajax、mysql、tomcat、servlet、filter、listener、jsp、公有云服务器。

2.项目需求分析

2.1后台功能

2.1.1管理员

1.管理员登录

2.管理员退出

2.1.2控制台

1.控制台-显示用户人数

2.控制台-显示快递员人数

3.控制台-显示总快件数

4.控制台-显示等待取件数量

2.1.3快递管理

1.快件增加 2.快件删除 3.快件修改4.快件列表查看

2.1.4用户管理

1.用户增加 2.用户删除3.用户删除 4.用户列表查看

2.1.5快递员管理

1.快递员增加

2.快递员删除

3.快递员修改

4.快递员查询

2.1.6其他

1.后台管理员以及快递员和用户密码采用32位MD5加密

2.前端页面采用layui自带规则验证表单

2.2微信前端功能

2.2.1用户

1.用户/快递员登录

2.用户/快递员注册

3.用户-我的取件列表(未取件/已取件)

4.用户-快件取件码展示

2.2.2快递员

1.快递员-扫码取件

2.快递员-取件码取件

3.首页根据快递单号查询快递信息

4.快递员-录入快递

5.快递员历史查询

2.2.3其他

1.个人中心-昵称显示与修改

2.懒人排行榜

3.自动登录

4.修改密码

3.项目前准备

3.1编写MVC框架

3.1.1MVC框架执行流程原理

servlet -> 映射器 -> 调用方法 -> 将结果返回【html/jsp -> Servlet(*.do) -> int(加载配置文件,建立映射地址池(映射器)) -> 调用方法 -> 将结果返回用户】

3.1.2代码设计

3.1.2.1servlet类:DispatcherServlet.java
package com.xzk.mvc;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
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;

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);
        /*Properties ppt = new Properties();
        try {
            ppt.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        }*/
        HandlerMapping.load(is);
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.获取用户请求的uri /xx.do
        String uri =req.getRequestURI();
        HandlerMapping.MVCMapping mapping = HandlerMapping.get(uri);
        if(mapping == null){
            resp.sendError(404,"自定义MVC:映射地址不存在");
            return;
        }
        Object obj = mapping.getObj();
        Method method = mapping.getMethod();
        Object result =null;
        try {
            result = method.invoke(obj, req, resp);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        switch(mapping.getType()){
            case TEXT:
                resp.getWriter().write((String) result);
                break;
            case VIEW:
                resp.sendRedirect((String) result);
                break;
        }
    }
}
3.1.2.2.配置web.xml
<?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.xzk.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>

3.1.2.3ResponseBody注解(用于返回文字内容给请求者)

package com.xzk.mvc;

import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
/**
 * 注解的作用
 * 被此注解添加的方法,会被用于处理请求
 * 方法返回的内容,会以文字的形式返回到客户端
 */
public @interface ResponseBody {
    String value();
}
3.1.2.4ResponseView注解(法返回的内容,会直接重定向)
package com.xzk.mvc;

import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
/**
 * 注解的作用
 * 被此注解添加的方法,会被用于处理请求
 * 方法返回的内容,会直接重定向
 */
public @interface ResponseView {
    String value();
}
3.1.2.5枚举类ResponseType(记录方法返回值,字符串类型或者视图类型)
package com.xzk.mvc;
public enum ResponserType {
    TEXT,VIEW;
}
3.1.2.6映射器HandlerMapping(加载关联的方法,Map集合建立请求和请求处理方法的键值对)
package com.xzk.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;

/**
 * 映射器(包含了大量的网址与方法的对应关系)
 */
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 cla:values){
            String className = (String) cla;
            try {
                //加载配置文件中描述的每一个类
                Class c = Class.forName(className);
                Object obj = c.getConstructor().newInstance();
                Method[] methods = c.getMethods();
                for(Method m:methods){
                    Annotation[] as = m.getAnnotations();
                    if(as!=null){
                        for(Annotation annotation:as){
                            if(annotation instanceof  ResponseBody){
                                //说明此方法,用于返回字符串给客户端
                                MVCMapping mapping = new MVCMapping(obj,m,ResponserType.TEXT);
                                Object o = data.put(((ResponseBody) annotation).value(), mapping);
                                if(o != null){
                                    //存在了重复的请求地址
                                    throw new RuntimeException("请求地址重复:"+((ResponseBody) annotation).value());
                                }
                            }else if(annotation instanceof ResponseView){
                                //说明此方法,用于返回字符串给客户端
                                MVCMapping mapping = new MVCMapping(obj,m,ResponserType.VIEW);
                                Object o = data.put(((ResponseView) annotation).value(), mapping);
                                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 ResponserType type;

        public MVCMapping() {
        }

        public MVCMapping(Object obj, Method method, ResponserType 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 ResponserType getType() {
            return type;
        }

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

3.1.2.7配置文件application.properties(记录请求处理类,每个类中可能包含0-n个用于处理请求的方法)

3.2框架前的前端补充

二维码生成

步骤:
    1.  引入Jquery.js文件
    2.  引入jquery.qrcode.js文件
    3.  引入支持中文的编码js文件 (utf.js)
    4.  在网页中编写一个div 用于显示二维码
            <div id="div1"></div>
    5.  准备二维码的规格对象(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 可选参数
        };
    6.  通过选择器, 查找到上述的div ,得到Jquery对象, 通过jquery对象的qrcode函数生成二维码
            $("#div1").qrcode(config);

3.3阿里云短信SMSUtil

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

发送短信类代码:

package com.xzk.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;

public class SMSUtil {

    public static boolean send(String phoneNumber,String code) {
        DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", "LTAI4GJVun7NhPS8FMgSqqS4", "TgTLk8KVJjESFu6iC1jTHsVMK53z5Q");
        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_196641606");
        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;
    }
}

3.4数据库链接的方式DruidUtil链接池

package com.xzk.util;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

public class DruidUtil {

    private static DataSource ds;
    static{
        try {
            Properties ppt = new Properties();
            ppt.load(DruidUtil.class.getClassLoader().getResourceAsStream("druid.properties"));
            ds = DruidDataSourceFactory.createDataSource(ppt);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 从连接池中取出一个连接给用户
     * @return
     */
    public static Connection getConnection(){
        try {
            return ds.getConnection();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return null;
    }


    public static void close(Connection conn, Statement state, ResultSet rs){
        try {
            if(rs!=null)
                rs.close();
        } catch (Exception throwables) {
            throwables.printStackTrace();
        }
        try {
            if(state!=null)
                state.close();
        } catch (Exception throwables) {
            throwables.printStackTrace();
        }
        try {
            if(conn!=null)
                conn.close();
        } catch (Exception throwables) {
            throwables.printStackTrace();
        }
    }
}

3.5密码加密机制md5

package com.xzk.util;

import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class MD5Util {
    public String getMD5Str(String str) {
        byte[] digest = null;
        try {
            MessageDigest md5 = MessageDigest.getInstance("md5");
            digest  = md5.digest(str.getBytes("utf-8"));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        //16是表示转换为16进制数
        String md5Str = new BigInteger(1, digest).toString(16);
        return md5Str;
    }
}

3.6生成随机码RandomUtil

package com.xzk.util;

import java.util.Random;

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

}

3.7转换Json格式模块JSONUtil

package com.xzk.util;

import com.google.gson.Gson;

public class JSONUtil {

    private static Gson g = new Gson();
    public static String toJSON(Object obj){
        return g.toJson(obj);
    }
}

3.8日期转换格式DateFormatUtil

package com.xzk.util;

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

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.数据库设计

管理员表

字段名 描述 字段类型
id 自增主键 int
username 用户名 varchar
password 密码 varchar
loginip 登录的ip地址 varchar
logintime 登录时间 timestamp
createtime 创建时间 timestamp

用户表

字段名 描述 字段类型
id 自增主键 int
nickname 昵称 varchar
username 用户名 varchar
userphone 手机号 varchar
id_card 身份证号 varchar
password 用户密码 varchar
createtime 注册时间 timestamp
logintime 上次登录时间 timestamp

快递员表

字段名 描述 字段类型
id 自增主键 int
couriername 姓名 varchar
courierphone 电话号码 varchar
id_card 身份证号 varchar
courierpassword 密码 varchar
sendNumber 派件数量 int
createtime 注册时间 timestamp
logintime 上次登录时间 timestamp

快递表

字段名 描述 字段类型
id 自增主键 int
number 快递单号 varchar
username 用户名 varchar
userphone 手机号 varchar
company 快递公司 varchar
code 取件码 varchar
intime 录入时间 timestamp
outtime 取件时间 timestamp
status 状态 int
sysphone 录入人手机号 varchar

5.接口API设计

5.1登录模块

1.登录

请求地址:
	express/login.do
请求参数:
	username:用户名
	password:密码
返回格式示例:
{
	"status":0,
	"result":"登录成功"
}

2.退出

请求地址:
	express/logout.do
返回格式示例:
{
	"status":0,
	"result":"登出成功"
}

5.2控制台

请求地址:express/console.do
参数列表:无
返回的格式示例:
	{
		status:0,
		reuslt:"获取成功",
		data:[
			{//全部的快递
				size:1000,//快递总数
				day:100//今日新增
			},{//待取件快递
				size:500,//待取件数
				day:100//今日新增
			}
		]
	}

5.4快递模块

1. 快件列表(分页)

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

2.根据单号查询快递信息

请求地址:express/findByNumber.do
参数列表:
	1.	number:快递单号
	
返回的格式示例:

3. 根据取件码查询快递信息

请求地址:express/findByCode.do
参数列表:
	1.	code:取件码
	
返回的格式示例:

4. 根据用户的手机号,查询快递信息

请求地址:express/findByUserPhone.do
参数列表:
	1.	phoneNumber:手机号码
	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.	userPhone:收件人手机号码
录入成功返回的格式示例:
	
录入失败返回的格式示例:

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:要更改状态为已取件的快递单号
	
返回的格式示例:

5.5用户模块

1.用户列表(分页)

请求地址:user/findAll.do
参数列表:
	1.	limit:
			值:0,表示开启分页(默认)
			值:1,表示查询所有
	2.	offset:
			值:数字,表示SQL语句起始索引
	3.	pageNumber:
			值:数字,表示获取的用户数量
			
返回的格式示例:

2.根据单号查询用户信息

请求地址:user/findByUserPhone.do
参数列表:
	1.	userPhone:用户手机号
	
返回的格式示例:

3.用户录入

请求地址:user/insert.do
参数列表:
	1.	userName:用户名
	2.	userPhone:用户手机号
	3.	id_card:用户身份证号
	4.	password:用户密码
录入成功返回的格式示例:
	
录入失败返回的格式示例:

4.修改用户信息

请求地址:user/update.do
参数列表:
	1.	id:要修改的用户id
	1.	userName:用户名
	2.	userPhone:用户手机号
	3.	id_card:用户身份证号
	4.	password:用户密码

返回的格式示例:

5.根据id删除用户信息

请求地址:express/delete.do
参数列表:
	1.	id:	要删除的用户的id
	
返回的格式示例:
	

5.6快递员模块

1.快递员列表(分页)

请求地址:courier/findAll.do
参数列表:
	1.	limit:
			值:0,表示开启分页(默认)
			值:1,表示查询所有
	2.	offset:
			值:数字,表示SQL语句起始索引
	3.	pageNumber:
			值:数字,表示获取的用户数量
			
返回的格式示例:

2.根据单号查询快递员信息

请求地址:courier/findByCourierPhone.do
参数列表:
	1.	courierPhone:快递员手机号
	
返回的格式示例:

3.快递员录入

请求地址:courier/insert.do
参数列表:
	1.	courierName:用户名
	2.	courierPhone:快递员手机号
	3.	id_card:快递员身份证号
	4.	password:快递员密码
录入成功返回的格式示例:
	
录入失败返回的格式示例:

4. 修改快递员信息

请求地址:courier/update.do
参数列表:
	1.	id:要修改的快递员id
	1.	courierName:用户名
	2.	courierPhone:快递员手机号
	3.	id_card:快递员身份证号
	4.	password:快递员密码

返回的格式示例:

5. 根据id删除用户信息

请求地址:courier/delete.do
参数列表:
	1.	id:	要删除的快递的id
	
返回的格式示例:
	

6.源码编写

6.1源代码编写流程

创建数据库表格(Express)-》编写DAO-》编写Service-》编写Controller-》前后端的交互

6.2前后端交互原理和过程

在这里插入图片描述

6.3创建数据库及数据表

管理员表

在这里插入图片描述

用户表

在这里插入图片描述

快递表

在这里插入图片描述

快递员表

在这里插入图片描述

6.4管理员模块代码

6.4.1dao接口BaseAdminDao和实现类AdminDaoMysql

BaseAdminDao接口

package com.xzk.dao;

import java.util.Date;

/**
 * 用于定义eadmin表格的操作规范
 */
public interface BaseAdminDao {
    /**
     * 根据用户名,更新登录时间和登录ip
     * @param username
     * @param date
     * @param ip
     */
    void updateLoginTime(String username, Date date, String ip);

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

AdminDaoMysql实现类

package com.xzk.dao.impl;

import com.xzk.dao.BaseAdminDao;
import com.xzk.util.DruidUtil;
import com.xzk.util.MD5Util;
import com.xzk.util.UserUtil;

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

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) {
        //1.    获取连接
        Connection conn = DruidUtil.getConnection();
        PreparedStatement state =null;
        //2.    预编译SQL语句
        try {
            state = conn.prepareStatement(SQL_UPDATE_LOGIN_TIME);
            //3.    填充参数
            state.setDate(1,new java.sql.Date(date.getTime()));
            state.setString(2,ip);
            state.setString(3,username);
            //4.    执行
            state.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            //5.    释放资源
            DruidUtil.close(conn,state,null);
        }
    }

    /**
     * 管理员根据账号和密码登录
     *
     * @param username
     * @param password
     * @return 登录结果,true表示登录成功
     */
    @Override
    public boolean login(String username, String password) {
        //1.    获取连接
        Connection conn = DruidUtil.getConnection();
        PreparedStatement state=null;
        ResultSet rs = null;
        //对密码进行md5加密
        MD5Util md5 = new MD5Util();
        password =md5.getMD5Str(password);
        //2.    预编译SQL语句
        try {
            state = conn.prepareStatement(SQL_LOGIN);
            //3.    填充参数
            state.setString(1,username);
            state.setString(2,password);
            //4.    执行并获取结果
            rs = state.executeQuery();
            //5.    根据查询结果,返回
            return rs.next();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DruidUtil.close(conn,state,rs);
        }
        return false;
    }
}

6.4.2Service服务层AdminService

package com.xzk.service;

import com.xzk.dao.BaseAdminDao;
import com.xzk.dao.impl.AdminDaoMysql;

import java.util.Date;

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.4.3Controller控制器AdminController

package com.xzk.controller;

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

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

public class AdminController {
    @ResponseBody("/admin/login.do")
    public String login(HttpServletRequest request, HttpServletResponse response){
        //1.    接收参数
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        //2.    调用Service传参数,并获取结果
        boolean result = AdminService.login(username, password);
        //3.    根据结果,返回不同的数据给ajax
        Message msg = null;
        if(result){
            msg = new Message(0,"登录成功");
            //登录时间和ip的更新
            Date date = new Date();
            String ip = request.getRemoteAddr();
            AdminService.updateLoginTimeAndIP(username,date,ip);
            request.getSession().setAttribute("adminUserName",username);
        }else{
            msg = new Message(-1,"登录失败");
        }
        //4.    将数据转换为JSON
        String json = JSONUtil.toJSON(msg);
        //5.    将JSON回复给ajax
        return json;
    }

    @ResponseBody("/admin/index.do")
    public String index(HttpServletRequest request, HttpServletResponse response){
        String adminUserName = UserUtil.getUserName(request.getSession());
        Message msg = new Message();
        Map<String,String> data = new HashMap<>();
        data.put("adminUserName",adminUserName);
        if(adminUserName==null){
            msg.setStatus(-1);
        }else{
            msg.setStatus(0);
        }
        msg.setData(data);
        String json = JSONUtil.toJSON(msg);
        return json;
    }

    @ResponseBody("/admin/logout.do")
    public String logout(HttpServletRequest request, HttpServletResponse response){
        //1.    销毁session
        request.getSession().invalidate();
        //2.    给客户端返回消息
        Message msg = new Message(0);
        String json = JSONUtil.toJSON(msg);
        return json;
    }
}

6.4.4前后端的交互ajax

前端调用代码参考gitee里的源代码

6.5快递模块代码

6.5.1dao接口BaseExpressDao和实现类ExpressDaoMysql

BaseExpressDao接口

package com.xzk.dao;

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

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

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 查询的快递信息列表
     */
    List<Express> findByUserPhone(String userPhone);

    /**
     * 根据录入人的手机号码,查询他录入的所有记录
     * @param sysPhone 手机号码
     * @return 查询的快递信息列表
     */
    List<Express> findBySysPhone(String sysPhone);

    /**
     * 快递的录入
     * @param e 需要录入的快递对象
     * @return 录入的结果,true表示成功,false表示失败
     */
    boolean insert(Express e) throws DuplicateCodeException;

    /**
     * 快递的修改
     * @param id  要修改的快递id
     * @param newExpress 新的快递对象(number,company,username,userPhone)
     * @return 修改的结果,true表示成功,false表示失败
     */
    boolean update(int id, Express newExpress);

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

    /**
     * 根据id,删除单个快递信息
     * @param id 要删除的快递id
     * @return 删除的结果,true表示成功,false表示失败
     */
    boolean delete(int id);

}

ExpressDaoMysql实现类

package com.xzk.dao.impl;

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

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

public class ExpressDaoMysql implements BaseExpressDao {

    //用于查询数据库中的全部快递(总数+新增),待取件快递(总数+新增)
    private 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";
    //用于查询数据库中的所有快递信息
    private static final String SQL_FIND_All ="SELECT * FROM EXPRESS";
    //用于分页查询数据库中的快递信息
    private static final String SQL_FIND_LIMIT ="SELECT * FROM EXPRESS LIMIT ?,?";
    //通过取件码查询快递信息
    private static final String SQL_FIND_BY_CODE ="SELECT * FROM EXPRESS WHERE CODE=?";
    //通过快递单号查询快递信息
    private static final String SQL_FIND_BY_NUMBER ="SELECT * FROM EXPRESS WHERE NUMBER=?";
    //通过录入人的手机号码查询快递信息
    private static final String SQL_FIND_BY_SYSPHONE ="SELECT * FROM EXPRESS WHERE SYSPHONE=?";
    //通过用户手机号码查询用户的所有快递
    private static final String SQL_FIND_BY_USERPHONE ="SELECT * FROM EXPRESS WHERE USERPHONE=?";
    //录入快递
    private static final String SQL_INSERT ="INSERT INTO EXPRESS (NUMBER,USERNAME, USERPHONE, COMPANY,CODE,INTIME,STATUS,SYSPHONE) VALUES(?,?,?,?,?,NOW(),0,?)";
    //修改快递
    private static final String SQL_UPDATE ="UPDATE EXPRESS SET NUMBER=?,USERNAME=?,COMPANY=?,STATUS=? WHERE ID=?";
    //快递的装袋么修改(取件)
    private static final String SQL_UPDATE_STATUS ="UPDATE EXPRESS SET STATUS=1,OUTTIME=NOW(),CODE=NULL WHERE CODE=?";
    //快递的删除
        private 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<>();
        //1.    获取数据库的链接
        Connection conn = DruidUtil.getConnection();
        PreparedStatement state = null;
        ResultSet result = null;
        //2.    预编译SQL语句
        try {
            state = conn.prepareStatement(SQL_CONSOLE);
            //3.    填充参数(可选)
            //4.    执行SQL语句
            result = state.executeQuery();
            //5.    获取执行的结果
            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 data1 = new HashMap();
                data1.put("data1_size",data1_size);
                data1.put("data1_day",data1_day);
                Map data2 = new HashMap();
                data2.put("data2_size",data2_size);
                data2.put("data2_day",data2_day);
                data.add(data1);
                data.add(data2);
            }
            //6.    资源的释放
        } catch (SQLException e) {
            e.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<>();
        //1.    获取数据库的链接
        Connection conn = DruidUtil.getConnection();
        PreparedStatement state = null;
        ResultSet result = null;
        //2.    预编译SQL语句
        try {
            if(limit){
                state = conn.prepareStatement(SQL_FIND_LIMIT);
                //3.    填充参数(可选)
                state.setInt(1,offset);
                state.setInt(2,pageNumber);
            }else{
                state = conn.prepareStatement(SQL_FIND_All);
            }
            //4.    执行SQL语句
            result = state.executeQuery();
            //5.    获取执行的结果
            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 express =new Express(id,number,userName,userPhone,company,code,inTime,outTime,status,sysPhone);
                data.add(express);
            }
            //6.    资源的释放
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DruidUtil.close(conn,state,result);
        }
        return data;
    }

    /**
     * 根据快递单号,查询快递信息
     *
     * @param number 单号
     * @return 查询的快递信息,单号不存在时返回null
     */
    @Override
    public Express findByNumber(String number) {
        //1.    获取数据库的链接
        Connection conn = DruidUtil.getConnection();
        PreparedStatement state = null;
        ResultSet result = null;
        //2.    预编译SQL语句
        try {
            state = conn.prepareStatement(SQL_FIND_BY_NUMBER);
            //3.    填充参数(可选)
            state.setString(1,number);
            //4.    执行SQL语句
            result = state.executeQuery();
            //5.    获取执行的结果
            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 express =new Express(id,number,userName,userPhone,company,code,inTime,outTime,status,sysPhone);
                return express;
            }
            //6.    资源的释放
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DruidUtil.close(conn,state,result);
        }
        return null;
    }

    /**
     * 根据快递取件码,查询快递信息
     *
     * @param code 取件码
     * @return 查询的快递信息,取件码不存在时返回null
     */
    @Override
    public Express findByCode(String code) {
        //1.    获取数据库的链接
        Connection conn = DruidUtil.getConnection();
        PreparedStatement state = null;
        ResultSet result = null;
        //2.    预编译SQL语句
        try {
            state = conn.prepareStatement(SQL_FIND_BY_CODE);
            //3.    填充参数(可选)
            state.setString(1,code);
            //4.    执行SQL语句
            result = state.executeQuery();
            //5.    获取执行的结果
            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 express =new Express(id,number,userName,userPhone,company,code,inTime,outTime,status,sysPhone);
                return express;
            }
            //6.    资源的释放
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DruidUtil.close(conn,state,result);
        }
        return null;
    }

    /**
     * 根据用户手机号码,查询他所有的快递信息
     *
     * @param userPhone 手机号码
     * @return 查询的快递信息列表
     */
    @Override
    public List<Express> findByUserPhone(String userPhone) {
        ArrayList<Express> data = new ArrayList<>();
        //1.    获取数据库的链接
        Connection conn = DruidUtil.getConnection();
        PreparedStatement state = null;
        ResultSet result = null;
        //2.    预编译SQL语句
        try {
            state = conn.prepareStatement(SQL_FIND_BY_USERPHONE);
            //3.    填充参数(可选)
            state.setString(1,userPhone);
            //4.    执行SQL语句
            result = state.executeQuery();
            //5.    获取执行的结果
            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 express =new Express(id,number,userName,userPhone,company,code,inTime,outTime,status,sysPhone);
                data.add(express);
            }
            //6.    资源的释放
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DruidUtil.close(conn,state,result);
        }
        return data;
    }

    /**
     * 根据录入人的手机号码,查询他录入的所有记录
     *
     * @param sysPhone 手机号码
     * @return 查询的快递信息列表
     */
    @Override
    public List<Express> findBySysPhone(String sysPhone) {
        ArrayList data = new ArrayList();
        //1.    获取数据库的链接
        Connection conn = DruidUtil.getConnection();
        PreparedStatement state = null;
        ResultSet result = null;
        //2.    预编译SQL语句
        try {
            state = conn.prepareStatement(SQL_FIND_BY_SYSPHONE);
            //3.    填充参数(可选)
            state.setString(1,sysPhone);
            //4.    执行SQL语句
            result = state.executeQuery();
            //5.    获取执行的结果
            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 express =new Express(id,number,userName,userPhone,company,code,inTime,outTime,status,sysPhone);
                data.add(express);
            }
            //6.    资源的释放
        } catch (SQLException e) {
            e.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 录入的结果,true表示成功,false表示失败
     */
    @Override
    public boolean insert(Express e) throws DuplicateCodeException {
        //1.    链接的获取
        Connection conn = DruidUtil.getConnection();
        //2.    预编译SQL语句
        PreparedStatement state = null;

        try {
            state = conn.prepareStatement(SQL_INSERT);
            //3.    填充参数
            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());
            //4.    执行SQL语句,并获取执行结果
            return state.executeUpdate()>0?true:false;
        } catch (SQLException e1) {
            //e1.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 {
            //5.    释放资源
            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 修改的结果,true表示成功,false表示失败
     */
    @Override
    public boolean update(int id, Express newExpress) {
        //1.    链接的获取
        Connection conn = DruidUtil.getConnection();
        //2.    预编译SQL语句
        PreparedStatement state = null;
        try {
            state = conn.prepareStatement(SQL_UPDATE);
            //3.    填充参数
            state.setString(1,newExpress.getNumber());
            state.setString(2,newExpress.getUserName());
            state.setString(3,newExpress.getCompany());
            state.setInt(4,newExpress.getStatus());
            state.setInt(5,id);
            //4.    执行SQL语句,并获取执行结果
            return state.executeUpdate()>0?true:false;
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            //5.    释放资源
            DruidUtil.close(conn,state,null);
        }
        return false;
    }

    /**
     * 更改快递的状态为1,表示取件完成
     * UPDATE EXPRESS SET STATUS=1 WHERE CODE=?
     * @param code 要修改的快递单号
     * @return 修改的结果,true表示成功,false表示失败
     */
    @Override
    public boolean updateStatus(String code) {
        //1.    链接的获取
        Connection conn = DruidUtil.getConnection();
        //2.    预编译SQL语句
        PreparedStatement state = null;
        try {
            state = conn.prepareStatement(SQL_UPDATE_STATUS);
            //3.    填充参数
            state.setString(1,code);
            //4.    执行SQL语句,并获取执行结果
            return state.executeUpdate()>0?true:false;
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            //5.    释放资源
            DruidUtil.close(conn,state,null);
        }
        return false;
    }

    /**
     * 根据id,删除单个快递信息
     *
     * @param id 要删除的快递id
     * @return 删除的结果,true表示成功,false表示失败
     */
    @Override
    public boolean delete(int id) {
        //1.    链接的获取
        Connection conn = DruidUtil.getConnection();
        //2.    预编译SQL语句
        PreparedStatement state = null;
        try {
            state = conn.prepareStatement(SQL_DELETE);
            //3.    填充参数
            state.setInt(1,id);
            //4.    执行SQL语句,并获取执行结果
            return state.executeUpdate()>0?true:false;
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            //5.    释放资源
            DruidUtil.close(conn,state,null);
        }
        return false;
    }
}

6.5.2Service服务层ExpressService

package com.xzk.service;

import com.xzk.bean.Express;
import com.xzk.dao.BaseExpressDao;
import com.xzk.dao.impl.ExpressDaoMysql;
import com.xzk.exception.DuplicateCodeException;
import com.xzk.util.RandomUtil;
import com.xzk.util.SMSUtil;

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

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 查询的快递信息列表
     */
    public static List<Express> findByUserPhone(String userPhone) {
        return dao.findByUserPhone(userPhone);
    }

    /**
     * 根据录入人的手机号码,查询他录入的所有记录
     *
     * @param sysPhone 手机号码
     * @return 查询的快递信息列表
     */
    public static List<Express> findBySysPhone(String sysPhone) {
        return dao.findBySysPhone(sysPhone);
    }

    /**
     * 快递的录入
     *
     * @param e 需要录入的快递对象
     * @return 录入的结果,true表示成功,false表示失败
     */
    public static boolean insert(Express e){
        //1.    生成取件码
        e.setCode(RandomUtil.getCode()+"");
        try {
            boolean flag = dao.insert(e);
            if(flag){
                //录入成功
                SMSUtil.send(e.getUserPhone(),e.getCode());
            }
            return flag;
        } catch (DuplicateCodeException e1) {
            return insert(e);
        }
    }

    /**
     * 快递的修改
     *
     * @param id         要修改的快递id
     * @param newExpress 新的快递对象(number,company,username,userPhone)
     * @return 修改的结果,true表示成功,false表示失败
     */
    public static boolean update(int id, Express newExpress) {
        if(newExpress.getUserPhone()!=null){
            dao.delete(id);
            boolean insert = insert(newExpress);
            return insert;
        }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 修改的结果,true表示成功,false表示失败
     */
    public static boolean updateStatus(String code) {
        return dao.updateStatus(code);
    }

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

6.5.3Controller控制器ExpressController

package com.xzk.controller;

import com.xzk.bean.BootStrapTableExpress;
import com.xzk.bean.Express;
import com.xzk.bean.Message;
import com.xzk.bean.ResultData;
import com.xzk.mvc.ResponseBody;
import com.xzk.service.ExpressService;
import com.xzk.util.DateFormatUtil;
import com.xzk.util.JSONUtil;
import com.xzk.util.UserUtil;

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

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;
    }

    @ResponseBody("/express/list.do")
    public String list(HttpServletRequest request,HttpServletResponse response){
        //1.    获取查询数据的起始索引值
        int offset = Integer.parseInt(request.getParameter("offset"));
        //2.    获取当前页要查询的数据量
        int pageNumber = Integer.parseInt(request.getParameter("pageNumber"));
        //3.    进行查询
        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();
        int total = console.get(0).get("data1_size");
        //4.    将集合封装为 bootstrap-table识别的格式
        ResultData<BootStrapTableExpress> data = new ResultData<>();
        data.setRows(list2);
        data.setTotal(total);
        String json = JSONUtil.toJSON(data);
        return json;
    }

    @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;
    }
    @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;
    }
    @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 newExress = new Express();
        newExress.setNumber(number);
        newExress.setCompany(company);
        newExress.setUserName(userName);
        newExress.setUserPhone(userPhone);
        newExress.setStatus(status);
        boolean flag = ExpressService.update(id, newExress);
        Message msg = new Message();
        if(flag){
            msg.setStatus(0);
            msg.setResult("修改成功");
        }else{
            msg.setStatus(-1);
            msg.setResult("修改失败");
        }
        String json = JSONUtil.toJSON(msg);
        return json;
    }

    @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;
    }
}

6.5.4前后端的交互ajax

前端调用代码参考gitee里的源代码

6.6用户模块代码

6.6.1dao接口UserExpressDao和实现类UserDaoMysql

BaseUserDao接口

package com.xzk.dao;

import com.xzk.bean.User;

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

public interface BaseUserDao {

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

    /**
     * 用于查询所有用户
     * @param limit 是否分页标记,true表示分页。false表示查询所有快递
     * @param offset SQL语句的其实索引
     * @param pageNumber 页查询的数量
     * @return 返回用户集合
     */
    List<User> findAll(boolean limit, int offset, int pageNumber);

    /**
     * 根据用户手机号,查询用户信息
     * @param userPhone 手机号
     * @return 查询的用户信息,手机号码不存在时返回null
     */
    User findByUserPhone(String userPhone);

    /**
     * 用户录入
     * @param u 需要录入的用户对象
     * @return 录入的结果,true表示成功,false表示失败
     */
    boolean insert(User u);

    /**
     * 用户修改
     * @param id 要修改的用户id
     * @param newUser 新的用户对象(userName,userPhone,id_card,password)
     * @return 修改的结果,true表示成功,false表示失败
     */
    boolean update(int id,User newUser);

    /**
     * 用户修改
     * @param id 要修改的用户id
     * @param password 新的用户密码
     * @return 修改的结果,true表示成功,false表示失败
     */
    boolean updatePassword(int id, String password);

    /**
     * 根据id,删除单个用户信息
     * @param id 要删除的用户id
     * @return 删除的结果,true表示成功,false表示失败
     */
    boolean delete(int id);
}

UserDaoMysql实现类

package com.xzk.dao.impl;

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

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

public class UserDaoMysql implements BaseUserDao {

    //用于查询数据库中的全部用户(总数+新增)
    private static final String SQL_CONSOLE ="SELECT COUNT(ID) data3_size,COUNT(TO_DAYS(CREATETIME)=TO_DAYS(NOW()) OR NULL) data3_day FROM USER";
    //用于查询数据库中的所有用户信息
    private static final String SQL_FIND_All ="SELECT * FROM USER";
    //用于分页查询数据库中的用户信息
    private static final String SQL_FIND_LIMIT ="SELECT * FROM USER LIMIT ?,?";
    //通过用户手机号码查询用户的信息
    private static final String SQL_FIND_BY_USERPHONE ="SELECT * FROM USER WHERE USERPHONE=?";
    //录入用户
    private static final String SQL_INSERT ="INSERT INTO USER (USERNAME,USERPHONE,PASSWORD,ID_CARD,CREATETIME,LOGINTIME) VALUES(?,?,?,?,NOW(),NOW())";
    //修改用户
    private static final String SQL_UPDATE ="UPDATE USER SET USERNAME=?,USERPHONE=?,ID_CARD=? WHERE ID=?";
    //修改用户修改密码
    private static final String SQL_UPDATE_PASSWORD ="UPDATE USER SET PASSWORD=? WHERE ID=?";
    //快递的删除
    private static final String SQL_DELETE ="DELETE FROM USER WHERE ID=?";

    /**
     * 用于查询数据库中的全部用户(总数+新增)
     *
     * @return {size:总数,day:新增}
     */
    @Override
    public Map<String, Integer> console() {

        Map<String,Integer> data = new HashMap<>();
        //1.    获取数据库的链接
        Connection conn = DruidUtil.getConnection();
        PreparedStatement state =null;
        ResultSet result = null;

        try {
            state = conn.prepareStatement(SQL_CONSOLE);
            //3.    填充参数(可选)
            //4.    执行SQL语句
            result = state.executeQuery();
            //5.    获取执行的结果
            if(result.next()) {
                int data3_size = result.getInt("data3_size");
                int data3_day = result.getInt("data3_day");
                data.put("data3_size",data3_size);
                data.put("data3_day",data3_day);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            //6.    资源的释放
            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<>();
        //1.    获取数据库的链接
        Connection conn = DruidUtil.getConnection();
        PreparedStatement state = null;
        ResultSet result = null;
        //2.    预编译SQL语句
        try {
            if(limit){
                state = conn.prepareStatement(SQL_FIND_LIMIT);
                //3.    填充参数(可选)
                state.setInt(1,offset);
                state.setInt(2,pageNumber);
            }else{
                state = conn.prepareStatement(SQL_FIND_All);
            }
            //4.    执行SQL语句
            result = state.executeQuery();
            //5.    获取执行的结果
            while (result.next()){
                int id = result.getInt("id");
                String nickName = result.getString("nickName");
                String userName = result.getString("userName");
                String userPhone = result.getString("userPhone");
                String id_card = result.getString("id_card");
                Timestamp createTime = result.getTimestamp("createTime");
                Timestamp loginTime = result.getTimestamp("loginTime");
                User user = new User(id,nickName,userName,userPhone,id_card,createTime,loginTime);
                data.add(user);
            }
            //6.    资源的释放
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DruidUtil.close(conn,state,result);
        }
        return data;
    }

    /**
     * 根据用户手机号,查询用户信息
     *
     * @param userPhone 手机号
     * @return 查询的用户信息,手机号码不存在时返回null
     */
    @Override
    public User findByUserPhone(String userPhone) {
        //1.    获取数据库的链接
        Connection conn = DruidUtil.getConnection();
        PreparedStatement state = null;
        ResultSet result = null;
        //2.    预编译SQL语句
        try {
            state = conn.prepareStatement(SQL_FIND_BY_USERPHONE);
            //3.    填充参数(可选)
            state.setString(1,userPhone);
            //4.    执行SQL语句
            result = state.executeQuery();
            //5.    获取执行的结果
            if(result.next()){
                int id = result.getInt("id");
                String nickName = result.getString("nickName");
                String userName = result.getString("userName");
                String id_card = result.getString("id_card");
                Timestamp createTime = result.getTimestamp("createTime");
                Timestamp loginTime = result.getTimestamp("loginTime");
                User user = new User(id,nickName,userName,userPhone,id_card,createTime,loginTime);
                return user;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DruidUtil.close(conn,state,result);
        }
        return null;
    }

    /**
     * 用户录入
     *
     * @param u 需要录入的用户对象(USERNAME,USERPHONE,PASSWORD,ID_CART)
     * @return 录入的结果,true表示成功,false表示失败
     */
    @Override
    public boolean insert(User u) {
        //1.    链接的获取
        Connection conn = DruidUtil.getConnection();
        //2.    预编译SQL语句
        PreparedStatement state = null;
        try {
            state = conn.prepareStatement(SQL_INSERT);
            //3.    填充参数
            state.setString(1,u.getUserName());
            state.setString(2,u.getUserPhone());
            state.setString(3,u.getPassword());
            state.setString(4,u.getId_card());
            //4.    执行SQL语句,并获取执行结果
            return state.executeUpdate()>0?true:false;
        } catch (SQLException e) {
            e.printStackTrace();

        }finally {
            //5.    释放资源
            DruidUtil.close(conn,state,null);
        }
        return false;
    }

    /**
     * 用户修改
     * UPDATE USER SET USERNAME=?,USERPHONE=?,ID_CART=? WHERE ID=?
     * @param id      要修改的用户id
     * @param newUser 新的用户对象(userName,userPhone,id_card)
     * @return 修改的结果,true表示成功,false表示失败
     */
    @Override
    public boolean update(int id, User newUser) {
        //1.    链接的获取
        Connection conn = DruidUtil.getConnection();
        //2.    预编译SQL语句
        PreparedStatement state = null;
        try {
            state = conn.prepareStatement(SQL_UPDATE);
            //3.    填充参数
            state.setString(1,newUser.getUserName());
            state.setString(2,newUser.getUserPhone());
            state.setString(3,newUser.getId_card());
            state.setInt(4,id);
            //4.    执行SQL语句,并获取执行结果
            return state.executeUpdate()>0?true:false;
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            //5.    释放资源
            DruidUtil.close(conn,state,null);
        }
        return false;
    }

    /**
     * 用户密码修改
     *
     * @param id       要修改的用户id
     * @param password 新的用户密码
     * @return 修改的结果,true表示成功,false表示失败
     */
    @Override
    public boolean updatePassword(int id, String password) {
        //1.    链接的获取
        Connection conn = DruidUtil.getConnection();
        //2.    预编译SQL语句
        PreparedStatement state = null;
        try {
            state = conn.prepareStatement(SQL_UPDATE_PASSWORD);
            //3.    填充参数
            state.setString(1,password);
            state.setInt(2,id);
            //4.    执行SQL语句,并获取执行结果
            return state.executeUpdate()>0?true:false;
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            //5.    释放资源
            DruidUtil.close(conn,state,null);
        }
        return false;
    }

    /**
     * 根据id,删除单个用户信息
     *
     * @param id 要删除的用户id
     * @return 删除的结果,true表示成功,false表示失败
     */
    @Override
    public boolean delete(int id) {
        //1.    链接的获取
        Connection conn = DruidUtil.getConnection();
        //2.    预编译SQL语句
        PreparedStatement state = null;
        try {
            state = conn.prepareStatement(SQL_DELETE);
            //3.    填充参数
            state.setInt(1,id);
            //4.    执行SQL语句,并获取执行结果
            return state.executeUpdate()>0?true:false;
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            //5.    释放资源
            DruidUtil.close(conn,state,null);
        }
        return false;
    }
}

6.6.2Service服务层UserService

package com.xzk.service;

import com.xzk.bean.User;
import com.xzk.dao.BaseUserDao;
import com.xzk.dao.impl.UserDaoMysql;

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

public class UserService {

    private static BaseUserDao dao = new UserDaoMysql();

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

    /**
     * 用于查询所有用户
     *
     * @param limit      是否分页标记,true表示分页。false表示查询所有快递
     * @param offset     SQL语句的其实索引
     * @param pageNumber 页查询的数量
     * @return 返回用户集合
     */
    public static List<User> findAll(boolean limit, int offset, int pageNumber) {
        return dao.findAll(limit,offset,pageNumber);
    }
    /**
     * 根据用户手机号,查询用户信息
     *
     * @param userPhone 手机号
     * @return 查询的用户信息,手机号码不存在时返回null
     */
    public static User findByUserPhone(String userPhone) {
        return dao.findByUserPhone(userPhone);
    }
    /**
     * 用户录入
     *
     * @param u 需要录入的用户对象(USERNAME,USERPHONE,PASSWORD,ID_CART)
     * @return 录入的结果,true表示成功,false表示失败
     */
    public static boolean insert(User u) {
        return dao.insert(u);
    }
    /**
     * 用户修改
     * UPDATE USER SET USERNAME=?,USERPHONE=?,ID_CART=?,PASSWORD=? WHERE ID=?
     * @param id      要修改的用户id
     * @param newUser 新的用户对象(userName,userPhone,id_card,password)
     * @return 修改的结果,true表示成功,false表示失败
     */
    public static boolean update(int id, User newUser) {
        return dao.update(id,newUser);
    }
    /**
     * 用户修改
     *
     * @param id       要修改的用户id
     * @param password 新的用户密码
     * @return 修改的结果,true表示成功,false表示失败
     */
    public static boolean updatePassword(int id, String password) {
        return dao.updatePassword(id,password);
    }
    /**
     * 根据id,删除单个用户信息
     *
     * @param id 要删除的用户id
     * @return 删除的结果,true表示成功,false表示失败
     */
    public static boolean delete(int id) {
        return dao.delete(id);
    }
}

6.6.3Controller控制器UserController

package com.xzk.controller;

import com.xzk.bean.*;
import com.xzk.mvc.ResponseBody;
import com.xzk.service.UserService;
import com.xzk.util.DateFormatUtil;
import com.xzk.util.JSONUtil;
import com.xzk.util.MD5Util;

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

public class UserController {
    @ResponseBody("/user/console.do")
    public String console(HttpServletRequest request, HttpServletResponse response){
        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;
    }

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

    @ResponseBody("/user/insert.do")
    public String insert(HttpServletRequest request,HttpServletResponse response){
        String userName = request.getParameter("userName");
        String userPhone = request.getParameter("userPhone");
        String id_card = request.getParameter("id_card");
        //对密码进行md5加密
        MD5Util md5 = new MD5Util();
        String password = md5.getMD5Str(request.getParameter("password"));
        User u = new User(userName,userPhone,password,id_card);
        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;
    }
    @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;
    }
    @ResponseBody("/user/update.do")
    public String update(HttpServletRequest request,HttpServletResponse response){
        boolean flag = false;
        int id = Integer.parseInt(request.getParameter("id"));
        String userName = request.getParameter("userName");
        String userPhone = request.getParameter("userPhone");
        String id_card = request.getParameter("id_card");
        String password = request.getParameter("password");
        if(password != null || password.length()!= 0){
            //对密码进行md5加密
            MD5Util md5 = new MD5Util();
            password = md5.getMD5Str(request.getParameter("password"));
            flag = UserService.updatePassword(id,password);
        }
        User u = new User(userName,userPhone,id_card);
        flag = UserService.update(id,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;
    }

    @ResponseBody("/user/delete.do")
    public String delete(HttpServletRequest request,HttpServletResponse response){
        int id = Integer.parseInt(request.getParameter("id"));
        boolean flag = UserService.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;
    }
}

6.6.4前后端的交互ajax

前端调用代码参考gitee里的源代码

6.7快递员模块代码

6.7.1dao接口CourierExpressDao和实现类CourierDaoMysql

BaseUserDao接口

package com.xzk.dao;

import com.xzk.bean.Courier;

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

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

    /**
     * 用于查询所有快递员
     * @param limit 是否分页标记,true表示分页。false表示查询所有快递
     * @param offset SQL语句的其实索引
     * @param pageNumber 页查询的数量
     * @return 返回快递员集合
     */
    List<Courier> findAll(boolean limit, int offset, int pageNumber);

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

    /**
     * 快递员录入
     * @param c 需要录入的快递员对象
     * @return 录入的结果,true表示成功,false表示失败
     */
    boolean insert(Courier c);

    /**
     * 快递员修改
     * @param id 要修改的快递员id
     * @param newCourier 新的快递员对象(courierName,courierPhone,id_card,courierPassword)
     * @return 修改的结果,true表示成功,false表示失败
     */
    boolean update(int id,Courier newCourier);

    /**
     * 快递员修改
     * @param id 要修改的快递员id
     * @param courierPassword 新的快递员密码
     * @return 修改的结果,true表示成功,false表示失败
     */
    boolean updatePassword(int id, String courierPassword);

    /**
     * 根据id,删除单个快递员信息
     * @param id 要删除的快递员id
     * @return 删除的结果,true表示成功,false表示失败
     */
    boolean delete(int id);
}

CourierDaoMysql实现类

package com.xzk.dao.impl;

import com.xzk.bean.Courier;
import com.xzk.dao.BaseCourierDao;
import com.xzk.util.DruidUtil;

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

public class CourierDaoMysql implements BaseCourierDao {

    //用于查询数据库中的全部快递员(总数+新增)
    private static final String SQL_CONSOLE ="SELECT COUNT(ID) data4_size,COUNT(TO_DAYS(CREATETIME)=TO_DAYS(NOW()) OR NULL) data4_day FROM COURIER";
    //用于查询数据库中的所有快递员信息
    private static final String SQL_FIND_All ="SELECT * FROM COURIER";
    //用于分页查询数据库中的快递员信息
    private static final String SQL_FIND_LIMIT ="SELECT * FROM COURIER LIMIT ?,?";
    //通过快递员手机号码查询快递员的信息
    private static final String SQL_FIND_BY_COURIERPHONE ="SELECT * FROM COURIER WHERE COURIERPHONE=?";
    //录入快递员
    private static final String SQL_INSERT ="INSERT INTO COURIER (COURIERNAME,COURIERPHONE,ID_CARD,COURIERPASSWORD,CREATETIME,LOGINTIME) VALUES(?,?,?,?,NOW(),NOW())";
    //修改快递员
    private static final String SQL_UPDATE ="UPDATE COURIER SET COURIERNAME=?,COURIERPHONE=?,ID_CARD=? WHERE ID=?";
    //修改快递员修改密码
    private static final String SQL_UPDATE_COURIERPASSWORD ="UPDATE COURIER SET COURIERPASSWORD=? WHERE ID=?";
    //快递的删除
    private static final String SQL_DELETE ="DELETE FROM COURIER WHERE ID=?";

    /**
     * 用于查询数据库中的全部快递员(总数+新增)
     *
     * @return {size:总数,day:新增}
     */
    @Override
    public Map<String, Integer> console() {
        Map<String,Integer> data = new HashMap<>();
        //1.    获取数据库的链接
        Connection conn = DruidUtil.getConnection();
        PreparedStatement state =null;
        ResultSet result = null;

        try {
            state = conn.prepareStatement(SQL_CONSOLE);
            //3.    填充参数(可选)
            //4.    执行SQL语句
            result = state.executeQuery();
            //5.    获取执行的结果
            if(result.next()) {
                int data4_size = result.getInt("data4_size");
                int data4_day = result.getInt("data4_day");
                data.put("data4_size",data4_size);
                data.put("data4_day",data4_day);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            //6.    资源的释放
            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<>();
        //1.    获取数据库的链接
        Connection conn = DruidUtil.getConnection();
        PreparedStatement state = null;
        ResultSet result = null;
        //2.    预编译SQL语句
        try {
            if(limit){
                state = conn.prepareStatement(SQL_FIND_LIMIT);
                //3.    填充参数(可选)
                state.setInt(1,offset);
                state.setInt(2,pageNumber);
            }else{
                state = conn.prepareStatement(SQL_FIND_All);
            }
            //4.    执行SQL语句
            result = state.executeQuery();
            //5.    获取执行的结果
            while (result.next()){
                int id = result.getInt("id");
                String courierName = result.getString("courierName");
                String courierPhone = result.getString("courierPhone");
                String courierPassword = result.getString("courierPassword");
                String id_card = result.getString("id_card");
                int sendNumber = result.getInt("sendNumber");
                Timestamp createTime = result.getTimestamp("createTime");
                Timestamp loginTime = result.getTimestamp("loginTime");
                Courier courier = new Courier(id,courierName,courierPhone,id_card,sendNumber,createTime,loginTime);
                data.add(courier);
            }
            //6.    资源的释放
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DruidUtil.close(conn,state,result);
        }
        return data;
    }

    /**
     * 根据快递员手机号,查询快递员信息
     *
     * @param courierPhone 手机号
     * @return 查询的快递员信息,手机号码不存在时返回null
     */
    @Override
    public Courier findByCourierPhone(String courierPhone) {
        //1.    获取数据库的链接
        Connection conn = DruidUtil.getConnection();
        PreparedStatement state = null;
        ResultSet result = null;
        //2.    预编译SQL语句
        try {
            state = conn.prepareStatement(SQL_FIND_BY_COURIERPHONE);
            //3.    填充参数(可选)
            state.setString(1,courierPhone);
            //4.    执行SQL语句
            result = state.executeQuery();
            //5.    获取执行的结果
            if(result.next()){
                int id = result.getInt("id");
                String courierName = result.getString("courierName");
                String id_card = result.getString("id_card");
                Courier courier = new Courier(id,courierName,courierPhone,id_card);
                return courier;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DruidUtil.close(conn,state,result);
        }
        return null;
    }


    /**
     * 快递员录入
     *
     * @param c 需要录入的快递员对象
     * @return 录入的结果,true表示成功,false表示失败
     */
    @Override
    public boolean insert(Courier c) {
        //1.    链接的获取
        Connection conn = DruidUtil.getConnection();
        //2.    预编译SQL语句
        PreparedStatement state = null;
        try {
            state = conn.prepareStatement(SQL_INSERT);
            //3.    填充参数
            state.setString(1,c.getCourierName());
            state.setString(2,c.getCourierPhone());
            state.setString(3,c.getId_card());
            state.setString(4,c.getCourierPassword());
            //4.    执行SQL语句,并获取执行结果
            return state.executeUpdate()>0?true:false;
        } catch (SQLException e) {
            e.printStackTrace();

        }finally {
            //5.    释放资源
            DruidUtil.close(conn,state,null);
        }
        return false;
    }

    /**
     * 快递员修改
     * @param id 要修改的快递员id
     * @param newCourier 新的快递员对象(courierName,courierPhone,id_card)
     * @return 修改的结果,true表示成功,false表示失败
     */
    @Override
    public boolean update(int id, Courier newCourier) {
        //1.    链接的获取
        Connection conn = DruidUtil.getConnection();
        //2.    预编译SQL语句
        PreparedStatement state = null;
        try {
            state = conn.prepareStatement(SQL_UPDATE);
            //3.    填充参数
            state.setString(1,newCourier.getCourierName());
            state.setString(2,newCourier.getCourierPhone());
            state.setString(3,newCourier.getId_card());
            state.setInt(4,id);
            //4.    执行SQL语句,并获取执行结果
            return state.executeUpdate()>0?true:false;
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            //5.    释放资源
            DruidUtil.close(conn,state,null);
        }
        return false;
    }

    /**
     * 快递员修改
     *
     * @param id       要修改的快递员id
     * @param courierPassword 新的快递员密码
     * @return 修改的结果,true表示成功,false表示失败
     */
    @Override
    public boolean updatePassword(int id, String courierPassword) {
        //1.    链接的获取
        Connection conn = DruidUtil.getConnection();
        //2.    预编译SQL语句
        PreparedStatement state = null;
        try {
            state = conn.prepareStatement(SQL_UPDATE_COURIERPASSWORD);
            //3.    填充参数
            state.setString(1,courierPassword);
            state.setInt(2,id);
            //4.    执行SQL语句,并获取执行结果
            return state.executeUpdate()>0?true:false;
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            //5.    释放资源
            DruidUtil.close(conn,state,null);
        }
        return false;
    }

    /**
     * 根据id,删除单个快递员信息
     *
     * @param id 要删除的快递员id
     * @return 删除的结果,true表示成功,false表示失败
     */
    @Override
    public boolean delete(int id) {
        //1.    链接的获取
        Connection conn = DruidUtil.getConnection();
        //2.    预编译SQL语句
        PreparedStatement state = null;
        try {
            state = conn.prepareStatement(SQL_DELETE);
            //3.    填充参数
            state.setInt(1,id);
            //4.    执行SQL语句,并获取执行结果
            return state.executeUpdate()>0?true:false;
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            //5.    释放资源
            DruidUtil.close(conn,state,null);
        }
        return false;
    }
}

6.7.2Service服务层CourierService

package com.xzk.service;

import com.xzk.bean.Courier;
import com.xzk.dao.BaseCourierDao;
import com.xzk.dao.impl.CourierDaoMysql;

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

public class CourierService {

    private static BaseCourierDao dao = new CourierDaoMysql();

    /**
     * 用于查询数据库中的全部快递员(总数+新增)
     *
     * @return {size:总数,day:新增}
     */
    public static 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);
    }

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

    /**
     * 快递员录入
     *
     * @param c 需要录入的快递员对象
     * @return 录入的结果,true表示成功,false表示失败
     */
    public static boolean insert(Courier c) {
        return dao.insert(c);
    }

    /**
     * 快递员修改
     *
     * @param id 要修改的快递员id
     * @param newCourier  新的快递员对象(courierName,courierPhone,id_card,courierPassword)
     * @return 修改的结果,true表示成功,false表示失败
     */
    public static boolean update(int id, Courier newCourier) {
        return dao.update(id,newCourier);
    }

    /**
     * 快递员修改
     *
     * @param id       要修改的快递员id
     * @param courierPassword 新的快递员密码
     * @return 修改的结果,true表示成功,false表示失败
     */
    public static boolean updatePassword(int id, String courierPassword) {
        return dao.updatePassword(id,courierPassword);
    }

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

6.7.3Controller控制器CourierController

package com.xzk.controller;

import com.xzk.bean.BootStrapTableCourier;
import com.xzk.bean.Courier;
import com.xzk.bean.Message;
import com.xzk.bean.ResultData;
import com.xzk.dao.BaseCourierDao;
import com.xzk.mvc.ResponseBody;
import com.xzk.service.CourierService;
import com.xzk.util.DateFormatUtil;
import com.xzk.util.JSONUtil;
import com.xzk.util.MD5Util;

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

public class CourierController {

    @ResponseBody("/courier/console.do")
    public String console(HttpServletRequest request, HttpServletResponse response){
        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;
    }
    @ResponseBody("/courier/list.do")
    public String list(HttpServletRequest request, HttpServletResponse response){
        //1.    获取查询数据的起始索引值
        int offset = Integer.parseInt(request.getParameter("offset"));
        //2.    获取当前页要查询的数据量
        int pageNumber = Integer.parseInt(request.getParameter("pageNumber"));
        //3.    进行查询
        List<Courier> list = CourierService.findAll(true, offset, pageNumber);
        List<BootStrapTableCourier> list2 =new ArrayList<>();
        for(Courier c:list){
            String createTime = DateFormatUtil.format(c.getCreateTime());
            String loginTime = DateFormatUtil.format(c.getLoginTime());
            BootStrapTableCourier c2 = new BootStrapTableCourier(c.getId(), c.getCourierName(), c.getCourierPhone(), c.getId_card(), c.getSendNumber(), createTime, loginTime);
            list2.add(c2);
        }
        Map<String, Integer> console = CourierService.console();
        int total = console.get("data4_size");
        //4.    将集合封装为 bootstrap-table识别的格式
        ResultData<BootStrapTableCourier> data = new ResultData<>();
        data.setRows(list2);
        data.setTotal(total);
        String json = JSONUtil.toJSON(data);
        return json;
    }
    @ResponseBody("/courier/insert.do")
    public String insert(HttpServletRequest request,HttpServletResponse response){
        String courierName = request.getParameter("courierName");
        String courierPhone = request.getParameter("courierPhone");
        String id_card = request.getParameter("id_card");
        //对密码进行md5加密
        MD5Util md5 = new MD5Util();
        String courierPassword = md5.getMD5Str(request.getParameter("courierPassword"));
        Courier c = new Courier(courierName,courierPhone,id_card,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;
    }
    @ResponseBody("/courier/find.do")
    public String find(HttpServletRequest request,HttpServletResponse response){
        String courierPhone = request.getParameter("courierPhone");
        Courier c = CourierService.findByCourierPhone(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;
    }
    @ResponseBody("/courier/update.do")
    public String update(HttpServletRequest request,HttpServletResponse response){
        boolean flag = false;
        int id = Integer.parseInt(request.getParameter("id"));
        String courierName = request.getParameter("courierName");
        String courierPhone = request.getParameter("courierPhone");
        String id_card = request.getParameter("id_card");
        String courierPassword = request.getParameter("courierPassword");
        if(courierPassword != null || courierPassword.length()!= 0){
            //对密码进行md5加密
            MD5Util md5 = new MD5Util();
            courierPassword = md5.getMD5Str(request.getParameter("courierPassword"));
            flag = CourierService.updatePassword(id,courierPassword);
        }
        Courier c = new Courier(id,courierName,courierPhone,id_card);
        flag = CourierService.update(id,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;
    }

    @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;
    }
}

6.7.4前后端的交互ajax

前端调用代码参考gitee里的源代码

6.8编写过滤器Filter

6.8.1登录权限访问限制 AccessControlFilter

package com.xzk.filter;

import com.xzk.util.UserUtil;

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

@WebFilter({"/admin/index.html","/admin/views/*","/express/*"})
public class AccessControlFilter implements Filter {
    public void destroy() {
    }

    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{
            ((HttpServletResponse)resp).sendRedirect("/admin/login.html");
        }

    }

    public void init(FilterConfig config) throws ServletException {

    }

}

6.8.2前后端交互编码设置CharSetFilter

package com.xzk.filter;

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

@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 {

    }

}

7.后记

代码正常布局到服务器需要自己申请阿里云短信接口并配置SMSUtil类以及修改微信端控制器UserController里面的login方法和微信公众号并配置TokenUtil类,目前前端没有使用短信登录,微信端登录测试使用账号18866668888 密码123456。

以上是前端后台后端的代码编写说明,微信端跟前端后台设计的流程差不多,相关代码已经展示在gitee里面。

本项目适合初学者参考学习,目的在于融会贯通javaWeb技术,体验项目开发流程。

由于时间比较赶,源码可能存在一些bug,比如逻辑上改用户手机号码时,用户之前手机号码还没取件的快递会没法去取;改快递员手机号码时,快递员之前录入还未取件的快递怎么办等等。

有不足之处,欢迎大家留言指出。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐