JAVA项目实战瑞吉外卖—day1
技术选型
数据库环境搭建
导入前端页面资源
因为创建的是maven初始化项目,没有自带的springboot文件目录,前端页面有些访问被禁止,静态资源的访问方法有两种
后端开发
创建SpringMVC静态资源页面访问拦截器
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @Slf4j @Configuration public class WebMvcConfig extends WebMvcConfigurationSupport {
@Override protected void addResourceHandlers(ResourceHandlerRegistry registry) { log.info("开始进行静态资源映射..."); registry.addResourceHandler("/backend/**").addResourceLocations("classpath:/backend/"); registry.addResourceHandler("/front/**").addResourceLocations("classpath:/front/"); } }
|
在resource目录下创建static目录
将静态资源文件放进去,因为springboot框架自动开放static资源访问
编写springboot通用模板
MVC三层架构
编写通用返回类
返回一个通用结果类,服务端响应的所有结果最终都是包装成这种类型返回给前端页面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| @Data public class R<T> {
private Integer code;
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; }
}
|
登录接口编写
个人认为将业务方法写在service层中更好,controller注解调用更为简便
写完项目会进行优化——–TODO
使用MD5加密方式校验密码
数据库中不能存在明文密码在,使用MD5加密,最好添加盐值混淆密码
1 2 3
| String password = employee.getPassword(); password = DigestUtils.md5DigestAsHex(password.getBytes());
|
1 2 3 4 5 6 7
|
private static final String salt = "passwordAc"; String password = employee.getPassword();
String newPassword = DigestUtils.md5DigestAsHex((salt + password).getBytes());
|
这样在数据库中混淆密码进行安全保护
判断用户是否正常 能否进行登录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(Employee::getUsername,employee.getUsername()); Employee emp = employeeService.getOne(queryWrapper);
if (emp == null){ return R.error("用户不存在"); }
if (!emp.getPassword().equals(password)){ return R.error("密码错误"); }
if (emp.getStatus() == 0){ return R.error("该员工以禁用"); }
request.getSession().setAttribute("employee",emp.getId());
return R.success(emp);
|
登出接口编写
根据前端页面返回的请求是POST,所以编写接口也应该未POST
1.移除用户登录态
2.跳转到登录页面
1 2 3 4 5 6 7 8 9 10 11
|
@PostMapping("/logout") public R<String> logout(HttpServletRequest request){ request.getSession().removeAttribute("employee"); return R.success("退出成功!"); }
|
完善登录接口
设置登录(SpringMVC)拦截器或者javaweb过滤器
这里使用的是过滤器记得在启动类入口添加@ServletComponentScan注解
1 2 3 4 5 6 7 8 9
| @Slf4j @SpringBootApplication @ServletComponentScan public class ReggieApplication { public static void main(String[] args) { SpringApplication.run(ReggieApplication.class,args); log.info("项目启动成功......"); } }
|
未登录无法查看管理窗口页面,需要跳转到登录页面
后端过滤器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| @WebFilter(filterName = "LoginCheckFilter", urlPatterns = "/*") @Slf4j public class LoginCheckFilter implements Filter {
public static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();
@Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse;
String requestURI = request.getRequestURI();
String[] urls = new String[]{ "/employee/login", "/employee/logout", "/backend/**", "/front/**" };
boolean check = check(urls, requestURI);
if (check) { filterChain.doFilter(request, response); return; }
if (request.getSession().getAttribute("employee")!=null){ filterChain.doFilter(request, response); return; } response.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN"))); return;
}
public boolean check(String[] urls, String requestURI) { for (String url : urls) { boolean match = PATH_MATCHER.match(url, requestURI); if (match) { return true; } } return false; } }
|
这里通过后端进行页面路径访问判断,从而得出哪些路径需要进行拦截,在根据前端的拦截器实现拦截页面跳转到登录界面,根据前后端传输数据”NOTLOGIN”来响应页面跳转
前端拦截器
1 2 3 4 5 6 7 8 9 10
| service.interceptors.response.use(res => { if (res.data.code === 0 && res.data.msg === 'NOTLOGIN') { console.log('---/backend/page/login/login.html---') localStorage.removeItem('userInfo') window.top.location.href = '/backend/page/login/login.html' } else { return res.data } },
|
Question
这里的路径匹配器我理解不了
/**是允许访问目录及子目录下的所有文件,意思为放行,放行还怎么拦截
1 2
| public static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();
|