书城项目-第三阶段:修改所有html页面为jsp页面、书城项目-第三阶段:抽取所有jsp页面中公共内容、书城项目-动态的base标签值、书城项目-表单提交失败的错误回显、书城项目-代码优化:合并LoginServlet和RegistServlet程序为UserServlet程序、书城项目-代码优化二:使用反射优化大量else if代码、书城项目-BeanUtils工具类的使用、书城项目-书城项目第四阶段,使用EL表达式
1.第三阶段:
a)页面 jsp 动态化
1、在 html 页面顶行添加 page 指令。
2、修改文件后缀名为:.jsp
3、使用 IDEA 搜索替换.html 为.jsp(快捷键:Ctrl+Shift+R)
b)抽取页面中相同的内容
i. head 中 css、jquery、base 标签
<%--
Created by IntelliJ IDEA.
User: ZRich
Date: 2022/12/9
Time: 下午 5:17
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
String basePath = request.getScheme()
+ "://"
+ request.getServerName()
+ ":"
+ request.getServerPort()
+ request.getContextPath()
+ "/";
%>
<%--<%=basePath%>--%>
<!-- 写base便签,永远固定相对路径跳转的结果 -->
<base href="<%=basePath%>">
<link type="text/css" rel="stylesheet" href="static/css/style.css" >
<script type="text/javascript" src="static/script/jquery-3.6.1.js"></script>
ii. 每个页面的页脚
<%--
Created by IntelliJ IDEA.
User: ZRich
Date: 2022/12/9
Time: 下午 5:28
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<div id="bottom">
<span>
尚硅谷书城.Copyright ©2015
</span>
</div>
iii. 登录成功后的菜单
<%--
Created by IntelliJ IDEA.
User: ZRich
Date: 2022/12/9
Time: 下午 5:11
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<div>
<span>欢迎<span class="um_span">韩总</span>光临尚硅谷书城</span>
<a href="pages/order/order.jsp">我的订单</a>
<a href="index.jsp">注销</a>
<a href="index.jsp">返回</a>
</div>
iv. manager 模块的菜单
<%--
Created by IntelliJ IDEA.
User: ZRich
Date: 2022/12/9
Time: 下午 5:33
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<div>
<a href="book_manager.jsp">图书管理</a>
<a href="order_manager.jsp">订单管理</a>
<a href="index.jsp">返回商城</a>
</div>
c)登录,注册错误提示,及表单回显
以登录回显为示例:
Servlet 程序端需要添加回显信息到 Request 域中
package top.qaqaq.web;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import top.qaqaq.pojo.User;
import top.qaqaq.service.UserService;
import top.qaqaq.service.impl.UserServiceImpl;
import java.io.IOException;
/**
* @author RichieZhang
* @create 2022-12-07 上午 11:51
*/
public class LoginServlet extends HttpServlet {
private UserService userService = new UserServiceImpl();
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// super.doPost(req, resp);
//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 页面,需要输出回显信息
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>尚硅谷会员登录页面</title>
<%-- 静态包含 base标签,css样式,jQuery文件 --%>
<%@ include file="/pages/common/head.jsp"%>
</head>
<body>
<div id="login_header">
<img class="logo_img" alt="" src="static/img/logo.gif" >
</div>
<div class="login_banner">
<div id="l_content">
<span class="login_word">欢迎登录</span>
</div>
<div id="content">
<div class="login_form">
<div class="login_box">
<div class="tit">
<h1>尚硅谷会员</h1>
<a href="pages/user/regist.jsp">立即注册</a>
</div>
<div class="msg_cont">
<b></b>
<span class="errorMsg">
<%=request.getAttribute("msg")==null?"请输入用户名和密码":request.getAttribute("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="<%=request.getAttribute("username")==null?"":request.getAttribute("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>
</div>
</div>
</div>
</div>
<%-- 静态包含页脚内容 --%>
<%@include file="/pages/common/footer.jsp"%>
</body>
</html>
d)BaseServlet 的抽取
在实际的项目开发中,一个模块,一般只使用一个 Servlet 程序。
代码优化一:代码优化:合并 LoginServlet 和 RegistServlet 程序为 UserServlet 程序
UserServlet 程序:
package top.qaqaq.web;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import top.qaqaq.pojo.User;
import top.qaqaq.service.UserService;
import top.qaqaq.service.impl.UserServiceImpl;
import top.qaqaq.utils.WebUtils;
import java.io.IOException;
/**
* @author RichieZhang
* @create 2022-12-10 上午 11:26
*/
public class UserServlet extends BaseServlet {
private UserService userService = new UserServiceImpl();
/**
* 处理登录的功能
* @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 {
// 登录 成功
// 跳到成功页面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 {
// 1、获取请求的参数
String username = req.getParameter("username");
String password = req.getParameter("password");
String email = req.getParameter("email");
String code = req.getParameter("code");
// User user = new User();
//测试代码
// Map<String, String[]> parameterMap = req.getParameterMap();
// for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
// System.out.println(entry.getKey() + "=" + Arrays.asList(entry.getValue()));
// }
// WebUtils.copyParamToBean(req.getParameterMap(),user);
User user = WebUtils.copyParamToBean(req.getParameterMap(), new User());
// 2、检查 验证码是否正确 === 写死,要求验证码为:abcde
if ("abcde".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);
}
}
}
还要给 login.jsp 添加隐藏域和修改请求地址
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>尚硅谷会员登录页面</title>
<%-- 静态包含 base标签,css样式,jQuery文件 --%>
<%@ include file="/pages/common/head.jsp"%>
</head>
<body>
<div id="login_header">
<img class="logo_img" alt="" src="static/img/logo.gif" >
</div>
<div class="login_banner">
<div id="l_content">
<span class="login_word">欢迎登录</span>
</div>
<div id="content">
<div class="login_form">
<div class="login_box">
<div class="tit">
<h1>尚硅谷会员</h1>
<a href="pages/user/regist.jsp">立即注册</a>
</div>
<div class="msg_cont">
<b></b>
<span class="errorMsg">
<%=request.getAttribute("msg")==null?"请输入用户名和密码":request.getAttribute("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="<%=request.getAttribute("username")==null?"":request.getAttribute("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>
</div>
</div>
</div>
</div>
<%-- 静态包含页脚内容 --%>
<%@include file="/pages/common/footer.jsp"%>
</body>
</html>
给 regist.jsp 页面添加隐藏域 action,和修改请求地址
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>尚硅谷会员注册页面</title>
<%-- 静态包含 base标签,css样式,jQuery文件 --%>
<%@ include file="/pages/common/head.jsp"%>
<script type="text/javascript">
// 页面加载完成之后
$(function () {
// 给注册绑定单击事件
$("#sub_btn").click(function () {
// 验证用户名:必须由字母,数字下划线组成,并且长度为 5 到 12 位
//1 获取用户名输入框里的内容
var usernameText = $("#username").val();
//2 创建正则表达式对象
var usernamePatt = /^\w{5,12}$/;
//3 使用test方法验证
if (!usernamePatt.test(usernameText)){
//4 提示用户结果
$("span.errorMsg").text("用户名不合法!");
return false;
}
// 验证密码:必须由字母,数字下划线组成,并且长度为 5 到 12 位
//1 获取用户名输入框里的内容
var passwordText = $("#password").val();
//2 创建正则表达式对象
var passwordPatt = /^\w{5,12}$/;
//3 使用test方法验证
if (!passwordPatt.test(passwordText)){
//4 提示用户结果
$("span.errorMsg").text("密码不合法!");
return false;
}
// 验证确认密码:和密码相同
//1 获取确认密码内容
var repwdText = $("#repwd").val();
//2 和密码相比较
if (repwdText != passwordText){
//3 提示用户
$("span.errorMsg").text("确认密码和密码不一致!");
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();
// 去掉验证码前后空格
// alert("去空格前:[" + codeText + "]");
codeText = $.trim(codeText);
// alert("去空格前:[" + codeText + "]");
if (codeText == null || codeText == ""){
//4 提示用户
$("span.errorMsg").text("验证码不能为空!");
return false;
}
$("span.errorMsg").text("");
});
});
</script>
<style type="text/css">
.login_form{
height:420px;
margin-top: 25px;
}
</style>
</head>
<body>
<div id="login_header">
<img class="logo_img" alt="" src="static/img/logo.gif" >
</div>
<div class="login_banner">
<div id="l_content">
<span class="login_word">欢迎注册</span>
</div>
<div id="content">
<div class="login_form">
<div class="login_box">
<div class="tit">
<h1>注册尚硅谷会员</h1>
<span class="errorMsg">
<%=request.getAttribute("msg")==null?"":request.getAttribute("msg")%>
</span>
</div>
<div class="form">
<form action="userServlet" method="post">
<input type="hidden" name="action" value="regist">
<label>用户名称:</label>
<input class="itxt" type="text" placeholder="请输入用户名"
value="<%=request.getAttribute("username")==null?"":request.getAttribute("username")%>"
autocomplete="off" tabindex="1" name="username" id="username" />
<br />
<br />
<label>用户密码:</label>
<input class="itxt" type="password" placeholder="请输入密码"
autocomplete="off" tabindex="1" name="password" id="password" />
<br />
<br />
<label>确认密码:</label>
<input class="itxt" type="password" placeholder="确认密码"
autocomplete="off" tabindex="1" name="repwd" id="repwd" />
<br />
<br />
<label>电子邮件:</label>
<input class="itxt" type="text" placeholder="请输入邮箱地址"
value="<%=request.getAttribute("email")==null?"":request.getAttribute("email")%>"
autocomplete="off" tabindex="1" name="email" id="email" />
<br />
<br />
<label>验证码:</label>
<input class="itxt" type="text" name="code" style="width: 150px;" id="code"/>
<img alt="" src="static/img/code.bmp" style="float: right; margin-right: 40px">
<br />
<br />
<input type="submit" value="注册" id="sub_btn" />
</form>
</div>
</div>
</div>
</div>
</div>
<%-- 静态包含页脚内容 --%>
<%@include file="/pages/common/footer.jsp"%>
</body>
</html>
优化代码二:使用反射优化大量 else if 代码:
package top.qaqaq.web;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @author RichieZhang
* @create 2022-12-10 下午 12:28
*/
public abstract class BaseServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// super.doPost(req, resp);
String action = req.getParameter("action");
// System.out.println(acction);
//方法一:写一个方法判断一次
// if ("login".equals(action)) {
// //System.out.println("处理登录的需求");
// login(req,resp);
// } else if ("regist".equals(action)) {
// //System.out.println("处理注册的需求");
// regist(req,resp);
// }
//方法二:通过反射动态获取
try {
// 通过action业务鉴别字符串,获取相应的业务 方法反射对象
Method method = this.getClass().getDeclaredMethod(action, HttpServletRequest.class, HttpServletResponse.class);
// System.out.println(method);
// 调用目标业务 方法
method.invoke(this,req,resp);
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
代码优化三:抽取 BaseServlet 程序。
BaseServlet 程序代码:
package top.qaqaq.web;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @author RichieZhang
* @create 2022-12-10 下午 12:28
*/
public abstract class BaseServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// super.doPost(req, resp);
String action = req.getParameter("action");
// System.out.println(acction);
//方法一:写一个方法判断一次
// if ("login".equals(action)) {
// //System.out.println("处理登录的需求");
// login(req,resp);
// } else if ("regist".equals(action)) {
// //System.out.println("处理注册的需求");
// regist(req,resp);
// }
//方法二:通过反射动态获取
try {
// 通过action业务鉴别字符串,获取相应的业务 方法反射对象
Method method = this.getClass().getDeclaredMethod(action, HttpServletRequest.class, HttpServletResponse.class);
// System.out.println(method);
// 调用目标业务 方法
method.invoke(this,req,resp);
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
修改 UserServlet 程序继承 BaseServlet 程序。
public class UserServlet extends BaseServlet {
private UserService userService = new UserServiceImpl();
e)数据的封装和抽取 BeanUtils 的使用
BeanUtils 工具类,它可以一次性的把所有请求的参数注入到 JavaBean 中。
BeanUtils 工具类,经常用于把 Map 中的值注入到 JavaBean 中,或者是对象属性值的拷贝操作。
BeanUtils 它不是 Jdk 的类。而是第三方的工具类。所以需要导包。
1、导入需要的 jar 包:
commons-beanutils-1.9.4.jar
commons-logging-1.2.jar
commons-collections-3.2.2.jar
2、编写 WebUtils 工具类使用:
WebUtils 工具类:
package top.qaqaq.utils;
import org.apache.commons.beanutils.BeanUtils;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
/**
* @author RichieZhang
* @create 2022-12-10 下午 2:11
*/
public class WebUtils {
/**
* 把Map中的值注入到对应的JavaBean属性中。
* @param value
* @param bean
* 如果形参写成HttpServletRequest DAO层和Service层没有这个API 且web层耦合度高,代码不优雅
* DAO层
* Service层
* Web层
*/
public static <T> T copyParamToBean(Map value, T bean) {
try {
System.out.println("注入之前:" + bean);
BeanUtils.populate(bean,value);
System.out.println("注入之后:" + bean);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return bean;
}
}
书城-第四阶段。使用 EL 表达式修改表单回显
以登录为示例:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>尚硅谷会员登录页面</title>
<%-- 静态包含 base标签,css样式,jQuery文件 --%>
<%@ include file="/pages/common/head.jsp"%>
</head>
<body>
<div id="login_header">
<img class="logo_img" alt="" src="static/img/logo.gif" >
</div>
<div class="login_banner">
<div id="l_content">
<span class="login_word">欢迎登录</span>
</div>
<div id="content">
<div class="login_form">
<div class="login_box">
<div class="tit">
<h1>尚硅谷会员</h1>
<a href="pages/user/regist.jsp">立即注册</a>
</div>
<div class="msg_cont">
<b></b>
<span class="errorMsg">
<%-- <%=request.getAttribute("msg")==null?"请输入用户名和密码":request.getAttribute("msg")%>--%>
${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="<%=request.getAttribute("username")==null?"":request.getAttribute("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>
</div>
</div>
</div>
</div>
<%-- 静态包含页脚内容 --%>
<%@include file="/pages/common/footer.jsp"%>
</body>
</html>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
version="5.0">
<!-- <servlet>-->
<!-- <servlet-name>RegistServlet</servlet-name>-->
<!-- <servlet-class>top.qaqaq.web.RegistServlet</servlet-class>-->
<!-- </servlet>-->
<!-- <servlet-mapping>-->
<!-- <servlet-name>RegistServlet</servlet-name>-->
<!-- <url-pattern>/registServlet</url-pattern>-->
<!-- </servlet-mapping>-->
<!-- <servlet>-->
<!-- <servlet-name>LoginServlet</servlet-name>-->
<!-- <servlet-class>top.qaqaq.web.LoginServlet</servlet-class>-->
<!-- </servlet>-->
<!-- <servlet-mapping>-->
<!-- <servlet-name>LoginServlet</servlet-name>-->
<!-- <url-pattern>/loginServlet</url-pattern>-->
<!-- </servlet-mapping>-->
<servlet>
<servlet-name>UserServlet</servlet-name>
<servlet-class>top.qaqaq.web.UserServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UserServlet</servlet-name>
<url-pattern>/userServlet</url-pattern>
</servlet-mapping>
</web-app>