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

本文档介绍了基于JavaWeb技术实现的快递e栈后台项目,涵盖了项目背景、目的、涉及的技术点和需求分析。详细讲解了从MVC框架搭建、layui使用、工具类介绍到数据库设计和实体类编写的过程,以及管理员登录退出、快递CRUD等功能的实现。项目旨在锻炼编码能力,熟悉JavaWeb技术,并为后续框架学习打下基础。
摘要由CSDN通过智能技术生成

写在前面

   这个部分对于我而言是一个重要的学习分水岭,学习了JavaWeb知识的之后,自己动手写一个demo的话可以更好的有助于之后阶段的学习。(应该)框架固然可以简化我们的开发流程,但如基本的JavaWeb都不熟练,又怎么会体验到框架的快捷性呢?
(快递e站本来是有微信端和后台两部分组成的,我微信端忘了好多,就不写了。)
   本demo实现了以下功能:
在这里插入图片描述
项目成功运行视频如下

后台视频

一,项目介绍

1.1项目背景

真实的:开课吧课程学习需要,培训进度到了。
虚假的:
   随着互联网和通信技术的高速发展,使电子商务迅速普及,网购成为人们购物的重要手段之一。据统计2019年双十一,11月11日~16日,受电商平台集中促销影响,业务量达全年高峰,6天内共处理邮(快)件23.09亿件。
   疫情期间配送快递成了一件难事。疫情防控已经趋于常态化,很多小区出台了新的治安管理条例,开始禁止快递人员进入。这给民众收发快件造成了极大的不便,因进不去小区,快递人员只能在小区门口周边摆摊设点,也影响了小区周边环境。
   除了快递,外卖也一样面临相同的问题。除了小区,写字楼、校园也面临着相同的问题。正是基于对疫情期间配送最后一公里深刻的认识,我们探索出一条解决之道,那就是社区快递e栈(类似快递柜)。

1.2项目目的

   1、锻炼编码能力
   2、融会贯通JavaWeb技术
   3、体验项目开发流程
   4、做出上线级别的微信端+JavaWeb后端项目(我微信端做的有点水)
   5、为框架阶段打下前后端交互的基础

1.3项目涉及技术点

html、css、js、Jquery、bootstrap、layui、ajax、mysql、tomcat、servlet、filter、jsp,Javaweb相关知识点。

1.4需求分析

   该快递项目按照用户分为三层,管理员,普通用户和快递员,管理员可以对用户和快递员的数据进行增删改查操作,以及对快递的增删改查。管理员可以对快递进行增删改查,用户可以取件,也可以查看自己的快递情况。
   按照功能模块分为登录模块,用户模块,快递员模块,快递模块,控制台模块,本系统主要是面向管理员端的后台关联系统。

二,搭建项目前准备

2.1编写MVC框架

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

2.1.1编写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>DispatherServlet</servlet-name>
        <servlet-class>com.kaikeba.mvc.DispatherServlet</servlet-class>
        <!--初始化配置文件-->
        <init-param>
            <param-name>contentConfigLocation</param-name>
            <param-value>application.properties</param-value>
        </init-param>
        <!--服务器启动的时候就加载这个servlet-->
        <load-on-startup>0</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>DispatherServlet</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>
</web-app>

2.1.2定义两个注解

package com.kaikeba.mvc;

import java.lang.annotation.*;

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

import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
/**
 * 注解的作用:
 *  被此注解添加的方法, 会被用于处理请求。
 *  方法返回的内容,会直接重定向
 */
public @interface ResponseView {
   
    String value();
}

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

package com.kaikeba.mvc;

/**
 * 枚举:用于描述响应的类型:文字;ResponseBody,视图;ResponseView
 */
public enum ResponseType {
   
    TEXT,VIEW;
}

2.1.3 编写映射器 HandlerMapping

package com.kaikeba.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 {
   

    // 静态的map集合,字符串加上mvc映射对象
    private static Map<String,MVCMapping> data = new HashMap<>();

    // 获取map集合中的对应方法
    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){
    // 如果注解的类型是ResponseBody
                                //说明此方法,用于返回字符串给客户端
                                MVCMapping mapping = new MVCMapping(obj,m,ResponseType.TEXT);
                                Object o = data.put(((ResponseBody) annotation).value(),mapping);
                                if(o != null){
   
                                    //存在了重复的请求地址
                                    throw new RuntimeException("请求地址重复:"+((ResponseBody) annotation).value());
                                }
                            }else if(annotation instanceof ResponseView){
    // 如果注解的类型是ResponseView
                                //说明此方法,用于返回界面给客户端
                                MVCMapping mapping = new MVCMapping(obj,m,ResponseType.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 ResponseType type; // 泛型

        public MVCMapping() {
   
        }

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

        public Object getObj() {
   
            return obj;
        }

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

        public Method getMethod() {
   
            return method;
        }

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

        public ResponseType getType() {
   
            return type;
        }

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

2.1.4 定义分发Servlet

package com.kaikeba.mvc;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
public class DispatherServlet extends javax.servlet.http.HttpServlet {
   

    @Override
    public void init(ServletConfig config) throws ServletException {
   
        // 读取配置文件的文件名称
        String path = config.getInitParameter("contentConfigLocation");
        // 加载配置文件
        InputStream is = DispatherServlet.class.getClassLoader().getResourceAsStream(path);
        // 常规方法加载
        /* //Properties可以用来保存属性集,主要用于读取Java的配置文件
        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();
        // 根据url得到MVCMapping映射对象
        HandlerMapping.MVCMapping mapping = HandlerMapping.get(uri);
        if( mapping == null){
   
            resp.sendError(404,"MVC:映射地址不存在:"+uri);
            return;
        }
        Object obj = mapping.getObj();
        Method method = mapping.getMethod();
        Object result = null;
        try {
   
            // 参数1.obj对象要执行method方法
            // 参数2.调用方法时传递的参数 req, resp 请求,响应对象
            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;
        }
    }

}

2.2layui介绍

layui官网地址

2.2.1布局部分

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

2.2.2 弹出层

步骤:
   1.下载layer , 并将解压后的layer文件夹 移动到项目中
   2.引入jquery.js
   3.引入layer.js
layer - msg函数
用于弹出信息提示框
   格式1:

layer.msg("文本");

   格式2 抖动显示:

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

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

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

   
      关闭loading:

layer.close(index);

   格式2
     超时自动关闭的loading

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

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

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

   关闭的格式:

layer.close(index);

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

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

layer - tips函数 提示层
   格式:

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

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

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

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

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

2.3工具类介绍

2.3.1DruidUtil

进行数据库连接池的工具类

package com.kaikeba.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();
        }
    }
}

2.3.2DateFormatUtil

时间格式化工具类

package com.kaikeba.util;

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

/**
 * 时间日期格式化工具
 */
public class DataFormatUtil {
   

    private static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //字符串转日期类型

    public static String format(Date date){
    // 把传入的Date类型转换为我们定义的Date类型
        return format.format(date);
    }
}

2.3.3随机数工具类

package com.kaikeba.util;

import java.util.Random;

/**
 * @Description : 生成随机取件码
 * @Author : Administrator
 * @Date : 2021/11/17 7:56
 * @Version : 1.0
 **/
public class RandomUtil {
   
    private static Random r = new Random();
    public static int getCode(){
   
        return r.nextInt(900000)+100000;
    };
}

2.3.4Json操作类

package com.kaikeba.util;

import com.google.gson.Gson;

/**
 * @Description : 为了更好的把数据返回给用户,返回Gson类型的数据给用户
 * @Author : Administrator
 * @Date : 2021/11/15 10:24
 * @Version : 1.0
 **/
public class JSONUtil {
   

    private static Gson g = new Gson();
    public static String toJSON(Object obj){
    // 把对象变为json字符串
        return g.toJson(obj);
    }
}

2.3.5用户的工具类

package com.kaikeba.util;

import com.kaikeba.bean.User;
import javax.servlet.http.HttpSession;

/**
 * @Description : 用户的工具类,
 * @Author : Administrator
 * @Date : 2021/11/17 22:05
 * @Version : 1.0
 **/
public class UserUtil {
   
    public static String getUserName(HttpSession session){
   // 根据session获取当前登录的用户名
        return (String) session.getAttribute("adminUserName");
    }
    public static String getUserPhone(HttpSession session){
   // 根据session获取当前登录的用户手机号
        // TODO : 还没有编写柜子端,未存储任何的录入人信息
        return "18888888888";
    }
}

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

package com.kaikeba.bean;

/**
 * @Description : 专门一个发消息的类
 * @Author : Administrator
 * @Date : 2021/11/15 10:13
 * @Version : 1.0
 **/
public class Message {
   

    //状态码: 0成功,-1表示失败
    private int status;
    //消息内容
    private String result;
    //消息所携带的一组数据
    private Object data;


    public int getStatus() {
   
        return status;
    }

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

    public String getResult() {
   
        return result;
    }

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

    public Object getData() {
   
        return data;
    }

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

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

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

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

    public Message() {
   
    }

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

2.3.7包装分页数据的类

package com.kaikeba.bean;

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

/**
 * @Description : 包装分页数据的一种格式
 * @Author : Administrator
 * @Date : 2021/11/17 16:20
 * @Version : 1.0
 **/
public class ResultData<T> {
   
    //每次查询的数据集合(存储分页的数据)
    private List<T> rows = new ArrayList<>();
    //总数量(长度)
    private int total;

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

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

    public int getTotal() {
   
        return total;
    }

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

2.3.8自定义的异常类

取件码重复异常:

package com.kaikeba.exception;

/**
 * @Description : 异常类:取件码重复异常
 * @Author : Administrator
 * @Date : 2021/11/17 7:20
 * @Version : 1.0
 **/
public class DuplicateCodeException extends Exception{
   
    /**
     * Constructs a new exception with {@code null} as its detail message.
     * The cause is not initialized, and may subsequently be initialized by a
     * call to {@link #initCause}.
     */
    public DuplicateCodeException() {
   
    }

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

2.4数据库设计+实体类编写

2.4.1数据库分析

   之前的需求分析中有说到。要实现登录模块,用户模块,快递员模块,快递模块,控制台模块。那么就要创建自少四张表。管理员表,用户表,快递员表,快递员表。
管理员表
在这里插入图片描述
用户表
在这里插入图片描述
快递员表
在这里插入图片描述
快递表
在这里插入图片描述
其实单看这几张表的话,也能感觉到这是一个很简单的练手项目。甚至还不如他的前置项目表复杂。基本都是单表操作。具体的表内容就大家自己创建了。

2.4.2实体类

根据所创建的sql创建对应的类
类名=表名,属性名=列名
1,管理员类不用创建对应的实体类。
2,再创建时间类型的属性时,把他定义为String类型的,方便用对应的工具类显示
User:

package com.kaikeba.bean;

import java.sql.Timestamp;

/**
 * @Description : 同样也是用户实体类,不过这里用了字符类型来结束时间参数
 * @Author : Administrator
 * @Date : 2021/11/18 16:55
 * @Version : 1.0
 **/
public class BootStrapTableUser {
   
    private int id;
    private String username;
    private String userphone;
    private String idcard;
    private String userpassword;

    private String registeradtime;
    private String login_time;
    private int status;

    public int getStatus() {
   
        return status;
    }

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

    public BootStrapTableUser() {
   
    }

    public BootStrapTableUser(int id, String username, String userphone, String idcard, String userpassword, String registeradtime, String login_time, int status) {
   
        this.id = id;
        this.username = username;
        this.userphone = userphone;
        this.idcard = idcard;
        this.userpassword = userpassword;
        this.registeradtime = registeradtime;
        this.login_time = login_time;
        this.status = status;
    }

    public BootStrapTableUser(String username, String userphone, String idcard, String userpassword, int operation) {
   
        this.username = username;
        this.userphone = userphone;
        this.idcard = idcard;
        this.userpassword = userpassword;
    }

    public BootStrapTableUser(int id, String username, String userphone, String idcard, String userpassword, String registeradtime, String login_time) {
   
    }

    @Override
    public String toString() {
   
        return "BootStrapTableUser{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", userphone='" + userphone + '\'' +
                ", idcard='" + idcard + '\'' +
                ", userpassword='" + userpassword + '\'' +
                ", registeradtime='" + registeradtime + '\'' +
                ", login_time='" + login_time + '\'' +
                ", status=" + status +
                '}';
    }

    public int getId() {
   
        return id;
    }

    public void setId(int id) {
   
        this.id = id;
    }

    public String getUsername() {
   
        return username;
    }

    public void setUsername(String username) {
   
        this.username = username;
    }

    public String getUserphone() {
   
        return userphone;
    }

    public void setUserphone(String userphone) {
   
        this.userphone = userphone;
    }

    public String getIdcard() {
   
        return idcard;
    }

    public void setIdcard(String idcard) {
   
        this.idcard = idcard;
    }

    public String getUserpassword() {
   
        return userpassword;
    }

    public void setUserpassword(String userpassword) {
   
        this.userpassword = userpassword;
    }

    public String getRegisteradtime() {
   
        return registeradtime;
    }

    public void setRegisteradtime(String registeradtime) {
   
        this.registeradtime = registeradtime;
    }

    public String getLogin_time() {
   
        return login_time;
    }

    public void setLogin_time(String login_time) {
   
        this.login_time = login_time;
    }

}

Express:

package com.kaikeba.bean;

/**
 * @Description : 同样也是快递实体类,不过这里用了字符类型来结束时间参数
 * @Author : Administrator
 * @Date : 2021/11/17 16:20
 * @Version : 1.0
 **/
public class BootStrapTableExpress {
   

    private int id;
    private String number;
    private String username;
    private String userPhone;
    private String company;
    private String code;
    private String inTime;
    private String outTime;
    private String status;
    private String sysPhone;

    private Courier Courier;

    public BootStrapTableExpress() {
   
    }

    public BootStrapTableExpress(int id, String number, String username, String userPhone, String company, String code, String inTime, String outTime, String status, String sysPhone) {
   
        this.id = id;
        this.number = number;
        this.username = username;
        this.userPhone = userPhone;
        this.company = company;
        this.code = code;
        this.inTime = inTime;
        this.outTime = outTime;
        this.status = status;
        this.sysPhone = sysPhone;
    }

    public BootStrapTableExpress(int id, String number, String username, String userPhone, String company, String code, String inTime, String outTime, String status, String sysPhone, com.kaikeba.bean.Courier courier) {
   
        this.id = id;
        this.number = number;
        this.username = username;
        this.userPhone = userPhone;
        this.company = company;
        this.code = code;
        this.inTime = inTime;
        this.outTime = outTime;
        this.status = status;
        this.sysPhone = sysPhone;
        Courier = courier;
    }

    @Override
    public String toString() {
   
        return "BootStrapTableExpress{" +
                "id=" + id +
                ", number='" + number + '\'' +
                ", username='" + username + '\'' +
                ", userPhone='" + userPhone + '\'' +
                ", company='" + company + '\'' +
                ", code='" + code + '\'' +
                ", inTime='" + inTime + '\'' +
                ", outTime='" + outTime + '\'' +
                ", status='" + status + '\'' +
                ", sysPhone='" + sysPhone + '\'' +
                ", Courier=" + Courier +
                '}';
    }

    public int getId() {
   
        return id;
    }

    public void setId(int id) {
   
        
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值