1.Spring的AOP特性
2.使用AOP统一处理全局捕获异常
3.使用AOP统一处理Web请求日志
Spring有两大特性,IOC(控制反转)和AOP(面向切面编程),
我们可以利用aop特性处理全局捕获异常,添加日志,添加事物等。
如果访问项目时出现异常,那么浏览器则会显示500或者别的报错信息,这样很显然是不合适的,这个时候我们就需要全局捕获异常了,当出现错误信息时,返回我们自定义的错误信息。
1.创建一个Controller类
package com.example.springboot_jsp.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ErrorController {
@RequestMapping("/getUser")
public String getUser(){
int i = 1/0;
return "SUCCESS";
}
}
2.浏览器访问时出现错误信息
3.这个时候,就需要我们springboot提供的全局捕获异常异常机制了
我们创建一个新的包下的全局捕获异常类
4.全局捕获异常主要分成两类:
一类捕获返回json格式,另一类捕获返回页面。
1)捕获返回json格式的代码:
package com.example.springboot_jsp.error;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.HashMap;
import java.util.Map;
@ControllerAdvice(basePackages = "com.example.springboot_jsp.controller")
public class GlobaExceptionHandler {
@ExceptionHandler(Exception.class)
@ResponseBody
public Map errorResult(){
Map errorResultMap = new HashMap<>();
errorResultMap.put("errorCode","500");
errorResultMap.put("errorMsg","全局捕获异常错误!");
return errorResultMap;
}
}
浏览器请求:
2)捕获返回ModelAndView(页面)的代码:
package com.example.springboot_jsp.error;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@ControllerAdvice(basePackages = "com.example.springboot_jsp.controller")
public class GlobaExceptionHandler {
/*@ExceptionHandler(Exception.class)
@ResponseBody
public Map errorResult(){
Map errorResultMap = new HashMap<>();
errorResultMap.put("errorCode","500");
errorResultMap.put("errorMsg","全局捕获异常错误!");
return errorResultMap;
}*/
@ExceptionHandler(Exception.class)
public String errorResult(){
return "errorMsg";
}
}
在jsp目录下创建一个errorMsg.jsp页面
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
系统错误啦!!!
浏览器请求:
1.在resources目录下创建一个log4j.properties文件
#log4j.rootLogger=CONSOLE,info,error,DEBUG log4j.rootLogger=info,error,CONSOLE,DEBUG log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout log4j.appender.CONSOLE.layout.ConversionPattern=%d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n log4j.logger.info=info log4j.appender.info=org.apache.log4j.DailyRollingFileAppender log4j.appender.info.layout=org.apache.log4j.PatternLayout log4j.appender.info.layout.ConversionPattern=%d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n log4j.appender.info.datePattern='.'yyyy-MM-dd log4j.appender.info.Threshold = info log4j.appender.info.append=true #log4j.appender.info.File=/home/admin/pms-api-services/logs/info/api_services_info log4j.appender.info.File= D log4j.logger.error=error log4j.appender.error=org.apache.log4j.DailyRollingFileAppender log4j.appender.error.layout=org.apache.log4j.PatternLayout log4j.appender.error.layout.ConversionPattern=%d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n log4j.appender.error.datePattern='.'yyyy-MM-dd log4j.appender.error.Threshold = error log4j.appender.error.append=true #log4j.appender.error.File=/home/admin/pms-api-services/logs/error/api_services_error log4j.appender.error.File=F:/log4j log4j.logger.DEBUG=DEBUG log4j.appender.DEBUG=org.apache.log4j.DailyRollingFileAppender log4j.appender.DEBUG.layout=org.apache.log4j.PatternLayout log4j.appender.DEBUG.layout.ConversionPattern=%d{yyyy-MM-dd-HH-mm} [%t] [%c] [%p] - %m%n log4j.appender.DEBUG.datePattern='.'yyyy-MM-dd log4j.appender.DEBUG.Threshold = DEBUG log4j.appender.DEBUG.append=true #log4j.appender.DEBUG.File=/home/admin/pms-api-services/logs/debug/api_services_debug log4j.appender.DEBUG.File=F:/log4j
2.添加依赖
org.springframework.boot spring-boot-starter-log4j 1.3.8.RELEASE org.springframework.boot spring-boot-starter-aop
3.新增一个aop包,定义一个切面类,打印日志
package com.example.springboot_jsp.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;@Aspect
@Component
public class WebLogAspect {private static final Logger logger = LoggerFactory.getLogger(WebLogAspect.class);
// 切面
@Pointcut("execution(public * com.example.springboot_jsp.controller.*.*(..))")
public void webLog() {
}// 前置通知
@Before("webLog()")
public void doBefore(JoinPoint joinPoint) throws Throwable {
// 接收到请求,记录请求内容
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
// 记录下请求内容
logger.info("URL : " + request.getRequestURL().toString());
logger.info("HTTP_METHOD : " + request.getMethod());
logger.info("IP : " + request.getRemoteAddr());
Enumerationenu = request.getParameterNames();
while (enu.hasMoreElements()) {
String name = (String) enu.nextElement();
logger.info("name:{},value:{}", name, request.getParameter(name));
}
}// 后置通知
@AfterReturning(returning = "ret", pointcut = "webLog()")
public void doAfterReturning(Object ret) throws Throwable {
// 处理完请求,返回内容
logger.info("RESPONSE : " + ret);
}
}
@Pointcut("execution(public * com.example.springboot_jsp.controller.*.*(..))")
定义拦截的切面是所有的controller包请求
4.在controller包下新增IndexController类
package com.example.springboot_jsp.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class IndexController { @RequestMapping("/index") public String getUser(String name,Integer age){ return "success"; } }
5.浏览器访问
6.控制台打印日志
7.我们也可以使用lombok组件的@Slf4j注解,简化每一个类中都要写这行代码,下一篇springboot集成lombok有详解。
private static final Logger logger = LoggerFactory.getLogger(XXXXXX.class);