【JavaWeb项目】一个众筹网站的开发(五)后台用户登录功能
用户模块
1)注册
- 表单校验,使用校验插件
- 用户密码需要加密存储
- 注册成功后来到管理控制台,将用户放在session中,防止以后获取
- 以后用户经常获取用户id,使用mabatis主键自增策略,保存用户的时候,将自增的主键放在TUser的id属性上
- 实际问题:用户的id不是自增
用户分开存储,经常查询需要根据关键字来直接锁定数据库
用户表合并,导致有问题
采取的策略;关键表的主键,一定不是自增的。美团:用户手机号等位id
2)登陆
- 输入登陆内容
- 来到controlller进行登陆
- 调用Service查询当前用户&密码是否存在
- 登陆成功来到控制台页面
- 登陆失败来到登陆页面
我们现在设置的是通过转发来到页面,此时刷新就是重复提交。我们要在关键位置解决表单重复提交问题。注册&登陆页面可以不用管,但是某些插入或者更新数据库转发到页面,数据CUD没有任何校验规则(直接就成功),一定要解决表单重复提交。表单重复提交解决办法:令牌机制;重定向(解决重复提交的根本方法)
登陆逻辑
login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="description" content=""> <meta name="keys" content=""> <meta name="author" content=""> <%@include file="/WEB-INF/includes/css-file.jsp" %> </head> <body> <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation"> <div class="container"> <div class="navbar-header"> <div><a class="navbar-brand" href="${ctp}/index.jsp" style="font-size:32px;">尚筹网-创意产品众筹平台</a></div> </div> </div> </nav> <div class="container"> <form class="form-signin" role="form" action="${ctp}/permission/user/login" method="post"> <h2 class="form-signin-heading"><i class="glyphicon glyphicon-log-in"></i> 用户登录</h2> <div class="form-group has-success has-feedback"> <input type="text" class="form-control" name="loginacct" id="loginacct_input" placeholder="请输入登录账号" value="${errorUser.loginacct }" autofocus> <span class="glyphicon glyphicon-user form-control-feedback"></span> <span style="color: red;">${msg }</span> <!-- 取出一次就将session中的这个属性移除 --> <!-- var="msg" 指定要从域中移除的key scope="" 指定从哪个域中移除,不写默认会从所有域中移除,包括session --> <c:remove var="msg"/> <c:remove var="errorUser"/> </div> <div class="form-group has-success has-feedback"> <input type="text" class="form-control" name="userpswd" id="userpswd_input" placeholder="请输入登录密码" style="margin-top:10px;"> <span class="glyphicon glyphicon-lock form-control-feedback"></span> </div> <div class="form-group has-success has-feedback"> <select class="form-control" > <option value="member">会员</option> <option value="manager">管理</option> </select> </div> <div class="checkbox"> <label> <input type="checkbox" value="remember-me"> 记住我 </label> <br> <label> 忘记密码 </label> <label style="float:right"> <a href="${ctp}/reg.jsp">我要注册</a> </label> </div> <a class="btn btn-lg btn-success btn-block" onclick="dologin()" > 登录</a> </form> </div> <script src="jquery/jquery-2.1.1.min.js"></script> <script src="bootstrap/js/bootstrap.min.js"></script> <script> function dologin() { var type = $(":selected").val(); if ( type == "manager" ) { // 管理员登陆 // 当前页面只有一个表单,直接选第一个表单即可 $("form:first").submit(); //window.location.href = "main.html"; } else { // 超链接跳转到指定的地址 window.location.href = "${ctp }/index.jsp"; } } </script> </body> </html>
<%@include file="/WEB-INF/includes/css-file.jsp" %>
提交表单转向
action="${ctp}/permission/user/login"
出错回显
value"${errorUser.loginacct }
显示出错信息<span style="color: red;">${msg }</span> <!-- 取出一次就将session中的这个属性移除 --> <!-- var="msg" 指定要从域中移除的key scope="" 指定从哪个域中移除,不写默认会从所有域中移除,包括session --> <c:remove var="msg"/> <c:remove var="errorUser"/>
控制器定义登陆的超链接
package com.atguigu.scw.manager.controller.permission; import javax.servlet.http.HttpSession; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import com.atguigu.scw.manager.bean.TUser; import com.atguigu.scw.manager.constant.Constants; import com.atguigu.scw.manager.service.UserService; //处理所有/permission/user下的请求 @RequestMapping("/permission/user") @Controller public class UserController { private final String MANAGER_MAIN = "manager/main"; @Autowired UserService userService; @RequestMapping("/login") public String login(TUser user, HttpSession session) { // 登陆后返回的用户要放在session中,用TUser TUser login = userService.login(user); if (login == null) { // 登陆失败 session.setAttribute("errorUser", user); session.setAttribute("msg", "登陆失败"); return "redirect:/login.jsp"; } // 登陆成功 // 1.将用户放在session中 session.setAttribute(Constants.LOGIN_USER, login); return MANAGER_MAIN; } // /permission/user/reg @RequestMapping("/reg") public String reg(TUser user, Model model, HttpSession session) { // ... } }
需要login方法
接口
package com.atguigu.scw.manager.service; import com.atguigu.scw.manager.bean.TUser; public interface UserService { public boolean register(TUser user); public TUser login(TUser user); }
实现类
package com.atguigu.scw.manager.service.impl; import java.util.Date; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.atguigu.project.MD5Util; import com.atguigu.project.MyStringUtils; import com.atguigu.scw.manager.bean.TUser; import com.atguigu.scw.manager.bean.TUserExample; import com.atguigu.scw.manager.bean.TUserExample.Criteria; import com.atguigu.scw.manager.dao.TUserMapper; import com.atguigu.scw.manager.service.UserService; @Service public class UserServiceImpl implements UserService { @Autowired TUserMapper userMapper; public boolean register(TUser user) { // ... } public TUser login(TUser user) { // 1.拿到用户名和密码 // 2.去数据库查询是否存在 TUserExample example = new TUserExample(); Criteria criteria = example.createCriteria(); // 设置查询条件 criteria.andLoginacctEqualTo(user.getLoginacct()); criteria.andUserpswdEqualTo(MD5Util.digest(user.getUserpswd())); // 因为失误等原因,可能会查询到多个用户 List<TUser> list = null; try { list = userMapper.selectByExample(example); } catch (Exception e) { System.out.println(e); } // ==1的时候查询成功 return list.size() == 1 ? list.get(0) : null; } }
spring默认是JDK动态代理,对实现类对象做增强得到的增强类与实现类是兄弟关系,所以不能用实现类接收增强类对象,只能用接口接收。
ssm项目中 @Autowired 注解在接口类上却是注入的是他的实现类
自动装配实现了接口的的实例,只有UserServiceImpl实现了接口,所以就会注入UserServiceImpl