项目主要内容分析:
第一天完成了系统用户登录、退出、密码修改、全局异常、非法请求与记住我等系统基本功能。
项目的目录结构如图:
1 登录思路:
** * 1.参数校验 * 用户名 非空 * 密码 非空 * 2.根据用户名 查询用户记录 * 3.校验用户存在性 * 不存在 -->记录不存在 方法结束 * 4.用户存在 * 校验密码 * 密码错误-->密码不正确 方法结束 * 5.密码正确 * 用户登录成功 返回用户相关信息 */
各个文件逻辑
UserService->login 方法代码实现
UserDao->queryUserByUserName 方法定 义 & Sql 配置
UserController层login方法实现
.前端登录js 方法实现
其中:前端用ndex.ftl 添加对应index.js 使用layui 表单组件实现表单提交操作
layui的用法可以在官网找到layer弹层组件开发文档 - Layui
==================================================
2主页面显示用户名信息
IndexController.java main方法转发时查询登录用户信息并放置到 request域。
@Controller
public class IndexController extends
BaseController {
/**
* 后端管理主页面
* @return
*/
@RequestMapping("main")
public String main(HttpServletRequest
request){
Integer userId =
LoginUserUtil.releaseUserIdFromCookie(request);
request.setAttribute("user",userService.selectB
yPrimaryKey(userId));
return "main";
}
}
3全局异常统一处理:
控制层
方法返回的内容两种情况
1 视图:视图异常
2 Json:方法执行错误 返回错误json信息
全局异常拦截器实现
实现HandlerExceptionResolver 接口 ,处理应用程序异常信息
package com.xxxx.crm;
import com.alibaba.fastjson.JSON;
import com.xxxx.crm.base.ResultInfo;
import com.xxxx.crm.exceptions.NoLoginException;
import com.xxxx.crm.exceptions.ParamsException;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.annotation.Annotation;
import java.util.logging.Handler;
@Component
public class GlobalExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
if (ex instanceof NoLoginException) {
// 如果捕获的是未登录异常,则重定向到登录⻚⾯
ModelAndView mv = new ModelAndView("redirect:/index");
return mv;
}
//设置默认异常统一处理
ModelAndView modelAndView = new ModelAndView("error");
modelAndView.addObject("code", 500);
modelAndView.addObject("msg", "系统异常 请重试...");
//判断HandlerMethod 是否是控制器异常
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
ResponseBody responseBody = handlerMethod.getMethod().getDeclaredAnnotation(ResponseBody.class);
if (responseBody == null) {
if (ex instanceof ParamsException) {
ParamsException p = (ParamsException) ex;
modelAndView.addObject("code", p.getCode());
modelAndView.addObject("msg", p.getMsg());
}
return modelAndView;
} else {
ResultInfo resultInfo = new ResultInfo();
resultInfo.setCode(500);
resultInfo.setMsg("异常异常,请重试。。。");
if (ex instanceof ParamsException) {
ParamsException p = (ParamsException) ex;
resultInfo.setCode(p.getCode());
resultInfo.setMsg(p.getMsg());
}
response.setContentType("application/json;charset=UTF-8");
PrintWriter out=null;
try{
out=response.getWriter();
String json= JSON.toJSONString(resultInfo);
out.write(json);
}catch(IOException e){
e.printStackTrace();
}finally {
if(out!=null){
out.close();
}
}
}
}
return modelAndView;
}
}
之后再消除try-catch 代码
4. 非法请求拦截
获取cookie 解析用户id
如果用户id存在 并且
数据库存在对应用户记录 放行
否 则进行拦截 重定向到登录页面
NoLoginInterceptor
package com.xxxx.crm.exceptions;
/**
* 自定义参数异常
*/
public class NoLoginException extends RuntimeException {
private Integer code=300;
private String msg="用户未登录!";
public NoLoginException() {
super("用户未登录!");
}
public NoLoginException(String msg) {
super(msg);
this.msg = msg;
}
public NoLoginException(Integer code) {
super("用户未登录!");
this.code = code;
}
public NoLoginException(Integer code, String msg) {
super(msg);
this.code = code;
this.msg = msg;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
拦截器生效配置 mvcConfig
package com.xxxx.crm.config;
import com.xxxx.crm.intercepter.NoLoginInterceptor;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {
@Bean
public NoLoginInterceptor noLoginInterceptor(){
return new NoLoginInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(noLoginInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/CSS/*","/images/**","/js/**","/lib/**","/index","/user/login");
}
}
统一异常类引入未登录异常判断
@Override
public ModelAndView
resolveException(HttpServletRequest request,
HttpServletResponse response, Object handler,
Exception ex) {
/**
* 首先判断异常类型
* 如果异常类型为未登录异常 执行视图转发
*/
ModelAndView mv=new ModelAndView();
if(ex instanceof NoLoginException){
NoLoginException ne =(NoLoginException) ex;mv.setViewName("no_login");
mv.addObject("msg",ne.getMsg());
mv.addObject("ctx",request.getContextPath());
return mv;
}
/**
后续代码省略
*/
}
5记住我功能实现
记住我功能核心在于当用户上次登录时如果点击了记住我,下次在重 新打开浏览器时可以不用选择登录,此时可以借助拦截器+cookie来 实现,当用户在登录时,如果用户点击了记住我功能,默认设置 cookie存储时间为7天即可
如上图 红色花的圈,其实区别就在这里 设置了cookie的失效时间。
以下是index.js的详细代码:
layui.use(['form','jquery','jquery_cookie'], function () {
var form = layui.form,
layer = layui.layer,
$ = layui.jquery,
$ = layui.jquery_cookie($);
form.on('submit(login)',function (data) {
console.log(data.field)
$.ajax({
type:"post",
url:ctx+"/user/login",
data:{
userName:data.field.username,
userPwd:data.field.password
},
success:function(result){
console.log(result);
if(result.code==200){
layer.msg("登录成功", function(){
//判断用户是否记住密码
if($("#rememberMe").prop("checked")){
$.cookie("userIdStr", result.userIdStr, { expires: 7 });
$.cookie("userName", result.userName, { expires: 7 });
$.cookie("trueName", result.trueName, { expires: 7 });
}else {
$.cookie("userIdStr", result.result.userIdStr);
$.cookie("userName", result.result.userName);
$.cookie("trueName", result.result.trueName);
window.location.href = ctx + "/main";
}
})
}else{
layer.msg(result.msg,{icon:5})
}
}
})
return false;
})
});
=======================================================================
小知识点小结:
instanceof 是 Java 的一个二元操作符,类似于 ==,>,< 等操作符。
instanceof 是 Java 的保留关键字。它的作用是测试它左边的对象是否是它右边的类的实例,返回 boolean 的数据类型。
=================================================
今日bug小结:
1.方法名字 最好复制 以防写错
2 run/debug 每次运行这个的时候
mybatis-generator:generate -e
会自动增添mapper vo等文件 不要重复运行 不然又生成冗余的代码 从而报错
一般就运行starter就行了 main方法
@SpringBootApplication
@MapperScan("com.xxxx.crm.dao")
public class Starter {
public static void main(String[] args) {
SpringApplication.run(Starter.class);
}
}
3 SaleChanceService记得继承BaseService
前者的方法是由后者继承来的 后者的方法如下 是调用了
忘记写继承就错了。