springboot-WebMvcConfigurer(攔截器、跨域訪問、格式化、註冊Controller)
阿新 • • 發佈:2021-06-30
WebMvcConfigurer是用來全域性定製化Spring Boot的MVC特性。開發者通過實現WebMvcConfigurer介面來配置應用的MVC全域性特性。
package com.gcz.conf.mvc; import org.springframework.format.FormatterRegistry; import org.springframework.web.servlet.config.annotation.*; /** * @author guocz * @date 20210621 * MVC全域性特性 */ public class MvcConfigurer implementsWebMvcConfigurer { /** * 攔截器 * @param registry 註冊 */ @Override public void addInterceptors(InterceptorRegistry registry){ } /** * 跨域訪問配置 * @param registry 註冊 */ @Override public void addCorsMappings(CorsRegistry registry){ }/** * 格式化 * @param registry 註冊 */ @Override public void addFormatters(FormatterRegistry registry) { } /** * URI到檢視的對映 * @param registry 註冊 */ @Override public void addViewControllers(ViewControllerRegistry registry){ }// 其他更多全域性定製介面 }
攔截器
通過addInterceptors方法可以設定多個攔截器,比如對特定的URI設定攔截器以檢查使用者是否登入,列印處理使用者請求耗費的時間等。
例:
1、全域性定製攔截器:
package com.gcz.conf.interceptor; import com.gcz.conf.interceptor.handler.SessionHandlerInterceptor; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; /** * @author guocz * @date 20210621 * 全域性攔截器 */ @Configuration public class MvcInterceptor implements WebMvcConfigurer { /** * 攔截器 * @param registry 註冊 */ @Override public void addInterceptors(InterceptorRegistry registry){ registry.addInterceptor(new SessionHandlerInterceptor()).addPathPatterns("/admin/**"); } }
2、會話處理類SessionHandlerInterceptor
package com.gcz.conf.interceptor.handler; import cn.hutool.core.util.StrUtil; import org.springframework.lang.Nullable; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * @author guocz * @date 20210621 * 會話處理攔截器 */ public class SessionHandlerInterceptor implements HandlerInterceptor { private final static String TOKEN = "12345"; /** * Controller處理前 * @param request HttpServletRequest * @param response HttpServletResponse * @param handler 處理物件 * @return true or false * @throws Exception 異常 */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("Controller處理前"); String token =request.getParameter("token"); if (!StrUtil.equals(token, TOKEN)) { // 如果沒登入,重定向到login.html response.getWriter().write("FAIL,PLEASE SIGN IN !"); response.setStatus(400); response.getWriter().close(); return false; } return true; } /** * Controller方法處理完畢後,呼叫此方法 * @param request HttpServletRequest * @param response HttpServletResponse * @param handler 處理物件 * @param modelAndView 檢視 * @throws Exception 異常 */ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception { System.out.println("Controller方法處理完畢後,呼叫此方法"); } /** * 頁面渲染完畢後呼叫此方法,通常用來清除某些資源,類似Java語法的finally * @param request HttpServletRequest * @param response HttpServletResponse * @param handler 處理物件 * @param ex 異常 * @throws Exception 異常 */ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception { System.out.println("頁面渲染完畢後呼叫此方法,通常用來清除某些資源,類似Java語法的finally"); } }
3、相關呼叫測試
package com.gcz.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * @author guocz * @date 20210621 * 使用者 */ @Controller @RequestMapping("/admin") public class UserController { @ResponseBody @RequestMapping("/getUser.json") public void getUser(HttpServletResponse response) throws IOException { response.getWriter().write("ON LINE"); response.setStatus(HttpServletResponse.SC_OK); response.getWriter().close(); } @ResponseBody @RequestMapping("/checkUser.json") public void checkUser(HttpServletResponse response) throws IOException { response.getWriter().write("SUCCESS"); response.setStatus(HttpServletResponse.SC_OK); response.getWriter().close(); } }
跨域訪問
出於安全的考慮,瀏覽器會禁止AJAX訪問不同域的地址。W3C的CORS規範(Cross-originresource sharing)允許實現跨域訪問,並被現在大多數瀏覽器支援,包括:
Chrome 3+;
FireFox 3.5+;
Opera 12+;
Safari 4+;
Internet Explorer 8+;
1、攔截器
/** * 跨域訪問 * @param registry 註冊 */ @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/**") .allowedOrigins("http://domain2.com") .allowedMethods("POST", "GET"); }
格式化
將HTTP請求對映到Controller方法的引數上後,Spring會自動進行型別轉化。對於日期型別的引數,Spring預設並沒有配置如何將字串轉為日期型別。為了支援可按照指定格式轉為日期型別,需要新增一個DateFormatter類:
1、攔截器
/** * 格式化 * @param registry 註冊 */ @Override public void addFormatters(FormatterRegistry registry) { registry.addFormatter(new DateFormatter("yyyy-MM-dd HH:mm:ss")); }
2、入參
package com.gcz.entity.req; import lombok.Data; import javax.validation.constraints.NotNull; import java.util.Date; /** * @author guocz * @date 20210623 * 使用者 */ @Data public class UserReq { /** * 日期 */ @NotNull(message = "日期不能為空") private Date date; }
3、呼叫類
package com.gcz.controller; import com.gcz.entity.req.UserReq; import org.springframework.stereotype.Controller; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Date; /** * @author guocz * @date 20210621 * 使用者 */ @Controller @RequestMapping("/admin") public class UserController { @ResponseBody @RequestMapping("/checkFormatter.json") public void checkFormatter(@Validated UserReq req, HttpServletResponse response) throws IOException { Date date = req.getDate(); response.getWriter().write(date.toString()); response.setStatus(HttpServletResponse.SC_OK); response.getWriter().close(); } }
4、呼叫格式:
註冊Controller
應用有時候沒必要為一個URL指定一個Controller方法,可以直接將URI請求轉到對模板的渲染上。
例:
package com.gcz.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; /** * @author guocz * @date 20210630 * 入口 */ @Controller @RequestMapping("/") public class IndexController { public String index(){ return "/index.btl"; } }
可以直接通過ViewControllerRegistry註冊一個
/** * 註冊Controller * @param registry 註冊 */ @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("index.html").setViewName("/index.btl"); registry.addRedirectViewController("/**/*.do", "/index.html"); }