尚硅谷书城项目第三阶段——用户注册和登陆代码优化
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 ©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>
<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;
}
}