登录逻辑
当我们无论登录成功与否,都可以访问index.html界面,因此可以使用拦截器或者过滤器完善登录请求。
1过滤器实现
1.1创建拦截器类,实现Filter接口
urlPatterns表示拦截什么请求,filterName表示过滤器的名称
package com.wzt.filter;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebFilter(filterName = "LoginCheckFilter",urlPatterns = "/*")
@Slf4j
public class LoginCheckFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
}
}
1.2创建过滤的逻辑
package com.wzt.filter;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebFilter(filterName = "LoginCheckFilter",urlPatterns = "/*")
@Slf4j
public class LoginCheckFilter implements Filter {
@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());
filterChain.doFilter(request, response);
}
}
1.3将创建的过滤器注册到springboot中
@SpringBootApplication
@Slf4j
@ServletComponentScan
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class,args);
log.info("服务启动成功");
}
}
1.4具体业务逻辑
在使用拦截器或者过滤器的时候,需要判断出要对哪些路径或者资源完成过滤或者拦截,比如说登录界面和退出界面以及静态资源就不需要被拦截。
1)获取当前请求的路径
2)判断当前路径是否是不需要拦截的路径
3)如果不是当前拦截的路径,则放行
4)如果是拦截的路径,但是当前的session存在,也放行
5)如果当前的session不存在的话,需要向前端返回相应的数据,让前端完成页面的跳转。
1.5具体实现代码
//如果前端的msg为中文,则需要设置相应的编码方式。查看前端编码方式为document.charset
@WebFilter(filterName = "LoginCheckFilter",urlPatterns = "/*")
@Slf4j
public class LoginCheckFilter implements Filter {
private AntPathMatcher pathMatcher=new AntPathMatcher();
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//使用过滤链放行请求
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
String[] paths={
"/employee/login",
"/employee/logout",
"/backend/**",
"/front/**"
};
String uri = request.getRequestURI();
log.info("当前路径为{}",uri);
//如果存在,则不用拦截
if (check(uri,paths)){
log.info("不需要拦截");
filterChain.doFilter(request, response);
return;
}
//如果不存在,session存在,不需要拦截,放行
if(!check(uri,paths)){
if(request.getSession().getAttribute("employee")!=null){
filterChain.doFilter(request, response);
return;
}
}
//向客户端写Json数据
log.info("用户未登录");
response.setCharacterEncoding("UTF-8");
response.getWriter().write(JSON.toJSONString(R.error("未登录")));
return;
}
public boolean check(String uri,String []paths){
for (String path : paths) {
if(pathMatcher.match(path,uri)){
return true;
}
}
return false;
}
}
2拦截器实现
2.1编写LoginInterceptor实现HandlerInterceptor接口
package com.wzt.interceptor;
import com.alibaba.fastjson.JSON;
import com.wzt.common.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 使用spring mvc的拦截器实现登录功能
*/
@Component
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Object employee = request.getSession().getAttribute("employee");
if (employee== null) {
// response.setContentType("application/json");
String json=JSON.toJSONString(R.error("NOTLOGIN"));
// response.sendRedirect("/backend/page/login/login.html");
response.getWriter().write(json);
return false;
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}
2.2配置WebMvcConfig类
这里使用实现WebMvcConfigurer接口而非扫描静态资源使其生效继承的WebMvcConfigurationSupport类。
WebMvcConfigurer接口和WebMvcConfigurationSupport类的区别见
【https://blog.csdn.net/asddasddeedd/article/details/127517429】
实现代码
package com.wzt.config;
import com.wzt.interceptor.LoginInterceptor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @author jason
*/
@Slf4j
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
LoginInterceptor loginInterceptor;
/**
* 设置静态资源映射
*
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
log.info("开始进行静态资源映射...");
registry.addResourceHandler("/backend/**").addResourceLocations("classpath:/backend/");
registry.addResourceHandler("/front/**").addResourceLocations("classpath:/front/");
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginInterceptor).addPathPatterns("/**").excludePathPatterns("/employee/login").excludePathPatterns("/employee/logout").excludePathPatterns("/backend/**").excludePathPatterns("/front/**");
}
}
2.3过滤器和拦截器的区别
- 过滤器依赖于Servlet,使用回调函数实现;拦截器依赖于spring,使用反射实现。
- 时机不同,过滤器在进入容器后,进入servlet中执行,而拦截器在servlet->controller中执行
- 使用场景不同,过滤器只能用于web中,而拦截器不但可以在web中还能在Swing或者Application中。