探究项目日志模块的构成
First: 项目简介:一款基于SpringBoot轻量级框架的单机应用管理系统。
Second: Log模块是每个系统都需要做的一个公共模块,探究其实现过程。
Third: 实现过程。
定义注解Annotation
定义日志切面LogAspect
服务调用层加相应注解@Interface
注解编写:
/**
* @Title: Log.java
* @Package com.app.util
* @Description:Annotation
* @version 0.0.0.1
*/
package com.app.log;
import java.lang.annotation.*;
/**
* @ClassName: Log
* @Description: Annotation
* @author pawn
*
*/
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {
/** 要执行的操作类型比如:add操作 **/
public String operationType() default "";
/** 要执行的具体操作比如:添加用户 **/
public String operationName() default "";;
}
日志切面Aspect类:
package com.app.log;
import ..;
@Aspect
@Component
public class SystemLogAspect {
private static final Logger logger = LoggerFactory.getLogger(SystemLogAspect.class);
@Autowired
HttpServletRequest request;
// Controller层切点
@Pointcut("execution (* com.app.*.controller..*.*(..)) && !within(com.app.test..*) && !within(com.app.controller..*)")
public void controllerAspect() {
}
/**
* @Title: doAround
* @Description: 对于Controller的环绕通知
* @param @param pjp
* @param @return
* @param @throws Throwable 设定文件
* @return Object 返回类型
* @throws
*/
@Around("controllerAspect()")
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
logger.info("-------------------------------------controller start------------------------------------------------");
try{
RequestAttributes ra = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes sra = (ServletRequestAttributes) ra;
request = sra.getRequest();
String url = request.getRequestURL().toString();
String method = request.getMethod();
String uri = request.getRequestURI();
String queryString = request.getQueryString();
logger.info("Request, url: {"+url+"}, method: {"+method+"}, uri: {"+uri+"}, params: {"+queryString+"}");
MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
Method methodObject = methodSignature.getMethod();
String operationType = "";
String operationName = "";
operationType = methodObject.getAnnotation(Log.class).operationType();
operationName = methodObject.getAnnotation(Log.class).operationName();
logger.info("Method Type:" + operationType);
logger.info("Method Desc:" + operationName);
Object args[] = pjp.getArgs();
for (Object arg : args) {
logger.info(arg.toString());
}
}catch(Exception e){
logger.error(e.getMessage());
}
// result的值就是被拦截方法的返回值
Object result = pjp.proceed();
Gson gson = new Gson();
logger.info("Response: " + gson.toJson(result));
logger.info("--------------------------------------controller end-------------------------------------------------");
return result;
}
控制器服务层:
package com.app.core.controller;
import ..;代指各种包
@Controller
public class LoginController {
/**
* @Title: loginView
* @Description: 登录页面展示
* @param @param request 请求
* @param @param response 响应
* @param @param locale 本地化
* @param @param model
* @param @return 设定文件
* @return String 返回类型
* @throws
*/
@SuppressWarnings("unchecked")
@RequestMapping(value="/login", method = RequestMethod.GET)
@Log(operationType="Forward",operationName="Forward to hello.jsp or login.jsp")
public ModelAndView loginView(HttpServletRequest request, HttpServletResponse response, Locale locale, Model model) {
ModelAndView modelAndView = new ModelAndView();
// 如果存在session信息,直接登录
if(request.getSession() != null && request.getSession().getAttribute("username") != null){
ServletContext application = request.getSession().getServletContext();
HashMap<String,String> userSessionMapList = (HashMap<String,String>)application.getAttribute("userSessionMapList");
if(userSessionMapList.containsKey(request.getSession().getAttribute("username"))
&& userSessionMapList.containsValue(request.getSession().getId())){
modelAndView.setViewName("devicemgmt");
return modelAndView;
}
}
modelAndView.setViewName("login");
return modelAndView;
}
}
启动服务:输入访问地址
后台日志输出如下:
2018-03-20 16:31:45.916 INFO 7792 --- [nio-8080-exec-2] com.app.log.SystemLogAspect : -------------------------------------controller start------------------------------------------------
2018-03-20 16:31:45.917 INFO 7792 --- [nio-8080-exec-2] com.app.log.SystemLogAspect : Request, url: {http://localhost:8080/login.do}, method: {GET}, uri: {/login.do}, params: {expired}
2018-03-20 16:31:45.918 INFO 7792 --- [nio-8080-exec-2] com.app.log.SystemLogAspect : Method Type:Forward
2018-03-20 16:31:45.918 INFO 7792 --- [nio-8080-exec-2] com.app.log.SystemLogAspect : Method Desc:Forward to hello.jsp or login.jsp
2018-03-20 16:31:45.919 INFO 7792 --- [nio-8080-exec-2] com.app.log.SystemLogAspect : SecurityContextHolderAwareRequestWrapper[ org.springframework.security.web.context.HttpSessionSecurityContextRepository$Servlet3SaveToSessionRequestWrapper@6689c36]
2018-03-20 16:31:45.919 INFO 7792 --- [nio-8080-exec-2] com.app.log.SystemLogAspect : org.springframework.security.web.context.HttpSessionSecurityContextRepository$SaveToSessionResponseWrapper@66c76f2f
2018-03-20 16:31:45.919 INFO 7792 --- [nio-8080-exec-2] com.app.log.SystemLogAspect : zh_CN
2018-03-20 16:31:45.919 INFO 7792 --- [nio-8080-exec-2] com.app.log.SystemLogAspect : {}
2018-03-20 16:31:46.114 INFO 7792 --- [nio-8080-exec-2] com.app.log.SystemLogAspect : Response: {"view":"login","cleared":false}
2018-03-20 16:31:46.114 INFO 7792 --- [nio-8080-exec-2] com.app.log.SystemLogAspect : --------------------------------------controller end-------------------------------------------------
第3、4行后面输出的内容就是controller类上我们自定义的日志内容
只用到了环绕Around,还有很多可以写。欢迎大家自行探索。
这篇文章写的较为简洁些,大家也可以参照。https://www.cnblogs.com/lcngu/p/6593190.html
谨以此记录下对日志一点小分析。