JavaWeb之书城项目(1)

该文档是:JavaWeb之书城项目巩固JavaWeb知识

博客连接:https://www.loveuluo.cn

日期:2020-12-22

1. JavaEE三层架构

image-20201207154850881

分层的目的是为了解耦。解耦就是为了降低代码的耦合度。方便项目后期的维护和升级。

image-20201207161932247

2. 搭建三层架构并导入静态页面等资源

image-20201207162521121

image-20201207160004577

image-20201207162427971

3. 创建登录注册所需数据库和表

image-20201207163711595

drop database if exists book;
create database book;
use book;
create table t_user(
`id` int primary key auto_increment,
`username` varchar(20) not null unique,
`password` varchar(32) not null,
`email` varchar(200)
);
insert into t_user(`username`,`password`,`email`) values('admin','admin','admin@atguigu.com');
select * from t_user;

4. 编写登录注册数据库表对应的 JavaBean 对象

image-20201207164135521

public class User {
    private Integer id;
    private String username;
    private String password;
    private String email;
} //省略get/set 构造方法等,用idea直接生成

5. 编写工具类JdbcUtils

在src下创建druid.properties配置文件:

url=jdbc:mysql://localhost:3306/book
username=root
password=123456
driverClassName=com.mysql.jdbc.Driver

initialSize=10
maxActive=20
maxWait=1000
filters=wall

JDBCUtils工具类:

public class JDBCUtils {
    //连接池只需要一个,所以放在静态代码块中
    private static DataSource dataSource;
    static {
        Properties pro = new Properties();
            //这里必须要加上JdbcUtils.class
            InputStream is = JdbcUtils.class.getClassLoader().getResourceAsStream("druid.properties");
        try {
            pro.load(is); //加载配置文件
            dataSource = DruidDataSourceFactory.createDataSource(pro); //传入Properties 得到连接池
        }catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取数据库连接池中的连接
     * @return 如果返回 null,说明获取连接失败,有值就是获取连接成功
     */
    public static Connection getConnection(){
        Connection conn=null;
        try {
            conn = dataSource.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return conn;
    }

    /**
     * 关闭连接,放回数据库连接池
     * @param conn
     */
    public static void close(Connection conn){
        try {
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

6. 编写BaseDao

使用 DbUtils 进行简化操作:

/**
 * 定义一个用来被继承的对数据库进行基本操作的Dao
 * @param <T>
 */
public abstract class BaseDao<T> {
    // 使用 DbUtils 操作数据库
    private QueryRunner queryRunner = new QueryRunner();
    // 定义一个变量来接收泛型的类型
    private Class<T> type;

    // 获取T的Class对象,获取泛型的类型,泛型是在被子类继承时才确定 (构造方法,只要子类创建对象就会执行)
    public BaseDao() { //这里操作是可以直接读取到泛型的类型,那么查询的方法里就不需要再手动传类的字节码对象进去了
        // 获取子类的类型
        Class clazz = this.getClass();
        // 获取父类的类型
        // getGenericSuperclass()用来获取当前类的父类的类型
        // ParameterizedType表示的是带泛型的类型
        ParameterizedType parameterizedType = (ParameterizedType) clazz.getGenericSuperclass();
        // 获取具体的泛型类型 getActualTypeArguments获取具体的泛型的类型
        // 这个方法会返回一个Type的数组
        Type[] types = parameterizedType.getActualTypeArguments();
        // 获取具体的泛型的类型·
        this.type = (Class<T>) types[0];
    }

    /**
     * 通用的增删改语句
     * @param conn 需要传入连接对象,因为可能涉及到事务
     * @param sql 执行的 sql 语句
     * @param objects sql对应的参数值
     * @return 返回成功执行的数量
     */
    public int update(Connection conn,String sql,Object...objects){
        int count=0;
        try {
            count = queryRunner.update(conn, sql, objects);//需要传入连接,sql语句,和参数
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return count;
    }

    /**
     * 查询返回一个 javaBean 的 sql 语句
     * @param conn 需要传入连接对象,因为可能涉及到事务
     * @param sql 执行的 sql 语句
     * @param objects sql对应的参数值
     * @return 返回对应泛型的对象
     */
    public T queryForOne(Connection conn,String sql,Object...objects){
        T t = null;
        try {
            t  = queryRunner.query(conn, sql, new BeanHandler<T>(type), objects); //type代表泛型的类型字节码对象
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return t;
    }

    /**
     * 查询返回多个 javaBean 的 sql 语句
     * @param conn 需要传入连接对象,因为可能涉及到事务
     * @param sql 执行的 sql 语句
     * @param objects sql对应的参数值
     * @return 返回对应泛型的对象集合
     */
    public List<T> queryForList(Connection conn,String sql,Object...objects){
        List<T> list = null;
        try {
            list = queryRunner.query(conn, sql, new BeanListHandler<T>(type), objects); //type代表泛型的类型字节码对象
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return list;
    }

    /**
     * 执行返回一行一列的 sql 语句(例如最大员工年龄,这个表有几条数据)
     * @param conn 需要传入连接对象,因为可能涉及到事务
     * @param sql 执行的 sql 语句
     * @param objects objects sql对应的参数值
     * @return
     */
    public Object queryForSingleValue(Connection conn,String sql,Object...objects){
        Object value=null;
        try {
           value = queryRunner.query(conn,sql,new ScalarHandler(),objects);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return value;
    }
    
}

7. 编写UserDao和UserDaoImpl

image-20201210190408243

UserDao 接口:

public interface UserDao {
    /**
     * 根据用户名查询用户信息
     * @param con
     * @param user
     * @return 如果返回null,说明没有这个用户,反之亦然
     */
    public User queryUserByUsername(Connection con,User user);

    /**
     * 根据 用户名和密码查询用户信息
     * @param con
     * @param user
     * @return 如果返回null,说明用户名或密码错误,反之亦然
     */
    public User queryUserByUsernameAndPassword(Connection con,User user);

    /**
     * 保存用户信息
     * @param con
     * @param user
     * @return 返回-1表示操作失败,其他是sql语句影响的行数
     */
    public int saveUser(Connection con,User user);
}

UserDaoImpl 实现类:

public class UserDaoImpl extends BaseDao<User> implements UserDao {
    @Override
    public User queryUserByUsername(Connection con, User user) {
        User bean=null;
        String sql="SELECT id,username,password,email FROM t_user WHERE username=?";
        bean = queryForOne(con, sql, user.getUsername());
        return bean;
    }

    @Override
    public User queryUserByUsernameAndPassword(Connection con, User user) {
        User bean=null;
        String sql="SELECT id,username,password,email FROM t_user WHERE username=? AND password=?";
        bean = queryForOne(con, sql, user.getUsername(), user.getPassword());
        return bean;
    }

    @Override
    public int saveUser(Connection con, User user) {
        String sql="INSERT INTO t_user(`username`,`password`,`email`) values(?,?,?)";
         return update(con,sql,user.getUsername(),user.getPassword(),user.getEmail());
    }
}

## 8. 编写UserService和UserServiceImpl

image-20201210193358462

UserService 接口:

public interface UserService {
    /**
     * 注册用户
     * @param user
     */
    public void register(User user);

    /**
     *  登录
     * @param user
     * @return 如果返回null,说明登录失败,返回有值,是登录成功
     */
    public User login(User user);

    /**
     * 检查用户名是否可用
     * @param user
     * @return 返回true表示用户名已存在,返回fals表示用户名可用
     */
    public boolean existsUsername(User user);
}

UserServiceImpl 实现类:

public class UserServiceImpl implements UserService {
    private UserDao userDao=new UserDaoImpl();
    @Override
    public void register(User user) {
        Connection con = JDBCUtils.getConnection();
        userDao.saveUser(con,user);
        JDBCUtils.close(con);
    }

    @Override
    public User login(User user) {
        User bean=null;
        Connection con = JDBCUtils.getConnection();
        bean = userDao.queryUserByUsernameAndPassword(con, user);
        JDBCUtils.close(con);
        return bean;
    }

    @Override
    public boolean existsUsername(User user) {
        User bean=null;
        Connection con = JDBCUtils.getConnection();
        bean = userDao.queryUserByUsername(con, user);
        if (bean == null){ //如果是空的就代表可以注册 返回true
            return true;
        }
        JDBCUtils.close(con);
        return false; //代表不能注册
    }
}

9. 注册登录页面正则表达式验证

验证用户名:必须由字母,数字下划线组成,并且长度为 5 到 12 位
验证密码:必须由字母,数字下划线组成,并且长度为 5 到 12 位
验证确认密码:和密码相同
邮箱验证:xxxxx@xxx.com
验证码:现在只需要验证用户已输入。因为还没讲到服务器。验证码生成。

注册页面代码(登录页面同理):

<script type="text/javascript" src="../../static/script/jquery-1.7.2.js"></script>
<script type="text/javascript">
   //入口函数
   $(function () {
      //当点击注册按钮时验证所有
      $("#sub_btn").click(function () {
               // 验证用户名:必须由字母,数字下划线组成,并且长度为 5 到 12 位
         // 1.获取用户名输入框的值
         var usernameText = $("#username").val();
         // 2.创建正则表达式
               var usernamePatt = /^\w{5,12}$/;
               // 3.用正则表达式验证输入的值
         if (!usernamePatt.test(usernameText)){
               // 4.如果值不正确进行提示(修改errorMsg中的值)
         $(".errorMsg").html("用户名不合法!");
         // 该设置可以让当用户名不合法的时候不跳转登陆成功页面
         return false;
         }

               // 验证密码:必须由字母,数字下划线组成,并且长度为 5 到 12 位
               // 1.获取密码输入框的值
               var passwordText = $("#password").val();
               // 2.创建正则表达式
               var passwordPatt = /^\w{5,12}$/;
               // 3.用正则表达式验证输入的值
               if (!passwordPatt.test(passwordText)) {
                   // 4.如果值不正确进行提示(修改errorMsg中的值)
                   $(".errorMsg").html("密码不合法!");
                   // 该设置可以让当用户名不合法的时候不跳转登陆成功页面
                   return false;
               }

               // 验证确认密码:必须和密码一致
         // 1.获取确认密码输入框的值
               var repwdText = $("#repwd").val();
               // 2.和密码输入框的值进行对比
         if (repwdText!=passwordText) {
             // 3.如果不相等进行提示
                   $(".errorMsg").html("确认密码和密码不相同!");
                   // 该设置可以让当用户名不合法的时候不跳转登陆成功页面
                   return false;
         }

               // 邮箱验证: xxxxx@xxx.com
         //1 获取邮箱输入框的值
               var emailText = $("#email").val();
         //2 创建正则表达式对象
               var emailPatt = /^[a-z\d]+(\.[a-z\d]+)*@([\da-z](-[\da-z])?)+(\.{1,2}[a-z]+)+$/;
         //3 使用 test 方法验证是否合法
               if (!emailPatt.test(emailText)) {
         //4 提示用户
                   $("span.errorMsg").text(" 邮箱格式不合法!");
                   // 该设置可以让当用户名不合法的时候不跳转登陆成功页面
                   return false;
               }
               
               // 验证码:现在只需要验证用户已输入。因为还没讲到服务器。验证码生成。
               var codeText = $("#code").val();
         // 用trim去掉验证码前后空格
               codeText = $.trim(codeText);
               if (codeText == null || codeText == "") {
         // 提示用户
                   $("span.errorMsg").text(" 验证码不能为空!");
                   return false;
               }

         //当以上的都正确时,把错误消息去掉,因为跳转页面的时候可能有延时,错误信息还存在不好看
               $("span.errorMsg").text("");

           })
       })

</script>

10. 实现用户的注册功能

10.1 图解用户注册的流程:

image-20201210194050660

10.2 添加base标签

image-20201210203702158

因为整个页面的相对路劲都变成base标签里写的了,所以之前的受到影响的路劲需要改一下:

image-20201210201909543

10.3 修改注册表单的提交地址和请求方式

为什么使用post?因为post提交的数据不会再地址栏出现,密码比较安全不会被人在地址栏看到。

10.4 编写 RegistServlet 程序

public class RegistServlet extends HttpServlet {
    private UserService service=new UserServiceImpl();

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取请求的参数
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String email = request.getParameter("email");
        String code = request.getParameter("code");
        User user = new User(null,username,password,email);

        //1.判断验证码是否正确
        if ("abcd".equalsIgnoreCase(code)){ //如果正确,这里还没学,暂时只能写死验证码
        //2.判断用户名是否存在
            boolean flag = service.existsUsername(user);
            if (flag){ //如果用户名不存在
                service.register(user);//调用Service保存用户
                // 跳到注册成功页面 regist_success.html
                request.getRequestDispatcher("/pages/user/regist_success.html").forward(request, response);
            }else { //如果用户名已存在
                System.out.println("用户名已存在");
                request.getRequestDispatcher("/pages/user/regist.html").forward(request,response); //请求转发也就是跳转回注册页面
            }
        } else { //如果验证码不正确
            System.out.println("验证码错误!");
            request.getRequestDispatcher("/pages/user/regist.html").forward(request,response); //请求转发也就是跳转回注册页面
        }
    }

}

11. IDEA 中Debug调试的简单使用

Debug调试代码,首先需要两个元素:断点 + Debug启动服务器。

image-20201211093105760

测试工具栏:

image-20201211093125905

使用说明:

image-20201211093148253

image-20201211093136657

image-20201211093141351

image-20201211093225112

image-20201211093231106

变量窗口:

image-20201211093245394

方法调用栈窗口:

image-20201211093330882

其他常用调试相关按钮:

image-20201211093342866

12. 实现用户的登录功能

12.1 图解用户登录的流程:

image-20201211095344717

12.2 添加base标签

image-20201211095636402

因为整个页面的相对路劲都变成base标签里写的了,所以之前的受到影响的路劲需要改一下:

image-20201211095648937

12.3 修改注册表单的提交地址和请求方式

image-20201211095800076

12.4 编写 LoginServlet 程序

public class LoginServlet extends HttpServlet {
    private UserService service=new UserServiceImpl();

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取请求参数
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        User user=new User(null,username,password,null);

        //调用service判断用户名密码是否正确
        User login = service.login(user);
        //如果user是null,说明没有查询到对象,说明账户密码错误了
        if (login == null){
            System.out.println("用户名密码错误");
            //跳转回登录页面
            request.getRequestDispatcher("/pages/user/login.html").forward(request,response);
        }else {
            //登陆成功
            // 跳到成功页面 login_success.html
            request.getRequestDispatcher("/pages/user/login_success.html").forward(request, response);
        }
    }
}

13. 页面jsp动态化

将所有页面都改为jsp页面,比较灵活:

1、在 html 页面顶行添加 page 指令。
2、修改文件后缀名为:.jsp
3、使用 IDEA 搜索替换.html 为.jsp(快捷键:Ctrl+Shift+R)

image-20201214154450724

14. 用静态包含抽取页面中相同的内容

14.1 每个页面head 中 cs、jquery、base 标签抽取出来

抽取为一个head.jsp 方便管理,以后只要更改这一处,所有使用了这个的都会跟着变:

image-20201214154746005

代码(这里的base标签使用动态获取,因为如果客户访问的话使用localhost的话那么就会访问他自己的电脑,所以服务器ip需要动态获取):

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
    String basePath = request.getScheme() //获取浏览器协议 例如http或者https(动态的)
            + "://"
            + request.getServerName() //浏览器输入的ip是什么这里获取到的就是什么(动态的)
            + ":"
            + request.getServerPort() //获取端口号(动态的)
            + request.getContextPath() //获取工程路径(动态的)
            + "/";
%>

<!--写base标签,永远固定相对路径跳转的结果-->
<!--例如浏览器输入的是192.168.33.33:8080/book/ 那么下边的base标签就是http://192.168.33.33:8080/book/-->
<base href="<%=basePath%>">
<link type="text/css" rel="stylesheet" href="static/css/style.css" >
<script type="text/javascript" src="static/script/jquery-1.7.2.js"></script>

例如在index.jsp或login.jsp中使用它(只需要加上这一行静态包含,就代表上边的代码直接显示在这里一个样,上边的改了这里的也会随之改动):

image-20201214154838705

image-20201214155236328

14.2 每个页面的页脚

将页脚抽取出来,跟上边同理!

%>
<%=basePath%>
<!-写 base 标签,永远固定相对路径跳转的结果->
<base href="<%=basePath%>">
<link type="text/cs" rel="styleshet" href="staic/s/style.cs" >
<scriptype="text/javscript" src="staic/script/jquery-1.72.js"></script>

14.3 登录成功后的菜单

将登录成功后的菜单抽取出来,跟上边同理!

<div>
    <span>欢迎<span clas="um_span">韩总</span>光临尚硅谷书城</span>
    <a href="./order/order.jsp">我的订单</a>
    <a href="././index.jsp">注销</a>&nbsp;&nbsp;
    <a href="././index.jsp">返回</a>
</div>

14.4 manger 模块的菜单

将manger模块的菜单抽取出来,跟上边同理!

<div>
<a href="bok_manger.jsp">图书管理</a>
<a href="order_manger.jsp">订单管理</a>
<a href="././index.jsp">返回商城</a>
</div>

15. 登录,注册错误提示,及表单回显

以登录回显为示例(注册同理):

对LoginServlet 程序端进行修改,添加回显信息到 Request 域中:

image-20201214164251609

jsp 页面修改,需要输出回显信息:

image-20201214164635192

16. BaseServlet抽取

在实际的项目开发中,一个模块,一般只使用一个 Servlet 程序。

16.1 代码优化一

代码优化:合并 LoginServlet 和 RegistServlet 程序为 UserSvlet 程序

图解:

image-20201214181119523

在页面中的form表单添加隐藏域以便在Servlet中分辨是什么。

注册的隐藏域:

image-20201214181042302

登录的隐藏域:

image-20201214181243223

UserServlet 程序:

public class UserServlet extends HttpServlet {
    private UserService service=new UserServiceImpl();

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1.根据name获取隐藏域的value值
        String action = request.getParameter("action");
        // 2.判断value值是regist还是login以便执行方法
        if ("login".equals(action)){
            //调用登录的方法
            login(request,response);
        } else if ("regist".equals(action)){
            //调用注册的方法
            regist(request,response);
        }
    }

    /**
     * 处理登录的功能
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    public void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取请求参数
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        User user=new User(null,username,password,null);

        //调用service判断用户名密码是否正确
        User login = service.login(user);
        //如果user是null,说明没有查询到对象,说明账户密码错误了
        if (login == null){
            System.out.println("用户名密码错误");
            // 把回显信息,保存到Request域中
            request.setAttribute("msg","用户名或密码错误"); //回显错误的原因信息
            request.setAttribute("username",username); //回显用户名,这样的话用户输入的用户名还保存着,不用再次输入
            //跳转回登录页面
            request.getRequestDispatcher("/pages/user/login.jsp").forward(request,response);
        }else {
            //登陆成功
            // 跳到成功页面 login_success.html
            request.getRequestDispatcher("/pages/user/login_success.jsp").forward(request, response);
        }
    }

    /**
     * 处理注册的功能
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    public void regist(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取请求的参数
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String email = request.getParameter("email");
        String code = request.getParameter("code");
        User user = new User(null,username,password,email);

        //1.判断验证码是否正确
        if ("abcd".equalsIgnoreCase(code)){ //如果正确,这里还没学,暂时只能写死验证码
            //2.判断用户名是否存在
            boolean flag = service.existsUsername(user);
            if (flag){ //如果用户名不存在
                service.register(user);//调用Service保存用户
                // 跳到注册成功页面 regist_success.html
                request.getRequestDispatcher("/pages/user/regist_success.html").forward(request, response);
            }else { //如果用户名已存在
                System.out.println("用户名已存在");
                // 把回显信息,保存到Request域中
                request.setAttribute("msg","用户名已存在!"); //回显错误的原因信息
                request.setAttribute("username",username); //回显用户名,这样的话用户输入的用户名还保存着,不用再次输入
                request.setAttribute("email",email); //回显邮箱,这样的话用户输入的用户名还保存着,不用再次输入
                request.getRequestDispatcher("/pages/user/regist.jsp").forward(request,response); //请求转发也就是跳转回注册页面
            }
        } else { //如果验证码不正确
            System.out.println("验证码错误!");
            request.setAttribute("msg","用户名已存在!"); //回显错误的原因信息
            request.setAttribute("username",username); //回显用户名,这样的话用户输入的用户名还保存着,不用再次输入
            request.setAttribute("email",email); //回显邮箱,这样的话用户输入的用户名还保存着,不用再次输入
            request.getRequestDispatcher("/pages/user/regist.jsp").forward(request,response); //请求转发也就是跳转回注册页面
        }
    }
}

16.2 优化代码二

使用反射优化大量 else if 代码:

因为UserServlet将来可能有各种功能,例如修改密码啊,修改名称之类的。可能会存在大量的else if,代码臃肿且麻烦。发现有一个规律,隐藏域里的value的值和方法名相同,那么可以通过反射根据value的值来调用方法!

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1.根据name获取隐藏域的value值
        String action = request.getParameter("action");
        // 2.根据value使用反射调用方法(value的值和方法名相同)
        try {
            Method declaredMethod = this.getClass().getDeclaredMethod(action, HttpServletRequest.class, HttpServletResponse.class);//获取到方法对象
            //调用目标业务方法
            declaredMethod.invoke(this,request,response); //传入对象(this是当前的对象实例),和参数
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

16.3 代码优化三:

抽取 BaseServlet 程序:

因为每个Servlet中都要写代 16.2 优化代码二 中的代码,所以干脆抽取BaseServlet出来,里边放的就是 16.2 优化代码二 中写的代码,只要继承这个BaseServlet,就能直接使用,方便代码复用!

网页访问例如UserServlet的时候,发现没有doPost方法,此时去父类找到doPost方法调用,所以此时BaseServlet中的反射方法中的this都相当于是子类(也就是UserServlet),这样的话就会去UserServlet中找对应value的方法名调用。

image-20201214192538986

BaseServlet 程序代码:

public abstract class BaseServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1.根据name获取隐藏域的value值
        String action = request.getParameter("action");
        // 2.根据value使用反射调用方法(value的值和方法名相同)
        try {
            Method declaredMethod = this.getClass().getDeclaredMethod(action, HttpServletRequest.class, HttpServletResponse.class);//获取到方法对象
            //调用目标业务方法
            declaredMethod.invoke(this,request,response); //传入对象(this是当前的对象实例),和参数
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

UserServlet继承BaseServlet:

image-20201214192744792

17. 数据的封装和抽取 BeanUtils 的使用

实际操作的时候实际的业务的参数可能有很多,一行一行去getParameter然后并且要放入User对象中,很麻烦。怎么一行代码解决呢!

BeanUtils 工具类,它可以一次性的把所有请求的参数注入到 JavBean 中。
BeanUtils 工具类,经常用于把 Map 中的值注入到 JavBean 中,或者是对象属性值的拷贝操作。

BeanUtils 它不是 Jdk 的类。而是第三方的工具类。所以需要导包。
1、导入需要的 jar 包:
comons-beanutils-1.80.jar
comons-loging-1.1.jar

2、编写 WebUtils 工具类使用:

WebUtils 工具类:

public class WebUtils {
    /**
     * 把 Map 中的值注入到对应的 JavaBean 属性中。
     * @param value
     * @param bean
     * @param <T>
     * @return
     */
    public static <T> T copyParmToBean(Map value , T bean ){
        try {
            System.out.println("注入之前:" + bean);
            /*
             * 把所有请求的参数都注入到 user 对象中
             * 只要Map集合的键和对象的属性相同,并且有set方法,就能成功注入
             */
            BeanUtils.populate(bean, value);
            System.out.println("注入之后:" + bean);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bean;
    }
}

3、在UserServlet中使用工具类 代替原来的方法:

例如注册方法,登录方法同理。

image-20201214200412941

最后修改:2020 年 12 月 22 日 07 : 48 PM
如果觉得我的文章对你有用,请随意赞赏