servlet簡介
過濾器,依靠servlet技術(shù)。
Java Servlet 是運(yùn)行在 Web 服務(wù)器或應(yīng)用服務(wù)器上的程序馍迄,它是作為來自 Web 瀏覽器或其他 HTTP 客戶端的請求和 HTTP 服務(wù)器上的數(shù)據(jù)庫或應(yīng)用程序之間的中間層兴泥。
servlet文檔:
https://www.runoob.com/servlet/servlet-intro.html
servlet 和tomcat 是什么關(guān)系主卫?
過濾器簡介
過濾器Filter,是Servlet的的一個實用技術(shù)了鹃愤〈亟粒可通過過濾器,對請求進(jìn)行攔截软吐,比如讀取session判斷用戶是否登錄瘩将、判斷訪問的請求URL是否有訪問權(quán)限(黑白名單)等。主要還是可對請求進(jìn)行預(yù)處理凹耙。
1.過濾器和攔截器觸發(fā)時機(jī)不一樣姿现,過濾器是在請求進(jìn)入容器后,但請求進(jìn)入servlet之前進(jìn)行預(yù)處理的使兔。請求結(jié)束返回也是建钥,是在servlet處理完后,返回給前端之前虐沥。
2.攔截器可以獲取IOC容器中的各個bean熊经,而過濾器就不行,因為攔截器是spring提供并管理的欲险,spring的功能可以被攔截器使用镐依,在攔截器里注入一個service,可以調(diào)用業(yè)務(wù)邏輯天试。而過濾器是JavaEE標(biāo)準(zhǔn)槐壳,只需依賴servlet api ,不需要依賴spring喜每。
1 通過@WebFilter來定義filter,
自定義 AllUrlFilter
@Slf4j
@WebFilter(filterName = "allurlfilter", urlPatterns = {"/*"})
public class AllUrlFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
log.info("all url filter -->" + filterConfig.toString());
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
log.info("all url filter do filter");
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
System.out.println(request.getHeader("token"));
//往下文傳遞
filterChain.doFilter(request, response);
}
@Override
public void destroy() {
log.info("all url filter do destroy");
}
}
在springboot 啟動器類上加上注解 @ServletComponentScan
@SpringBootApplication
@ServletComponentScan
public class StudySpringbootApplication {
public static void main(String[] args) {
SpringApplication.run(StudySpringbootApplication.class, args);
}
}
總結(jié):
Filter使用白名單過濾Url的方式务唐,配置需要攔截的Url,如果想設(shè)置不過濾某些Url需要在doFilter方法中指定带兜。
通過@WebFilter的方式定義Filter枫笛,默認(rèn)使用Filter的類名設(shè)置優(yōu)先級。使用FilterRegistrationBean可以指定優(yōu)先級
2 filter 中的異常處理
2.1 制造錯誤
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
log.info("all url filter do filter");
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
System.out.println(request.getHeader("token"));
try {
int i = 0 / 0;
} catch (Exception e) {
//錯誤封裝在 request 中
request.setAttribute("errormsg", e.getMessage());
//
request.getRequestDispatcher("/500").forward(request, response);
}
filterChain.doFilter(request, response);
}
盡量使用request.getRequestDispatcher("/500").forward(req, resp);此方式只會在服務(wù)器內(nèi)部轉(zhuǎn)發(fā)客戶端地址不會發(fā)生任何改變刚照;如果使用response.sendRedirect("/500");請求轉(zhuǎn)發(fā)刑巧,客戶端地址會發(fā)生改變
2.2 添加/500 url
@GetMapping("/500")
public Response excep401(HttpServletRequest request) throws CustomException {
System.out.println(request.getAttribute("errormsg"));
throw new CustomException();
}
方法2 : 通過FilterRegistrationBean來定義 多個filter
所有的filter 去掉 @WebFilter
3.1 新建HelloFilter
@Slf4j
//@WebFilter(filterName = "helloFilter" , urlPatterns = {"/hello/*"})
public class HelloFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
log.info("hello filter --> " + filterConfig.toString());
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
log.info("hello do filter");
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
log.info("hello do destroy");
}
}
3.2 新建UserFilter
@Slf4j
//@WebFilter(filterName = "userFilter", urlPatterns = {"/user/*"})
public class UserFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
log.info("user filter --> " + filterConfig.toString());
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
log.info("user do filter");
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
log.info("user do destroy");
}
}
3.3 新建 FilterConfig 配置
@Configuration
public class FilterConfig {
@Bean
public AllUrlFilter allUrlFilter(){
return new AllUrlFilter();
}
@Bean
public UserFilter userFilter(){
return new UserFilter();
}
@Bean
public HelloFilter helloFilter(){
return new HelloFilter();
}
@Bean
public FilterRegistrationBean filterRegistrationBean(AllUrlFilter allUrlFilter){
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(allUrlFilter);
registration.setName("allUrlFilter");
List<String> urlList = new ArrayList<>();
urlList.add("/*");
registration.setUrlPatterns(urlList);
registration.setOrder(1);
return registration;
}
@Bean
public FilterRegistrationBean filterRegistrationBea2(HelloFilter helloFilter){
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(helloFilter);
registration.setName("helloFilter");
List<String> urlList = new ArrayList<>();
urlList.add("/hello/*");
registration.setUrlPatterns(urlList);
registration.setOrder(2);
return registration;
}
@Bean
public FilterRegistrationBean filterRegistrationBea3(UserFilter userFilter){
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(userFilter);
registration.setName("userFilter");
List<String> urlList = new ArrayList<>();
urlList.add("/user/*");
registration.setUrlPatterns(urlList);
registration.setOrder(3);
return registration;
}
}
SpringBoot中使用Filter和Interceptor
https://juejin.cn/post/6844903869927931918
Spring Interceptor vs Filter
https://juejin.cn/post/6844903828970553358
SpringBoot圖文教程6—SpringBoot中過濾器的使用
https://juejin.cn/post/6844904072173060109