尚硅谷书城项目第三阶段——用户注册和登陆代码优化

472 阅读1分钟

尚硅谷书城项目第三阶段——用户注册和登陆代码优化

1、页面jsp动态化

1、将静态HTML网页后缀名改为 .jsp 2、在每个页面顶部添加jsp的page指令代码

全局搜索替换: Ctrl+Shift+R 在这里插入图片描述

2、 提取多个页面中相同的内容,单独做成一个页面用于文件包含

1、 将页面head标签中的css、jquery、base标签提取出来组成head.jsp页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!--添加base标签,
base标签一定在title标签的下面,紧跟着title标签
baase标签的值,一般在项目中,都设置到工程路径.也就是映射到IDEA代码的web目录
-->
<%
    String basePath = request.getScheme()
            + "://"
            + request.getServerName()
            + ":"
            + request.getServerPort()
            + request.getContextPath()
            + "/";
    pageContext.setAttribute("basePath", basePath);
%>
<base href="${ basePath }">
<link type="text/css" rel="stylesheet" href="static/css/style.css" >
<script src="static/script/jquery-1.7.2.js"></script>

2、 将每个页面的页脚代码提取出来组成footer.jsp页面

<div id="bottom">
      <span>
         尚硅谷书城.Copyright &copy;2020
      </span>
</div>

3、 将登录成功后的菜单代码提取出来,组成login_success_menu.jsp页面

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

4、 将manager模块代码提取,组成manager_menu.jsp页面

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

3、 登录与注册错误提示代码的编写以及表单回显

以登录举例,注册与之类似: 先保存需要回显到前端页面的信息到reqeust域中

public class LoginServlet extends HttpServlet {
    private UserService userService = new UserServiceImpl();
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //  1、获取请求的参数
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        // 调用 userService.login()登录处理业务
        User loginUser = userService.login(new User(null, username, password, null));
        // 如果等于null,说明登录 失败!
        if (loginUser == null) {
            // 把错误信息,和回显的表单项信息,保存到Request域中
            req.setAttribute("msg","用户或密码错误!");
            req.setAttribute("username", username);
            //   跳回登录页面
            req.getRequestDispatcher("/pages/user/login.jsp").forward(req, resp);
        } else {
            // 登录 成功
            //跳到成功页面login_success.html
            req.getRequestDispatcher("/pages/user/login_success.jsp").forward(req, resp);
        }
    }
}

在前端的jsp页面输出

<div class="msg_cont">
   <b></b>
   <span class="errorMsg">
      ${ empty requestScope.msg ? "请输入用户名和密码":requestScope.msg }
   </span>
</div>
<div class="form">
   <form action="userServlet" method="post">
      <input type="hidden" name="action" value="login" />
      <label>用户名称:</label>
      <input class="itxt" type="text" placeholder="请输入用户名"
            autocomplete="off" tabindex="1" name="username"
            value="${requestScope.username}" />
      <br />
      <br />
      <label>用户密码:</label>
      <input class="itxt" type="password" placeholder="请输入密码"
            autocomplete="off" tabindex="1" name="password" />
      <br />
      <br />
      <input type="submit" value="登录" id="sub_btn" />
   </form>
</div>

4、组合功能登陆与注册模块,将各个servlet代码重复部分提取出来, 实际开发中,一个模块一般只有一个Servlet。

1、将LoginServlet和RegistServlet组合成为UserServlet

public class UserServlet extends BaseServlet {
    private UserService userService = new UserServiceImpl();
    protected void ajaxExistsUsername(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 获取请求的参数username
        String username = req.getParameter("username");
        // 调用userService.existsUsername();
        boolean existsUsername = userService.existsUsername(username);
        // 把返回的结果封装成为map对象
        Map<String,Object> resultMap = new HashMap<>();
        resultMap.put("existsUsername",existsUsername);
        Gson gson = new Gson();
        String json = gson.toJson(resultMap);
        resp.getWriter().write(json);
    }
    /**
     * 注销
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    protected void logout(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        1、销毁Session中用户登录的信息(或者销毁Session)
        req.getSession().invalidate();
//        2、重定向到首页(或登录页面)。
        resp.sendRedirect(req.getContextPath());
    }
    /**
     * 处理登录的功能
     *
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    protected void login(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //  1、获取请求的参数
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        // 调用 userService.login()登录处理业务
        User loginUser = userService.login(new User(null, username, password, null));
        // 如果等于null,说明登录 失败!
        if (loginUser == null) {
            // 把错误信息,和回显的表单项信息,保存到Request域中
            req.setAttribute("msg", "用户或密码错误!");
            req.setAttribute("username", username);
            //   跳回登录页面
            req.getRequestDispatcher("/pages/user/login.jsp").forward(req, resp);
        } else {
            // 登录 成功
            // 保存用户登录的信息到Session域中
            req.getSession().setAttribute("user", loginUser);
            //跳到成功页面login_success.html
            req.getRequestDispatcher("/pages/user/login_success.jsp").forward(req, resp);
        }
    }
    /**
     * 处理注册的功能
     *
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    protected void regist(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 获取Session中的验证码
        String token = (String) req.getSession().getAttribute(KAPTCHA_SESSION_KEY);
        // 删除 Session中的验证码
        req.getSession().removeAttribute(KAPTCHA_SESSION_KEY);
        //  1、获取请求的参数
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        String email = req.getParameter("email");
        String code = req.getParameter("code");
        User user = WebUtils.copyParamToBean(req.getParameterMap(), new User());
//        2、检查 验证码是否正确  === 写死,要求验证码为:abcde
        if (token!=null && token.equalsIgnoreCase(code)) {
//        3、检查 用户名是否可用
            if (userService.existsUsername(username)) {
                System.out.println("用户名[" + username + "]已存在!");
                // 把回显信息,保存到Request域中
                req.setAttribute("msg", "用户名已存在!!");
                req.setAttribute("username", username);
                req.setAttribute("email", email);
//        跳回注册页面
                req.getRequestDispatcher("/pages/user/regist.jsp").forward(req, resp);
            } else {
 //                调用Sservice保存到数据库
                userService.registUser(new User(null, username, password, email));
//
//        跳到注册成功页面 regist_success.jsp
                req.getRequestDispatcher("/pages/user/regist_success.jsp").forward(req, resp);
            }
        } else {
            // 把回显信息,保存到Request域中
            req.setAttribute("msg", "验证码错误!!");
            req.setAttribute("username", username);
            req.setAttribute("email", email);

            System.out.println("验证码[" + code + "]错误");
            req.getRequestDispatcher("/pages/user/regist.jsp").forward(req, resp);
        }
    }
}

2、将各个servlet代码重复部分提取出来组成BaseServlet

public abstract class BaseServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 解决post请求中文乱码问题
        // 一定要在获取请求参数之前调用才有效
        req.setCharacterEncoding("UTF-8");
        // 解决响应的中文乱码
        resp.setContentType("text/html; charset=UTF-8");
        String action = req.getParameter("action");
        try {
            // 获取action业务鉴别字符串,获取相应的业务 方法反射对象
            Method method = this.getClass().getDeclaredMethod(action, HttpServletRequest.class, HttpServletResponse.class);
//            System.out.println(method);
            // 调用目标业务 方法
            method.invoke(this, req, resp);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);// 把异常抛给Filter过滤器
        }
    }
}

其他模块的Servlet,继承BaseServlet抽象类就可以了。

5、数据封装和抽取BeanUtils

BeanUtils工具类可以把一个给定的数据源中的数据,一次性的拷贝到Bean对象属性中赋值. BeanUtils可以一次性给Bean中的属性都赋上需要的值.

BeanUtils工具类的使用步骤: 第一步:要先导入实现功能所需jar包.

commons-beanutils-1.8.0.jar
commons-logging-1.1.1.jar

第二步:使用populate(); 一次性注入属性值

EL表达式在输出Bean的属性值时,调用读方法,就是getXxx() 或 isXxx()方法 给Bean的属性赋值操作时,调用写方法,就是setXxxx();

public class WebUtils {
    /**
     * 编写一个方法去将所有参数都一次性注入到JavaBean属性中 <br/>
     */
    public static <T> T copyParamToBean(T bean , Map value){
        try {
            /**
             * populate() 是把指定数据源中的值一次性注入到Bean的属性中 <br>
             *     第一个参数是要赋值的Bean对象 <br>
             *     第二个参数是数据源 <br>
             */
            BeanUtils.populate(bean, value);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bean;
    }
}