1 SpringBoot過濾器
- 什么是過濾器
filter簡(jiǎn)單理解:?--->檢票員(filter)---> 景點(diǎn) - SpringBoot2.X??的過濾器
ApplicationContextHeaderFilter
OrderedCharacterEncodingFilter
OrderedFormContentFilter
OrderedRequestContextFilter
- 過濾器優(yōu)先級(jí)
Ordered.HIGHEST_PRECEDENCE Ordered.LOWEST_PRECEDENCE
低位值意味著更?的優(yōu)先級(jí) Higher values are interpreted as lower priority
?定義Filter赔嚎,避免和默認(rèn)的Filter優(yōu)先級(jí)?樣,不然會(huì)沖突 - 注冊(cè)Filter配置兩種?式
bean FilterRegistrationBean
Servlet3.0 webFileter
2 使用Servlet3.0注解開發(fā)?定義的過濾器
- 使?Servlet3.0的注解進(jìn)?配置步驟
啟動(dòng)類??增加 @ServletComponentScan裙犹,進(jìn)?掃描
新建?個(gè)Filter類尽狠,implements Filter衔憨,并實(shí)現(xiàn)對(duì)應(yīng)的接?
@WebFilter 標(biāo)記?個(gè)類為filter,被spring進(jìn)?掃描
urlPatterns:攔截規(guī)則袄膏,?持正則
控制chain.doFilter的?法的調(diào)?践图,來(lái)實(shí)現(xiàn)是否通過放?
不放?,web應(yīng)?resp.sendRedirect("/index.html") 或者 返回json字符串 - 使用場(chǎng)景
權(quán)限控制沉馆、?戶登錄狀態(tài)控制码党,也可以交給攔截器處理等 - 示例:用戶登錄過濾器
2.1 新建controller同級(jí)包filter
2.2 創(chuàng)建登錄過濾器類LoginFilter
@WebFilter(urlPatterns = "/app/v1/pri/*", filterName = "loginFilter")
public class LoginFilter implements Filter {
private static final ObjectMapper objectMapper = new ObjectMapper(); // 處理對(duì)象與json的轉(zhuǎn)換
/**
* 容器加載的時(shí)候
* @param filterConfig
* @throws ServletException
*/
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("init LoginFilter======");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("doFilter LoginFilter======");
HttpServletRequest req = (HttpServletRequest) servletRequest;
HttpServletResponse resp = (HttpServletResponse) servletResponse;
String token = req.getHeader("token");
if(StringUtils.isEmpty(token)){
token = req.getParameter("token");
}
if(!StringUtils.isEmpty(token)){
//判斷token是否合法
User user = UserServiceImpl.sessionMap.get(token);
if(user!=null){
filterChain.doFilter(servletRequest,servletResponse);
} else {
// 有token,但token無(wú)效
RetData retData = RetData.RetError(-2,"登錄失敗斥黑,token無(wú)效");
String jsonStr = objectMapper.writeValueAsString(retData);
renderJson(resp,jsonStr);
}
}else {
// 沒有登錄
RetData retData = RetData.RetError(-3,"未登錄");
String jsonStr = objectMapper.writeValueAsString(retData);
renderJson(resp,jsonStr);
}
}
/**
* 容器銷毀的時(shí)候
*/
@Override
public void destroy() {
System.out.println("destroy LoginFilter======");
}
/**
* @param response
* @param json
*/
private void renderJson(HttpServletResponse response,String json){
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json");
try(PrintWriter writer = response.getWriter()){
writer.print(json);
}catch (Exception e){
e.printStackTrace();
}
}
}
2.3 測(cè)試
沒有登錄訪問
{
"code": -3,
"data": null,
"message": "未登錄"
}
錯(cuò)誤的token訪問
{
"code": -2,
"data": null,
"message": "登錄失敗揖盘,token無(wú)效"
}
登錄之后使用正確的token訪問
{
"code": 0,
"data": "下單成功!",
"message": "success"
}
3 使? Servlet3.0的注解?定義原?Servlet
編寫Servlet類繼承HttpServlet
/**
* 使用servlet3.0開發(fā)原生接口
*/
@WebServlet(name = "userServlet", urlPatterns = "/api/v1/test/customs" )
public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter writer = resp.getWriter();
writer.write("this is my custom servlet api");
writer.flush();
writer.close();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
}
}
測(cè)試接口訪問:結(jié)果正確輸出
this is my custom servlet api
4 Servlet3.0的注解?定義原?Listener監(jiān)聽器
- 應(yīng)用上下文監(jiān)聽器ServletContextListener
@WebListener
public class CustomContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("===========contextInitialized==============");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("===========contextDestroyed==============");
}
}
- 會(huì)話監(jiān)聽器HttpSessionLisener
@WebListener
public class CustomSessionListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent se) {
System.out.println("===========sessionCreated==============");
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
System.out.println("===========sessionDestroyed==============");
}
}
- 請(qǐng)求監(jiān)聽器ServletRequestListener
@WebListener
public class CustomRequestListener implements ServletRequestListener {
@Override
public void requestDestroyed(ServletRequestEvent sre) {
System.out.println("===========requestDestroyed==============");
}
@Override
public void requestInitialized(ServletRequestEvent sre) {
System.out.println("===========requestInitialized==============");
}
}
5 SpringBoot2.X攔截器配置
攔截器的作用和用法和過濾器?途基本類似
SpringBoot2.x使?步驟:
- ?定義攔截器 HandlerInterceptor
preHandle:調(diào)?Controller某個(gè)?法之前
postHandle:Controller之后調(diào)?锌奴,視圖渲染之前兽狭,如果控制器Controller出現(xiàn)了異常,則不會(huì)執(zhí)?此?法
afterCompletion:不管有沒有異常鹿蜀,這個(gè)afterCompletion都會(huì)被調(diào)?箕慧,?于資源清理 - 配置攔截器 implements WebMvcConfigurer
有多個(gè)攔截器的情況下,按照注冊(cè)順序進(jìn)?攔截茴恰,先注冊(cè)颠焦,先被攔截
5.1 示例演示:配置登錄攔截器
- 創(chuàng)建controller同級(jí)包intercepter
- 創(chuàng)建自定義攔截器類LoginIntercepter
public class LoginIntercepter implements HandlerInterceptor {
private static final ObjectMapper objectMapper = new ObjectMapper();
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("========LoginIntercepter preHandle======");
String token = request.getHeader("token");
if(StringUtils.isEmpty(token)){
token = request.getParameter("token");
}
if(!StringUtils.isEmpty(token)){
//判斷token是否合法
User user = UserServiceImpl.sessionMap.get(token);
if(user!=null){
return true;
} else {
RetData retData = RetData.RetError(-2,"登錄失敗,token無(wú)效");
String jsonStr = objectMapper.writeValueAsString(retData);
renderJson(response,jsonStr);
}
}else {
RetData retData = RetData.RetError(-3,"未登錄");
String jsonStr = objectMapper.writeValueAsString(retData);
renderJson(response,jsonStr);
}
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("=============postHandle=============");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("=============postHandle=============");
}
/**
* 返回json數(shù)據(jù)
* @param response
* @param json
*/
private void renderJson(HttpServletResponse response,String json){
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json");
try(PrintWriter writer = response.getWriter()){
writer.print(json);
}catch (Exception e){
e.printStackTrace();
}
}
}
- 配置攔截器
/**
* 攔截器配置類
*/
@Configuration
public class CustomMvcConfigurer implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
System.out.println("==========addInterceptors=============");
registry.addInterceptor(getLoginInterceptor()).addPathPatterns("/app/v1/pri/**");
WebMvcConfigurer.super.addInterceptors(registry);
}
/**
* 通過bean的方式引入攔截器
* @return
*/
@Bean
public LoginIntercepter getLoginInterceptor(){
return new LoginIntercepter();
}
}
5.2 攔截器不?效常?問題:
- 是否有加@Configuration
- 攔截路徑是否有問題 ** 和 *
- 攔截器最后路徑?定要 /** 如果是?錄的話則是 /*/
5.3 攔截器和Filter過濾器的區(qū)別
- Filter和Interceptor?者都是AOP編程思想的體現(xiàn)往枣,功能基本都可以實(shí)現(xiàn)
- 攔截器功能更強(qiáng)?些伐庭,F(xiàn)ilter能做的事情它都能做
- Filter在只在Servlet前后起作?,?Interceptor夠深?到?法前后分冈、異常拋出前后等
- filter依賴于Servlet容器即web應(yīng)?中圾另,?Interceptor不依賴于Servlet容器所以可以運(yùn)?在
多種環(huán)境。 - 在接?調(diào)?的?命周期?丈秩,Interceptor可以被多次調(diào)?盯捌,?Filter只能在容器初始化時(shí)調(diào)??
次淳衙。
5.4 Filter和Interceptor的執(zhí)?順序
- 過濾前->攔截前->action執(zhí)?->攔截后->過濾后
5.5 如何配置不攔截某些路徑蘑秽?
registry.addInterceptor(new LoginIntercepter()).addPathPatterns("/api/v1/pri/**")
//配置不攔截某些路徑,?如靜態(tài)資源
.excludePathPatterns("/**/*.html","/**/*.js");