springboot(3)——整合freemarker模板、AOP統一處理、全域性異常處理
阿新 • • 發佈:2018-11-01
《三》、整合freemarker模板、AOP統一處理、全域性異常處理
一、整合freemarker模板引擎
- 1、引入freemarker依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
- 2、常用配置
################## ##########################################
#
# freemarker 靜態資源配置
#
############################################################
# 設定ftl檔案路徑
spring.freemarker.template-loader-path=classpath:/templates
# 關閉快取, 即時重新整理, 上線生產環境時需要修改了true
spring.freemarker.cache=false
spring.freemarker.charset=UTF-8
spring.freemarker.check-template-location=true
spring.freemarker.content-type=text/html
spring.freemarker.expose-request-attributes=true
spring.freemarker.expose-session-attributes=true
spring.freemarker.request-context-attribute=request
spring.freemarker.suffix=.ftl
3、
templates
目錄下新建xxx.ftl
字尾的模板html檔案4、註解
@Controller
開啟模板網頁
@RequestMapping ("/ftl")
public String showFtl(ModelMap map) {
return "xxx"; // 對應templates目錄下的xxx.ftl模板
}
二、AOP統一處理
AOP指面向切面程式設計, 比如在很多個請求中加某一點"面"中驗證是否登入的切入口(PointCut)
- 1、引入aop依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
- 2、新建一個類
HttpAspect.java
切面類
@Aspect // 切面註解
@Component
public class HttpAspect {
// 攔截TestController控制器的aspectTest方法
@Before("execution(public * com.xxx.yyy.controller.TestController.aspectTest(..))")
public void logBefore() {
// 每次訪問“..../aspect”請求前會列印如下
System.out.println("logBefore");
}
// 攔截TestController控制器中所有方法
// @Before("execution(public * com.xxx.yyy.controller.TestController.*(..))")
@After("execution(public * com.xxx.yyy.controller.TestController.aspectTest(..))")
public void logAfter() {
// 每次訪問“..../aspect”請求後會列印如下
System.out.println("logAfter");
}
// 上面的@Before和@After重複, 可以抽出公用的PointCut切面
// 上面的程式碼可替換為如下
@Pointcut("execution(public * com.xxx.yyy.TestController.aspectTest(..))")
public void log() {
}
@Before("log()")
public void logBefore() {
System.out.println("logBefore");
}
@After("log()")
public void logAfter() {
System.out.println("logAfter");
}
}
- 3、TestController控制器中
@GetMapping("/aspect")
@ResponseBody
public String aspectTest() {
return "aspect test";
}
- 4、獲取http請求頭的內容
@Before("log()")
public void doBefore(JoinPoint joinPoint) { //JoinPoint提供對連線點上可用狀態和靜態資訊的反射訪問
ServletRequestAttributes attributes=(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
//url
logger.info("url={}",request.getRequestURL());
//method
logger.info("method={}",request.getMethod());
//ip
logger.info("ip={}",request.getRemoteAddr());
//類方法
logger.info("clsss_method={}",joinPoint.getSignature().getDeclaringTypeName()+"."+joinPoint.getSignature().getName());
//引數
logger.info("args={}",joinPoint.getArgs());
}
- 5、AOP中獲取方法返回Response內容
@AfterReturning(returning = "obj", pointcut="log()")
public void doAfterReturn(Object obj){
logger.info("response={}", obj.toString())
}
三、全域性異常處理
- 1、列舉用於統一管理異常的code和message
@Getter
public enum ResultEnum {
LOGIN_FAIL(-1, "登入失敗, 登入資訊不正確"),
LOGOUT_SUCCESS(-2, "登出成功"),
;
private Integer code;
private String message;
ResultEnum(Integer code, String message) {
this.code = code;
this.message = message;
}
}
- 2、定義自己的繼承RuntimeException的異常類
@Getter
public class B2CException extends RuntimeException {
private Integer code;
public B2CException(ResultEnum resultEnum) {
super(resultEnum.getMessage());
this.code = resultEnum.getCode();
}
public B2CException(Integer code, String message) {
super(message);
this.code = code;
}
}
- 3、兩種請求的捕獲異常類:
- 頁面跳轉形式
@ControllerAdvice
public class B2CExceptionHandler {
public static final String IMOOC_ERROR_VIEW = "error";
// 全域性捕獲Exception.class異常, 跳轉到error.ftl模板
@ExceptionHandler(value = Exception.class)
public Object errorHandler(HttpServletRequest reqest,
HttpServletResponse response, Exception e) throws Exception {
e.printStackTrace(); // 列印錯誤
ModelAndView mav = new ModelAndView();
mav.addObject("exception", e);
mav.addObject("url", reqest.getRequestURL());
mav.setViewName(IMOOC_ERROR_VIEW);
return mav;
}
}
- ajax形式(捕獲自定義B2CException異常)
// 全域性捕獲B2CExceptionn.class自定義的異常, json資料返回時
@ExceptionHandler(value = B2CException.class)
@ResponseBody
public ResultVO handlerB2CException(B2CException e) {
return ResultVOUtil.error(e.getCode(), e.getMessage());
}
統一返回異常的形式
根據請求頭判斷是否是ajax請求來返回頁面還是json資料
@ControllerAdvice public class B2CExceptionHandler { public static final String IMOOC_ERROR_VIEW = "error"; @ExceptionHandler(value = Exception.class) public Object errorHandler(HttpServletRequest reqest, HttpServletResponse response, Exception e) throws Exception { e.printStackTrace(); if (isAjax(reqest)) { return ResultVOUtil.error(555, e.getMessage()); } else { ModelAndView mav = new ModelAndView(); mav.addObject("exception", e); mav.addObject("url", reqest.getRequestURL()); mav.setViewName(IMOOC_ERROR_VIEW); return mav; } } // 判斷是否是ajax請求 private static boolean isAjax(HttpServletRequest httpRequest){ return (httpRequest.getHeader("X-Requested-With") != null && "XMLHttpRequest" .equals( httpRequest.getHeader("X-Requested-With").toString()) ); } }
- 4、使用測試
@GetMapping("/exception")
@ResponseBody
public String exceptionTest() throws Exception {
throw new B2CException(ResultEnum.LOGIN_FAIL);
// return "aspect test";
}
可以看到瀏覽器返回{"code":-1,"msg":"登入失敗, 登入資訊不正確"}