登录
需求分析:
1)页面原型展示
2)登录页面展示(http://localhost:8080/backend/page/login/login.html)
3)查看登录请求信息:
输入账号密码,点击登录,发出请求,并且以json的形式将账号密码提交到服务端在页面点击F12,如图:
后台请求:controler->service->mapper-db
4)数据模型(employee表)
5)页面逻辑(主要是请求和返回数据的逻辑,其他页面小的效果不作分析)
validate:
①,校验用户名密码
②,校验通过之后,请求到loginApi,其实(loginApi)是封装到了一个js文件中(按住Ctrl左键可以关联过去),通过Ajax向后端发送请求。并且将数据(就是这个loginForm里放的用户名和密码)带过来。
③,得到的res,返回的数据(约定好1表示成功)
④,成功之后,将数据转为json保存到浏览器中,localStorage.setItem(‘userInfo’,JSON.stringify(res.data));
⑤,做页面跳转:window.location.href= ‘/backend/index.html’;
⑥登录失败提示的信息
this.$message.error(res.msg)
this.loading = false
6)后台代码开发
【返回结果类】
此类是一个通用结果类,服务端响应的所有结果最终都会包装成此种类型返回到前端页
/**
* 此类是一个通用结果类,服务端响应的所有结果最终都会包装成此种类型返回到前端页
* @param <T>
*/
@Data
public class R<T> {
private Integer code; //编码:1成功,0和其它数字为失败
private String msg; //错误信息
private T data; //数据
private Map map = new HashMap(); //动态数据
public static <T> R<T> success(T object) {
R<T> r = new R<T>();
r.data = object;
r.code = 1;
return r;
}
public static <T> R<T> error(String msg) {
R r = new R();
r.msg = msg;
r.code = 0;
return r;
}
public R<T> add(String key, Object value) {
this.map.put(key, value);
return this;
}
}
①实体类(略)
②mapper
@Mapper //mybatisplus
public interface EmployeeMapper extends BaseMapper<Employee> {
}
③service
@Service //引入两个泛型(mapper和实体)
public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper, Employee> implements EmployeeService{
}
④controller
@Slf4j
@RestController
@RequestMapping("/employee")
public class EmployeeController {
@Autowired
private EmployeeService employeeService;
/**
* 员工登录
* @param request
* @param employee
* @return
*/
@PostMapping("/login")
public R<Employee> login(HttpServletRequest request, @RequestBody Employee employee){
//1,将页面提交的密码进行MD5加密
String password = employee.getPassword();
password = DigestUtils.md5DigestAsHex(password.getBytes());
// String aa = "123456";
// aa = DigestUtils.md5DigestAsHex(aa.getBytes());
// System.out.println("密文:" + aa);
//2,根据用户名查数据库
LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Employee::getUsername,employee.getUsername());
//数据库已经对username字段做了一个唯一的约束,所以可以调用getOne()查出唯一的数据
Employee emp = employeeService.getOne(queryWrapper);
//3,如果没有查到则返回登录失败结果
if(emp == null){
return R.error("登陆失败aaaaaaaaa");
}
//4,查到结果的话,密码比对不一致也返回失败结果
if(!emp.getPassword().equals(password)){
return R.error("登陆失败aaabbbbbbbbbbbbbbbbbbbbba");
}
//5,查看员工状态是否可用(0是禁用)
if(emp.getStatus() == 0){
return R.error("账号已禁用");
}
//6,登录成功,将用户状态存入session中
HttpSession session = request.getSession();
session.setAttribute("employee",emp);
return R.success(emp);
}
}
登出
1)需求分析
2)代码开发
3)前端,顺便移除用户信息
【用户】
完善登录功能
过滤器及其逻辑:
@Slf4j
@WebFilter(filterName = "LoginCheckFilter" ,urlPatterns = "/*")
public class LoginCheckFilter implements Filter {
//路径匹配器,支持通配符
public static final AntPathMatcher ANT_PATH_MATCHER = new AntPathMatcher();
/**
* 过滤的方法
* @param servletRequest
* @param servletResponse
* @param filterChain
* @throws IOException
* @throws ServletException
*/
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
//{}占位符
log.info("拦截到请求:{}",request.getRequestURI());
//1,获取本次请求的uri
String requestURI = request.getRequestURI();
//定义不需要处理的请求路径
String [] urls = new String[]{
"/employee/login",
"/employee/logout",
"/backend/**",//静态资源放行
"/front/**",//静态资源放行
};
//2,判断本次请求是否需要处理,也就是说用匹配器ANT_PATH_MATCHER来判断本次请求是否是以上数组的某一个
boolean check = check(urls,requestURI);
//3,如果不需要处理,则直接放行
if(check){
log.info("本次请求{}不需要处理",request.getRequestURI());
//放行
filterChain.doFilter(request,response);
return;
}
//4,判断登录状态,如果已登录,直接放行
Employee employee = (Employee) request.getSession().getAttribute("employee");
if(employee != null){
log.info("用户已登录,账号:{}",employee.getUsername());
filterChain.doFilter(request,response);
return;
}
//5,走到这里说明请求未放行 或 未登录
//通过输出流的方式将结果写到页面(写的是json数据)
//另外返回的提示中要与前端契合
log.info("用户未登录");
PrintWriter out = response.getWriter();
out.write(JSON.toJSONString(R.error("NOTLOGIN")));
return;
}
/**
* 检查本次请求是否需要放行
* @param urls
* @param requestURI
* @return
*/
private boolean check(String [] urls,String requestURI) {
for (String url : urls) {
//匹配match()
boolean match = ANT_PATH_MATCHER.match(url,requestURI);
//匹配上了。
if(match){
return true;
}
}
return false;
}
}
前端的拦截器(写在了request.js里),拦截服务端给页面的响应,并判断返回值