完整开发一个JAVAWEB项目(手写MVC框架)过程

前言

项目的代码已经上传到了我的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,比如逻辑上改用户手机号码时,用户之前手机号码还没取件的快递会没法去取;改快递员手机号码时,快递员之前录入还未取件的快递怎么办等等。

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

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值