spingmvc的執行步驟
用戶發送請求到dispatcherservlet,
前端控制器到handermaping去找對應的handler,
然後返回一個執行鏈,是handler和響應的攔截器,
執行鏈經過適配器,做一些處理,
到達對應的handler,
經過handler來處理後,返回modelandview,
前端控制器會先對視圖對象進行解析,解析完成後,
前端控制器會對視圖進行渲染,
渲染完成之後,將視圖返回給用戶。
首先,我們發現以上步驟中包含了handlermaping,handlerAdpdater(適配器),和handler,那麼springmvc執行的時候,這些都應該作爲對象存在的,這就是我們springmvc配置的由來
1.我們配置掃描包,將controller全都交給spring管理
2.然後我們開啓註解的自動,來註冊handlermaping和handlerAdpdater
3.因爲我們要解析視圖,所以要有視圖解析器的配置。
4.我們看到經過handlerMaping後,返回的是一個handler和攔截器的執行鏈,那麼重點來了,我們的攔截器開始配置了。
步驟是:我們首先用一個類實現HandlerAdpter,實現裏面的方法,有前置攔截(在handler之前),後置攔截,最終攔截(視圖渲染完成之後)
以上是springmvc的攔截器,那麼springboot中的攔截器又是怎麼實現的呢?
springboot中使用攔截器,
- 自定義一個攔截器,
- 一個類
WebMvcConfigurer
並添加 - 在這個類中重寫 addInterceptors方法,這裏還有一點巧妙的是通過@Bean的方式,將日誌引入
@Bean public LoginInterceptor loginInterceptor(){ return new LoginInterceptor(); } @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(this.loginInterceptor()).addPathPatterns("/**"); }
這個方式來添加攔截器,那麼我們真實開發是怎麼用的呢?
首先跟mvc一樣,用一個類繼承handlerintercapter
public class LoginInterceptor extends HandlerInterceptorAdapter { private JwtProperties jwtProperties; // 定義一個線程域,存放登錄用戶 private static final ThreadLocal<UserInfo> tl = new ThreadLocal<>(); public LoginInterceptor(JwtProperties jwtProperties) { this.jwtProperties = jwtProperties; } @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 查詢token String token = CookieUtils.getCookieValue(request, "LY_TOKEN"); if (StringUtils.isBlank(token)) { // 未登錄,返回401 response.setStatus(HttpStatus.UNAUTHORIZED.value()); return false; } // 有token,查詢用戶信息 try { // 解析成功,證明已經登錄 UserInfo user = JwtUtils.getInfoFromToken(token, jwtProperties.getPublicKey()); // 放入線程域 tl.set(user); return true; } catch (Exception e) { // 拋出異常,證明未登錄或超時,返回401 response.setStatus(HttpStatus.UNAUTHORIZED.value()); return false; } } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { tl.remove(); } public static UserInfo getLoginUser() { return tl.get(); } }然後用mvcconfig實現webmvcconfigurer
@Configuration @EnableConfigurationProperties(JwtProperties.class) public class MvcConfig implements WebMvcConfigurer { @Autowired private JwtProperties jwtProperties; @Bean public LoginInterceptor loginInterceptor() { return new LoginInterceptor(jwtProperties); } @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(loginInterceptor()) .addPathPatterns("/**"); } }