一.自定义注解
package com.xiaojukeji.common.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface SystemLogAnnotation {
String value();
}
(1)@Target
注解是标注这个类它可以标注的位置,常用的元素类型(ElementType):
public enum ElementType {
/** Class, interface (including annotation type), or enum declaration */
// TYPE类型可以声明在类上或枚举上或者是注解上
TYPE,
/** Field declaration (includes enum constants) */
// FIELD声明在字段上
FIELD,
/** Method declaration */
// 声明在方法上
METHOD,
/** Formal parameter declaration */
// 声明在形参列表中
PARAMETER,
/** Constructor declaration */
// 声明在构造方法上
CONSTRUCTOR,
/** Local variable declaration */
// 声明在局部变量上
LOCAL_VARIABLE,
/** Annotation type declaration */
ANNOTATION_TYPE,
/** Package declaration */
PACKAGE,
/** * Type parameter declaration * * @since 1.8 */
TYPE_PARAMETER,
/** * Use of a type * * @since 1.8 */
TYPE_USE
}
(2)@Retention
注解表示的是本注解(标注这个注解的注解保留时期)
public enum RetentionPolicy {
/**
* Annotations are to be discarded by the compiler.
*/
// 源代码时期
SOURCE,
/**
* Annotations are to be recorded in the class file by the compiler
* but need not be retained by the VM at run time. This is the default
* behavior.
*/
// 字节码时期, 编译之后
CLASS,
/**
* Annotations are to be recorded in the class file by the compiler and
* retained by the VM at run time, so they may be read reflectively.
*
* @see java.lang.reflect.AnnotatedElement
*/
// 运行时期, 也就是一直保留, 通常也都用这个
RUNTIME
}
(3)
@Documented
是否生成文档的标注, 也就是生成接口文档是, 是否生成注解文档
二.拦截器类
package com.xiaojukeji.ecm.interceptor;
import java.lang.reflect.Method;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import nl.bitwalker.useragentutils.UserAgent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import com.xiaojukeji.common.annotation.SystemLogAnnotation;
import com.xiaojukeji.dao.model.SystemLog;
import com.xiaojukeji.ep.ip.common.model.AdUser;
import com.xiaojukeji.ep.ip.common.utils.ContextHolder;
import com.xiaojukeji.service.ERPService;
import com.xiaojukeji.service.SystemLogService;
/**
* <p>Description: [ecm用户操作日志拦截器]</p>
* Created on 2017年11月23日 下午12:05:35
* @author <a href="mailto: 15175223269@163.com">全冉</a>
* @version 1.0
* Copyright (c) 2017 全冉公司
*/
public class EcmSysemLogInterceptor extends HandlerInterceptorAdapter { //此处不继承这个适配器,用implements HandlerInterceptor也行
@Autowired
private ERPService erpService;
@Resource
private SystemLogService systemLogService;
/**
* 在请求处理之前进行调用(Controller方法调用之前),只有返回true才会继续向下执行,返回false取消当前请求
*/
@Override
public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1,
Object handler) throws Exception {
// 将handler强转为HandlerMethod
HandlerMethod handlerMethod = (HandlerMethod) handler;
// 从方法处理器中获取出要调用的方法
Method method = handlerMethod.getMethod();
// 获取出方法上的Access注解
SystemLogAnnotation systemLogAnnotation = method.getAnnotation(SystemLogAnnotation.class);
if (systemLogAnnotation == null) {
// 如果注解为null, 说明不需要拦截, 直接放过
return true;
}
if (systemLogAnnotation != null) {
// 如果自定义注解不为空, 则取出配置值
String value = systemLogAnnotation.value();
// 保存操作日志
addSystemLog(value);
return true;
}
return false;
}
/**
* <p>Discription:[保存操作日志]</p>
* Created on 2017年11月20日 下午3:07:33
* @param operationContent 操作内容
* @author:[全冉]
*/
public void addSystemLog(String operationContent) {
// 获取此次请求的request对象
HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
// 员工号
String employeeNum = adUser.getEmplID();
// 员工姓名
String employeeName = adUser.getEmplName();
// 邮箱
String employeeEmail = adUser.getEmailAddr();
// 浏览器标标识
String webIdentifiy = getBrowserInfo(request);
SystemLog systemLog = new SystemLog();
systemLog.setEmployeeNum(employeeNum);
systemLog.setEmployeeName(employeeName);
systemLog.setEmployeeEmail(employeeEmail);
systemLog.setOperationContent(operationContent);
systemLog.setWebIdentifiy("浏览器" + webIdentifiy);
systemLogService.save(systemLog);
}
/**
* <p>Discription:[根据request获取前台浏览器标识]</p>
* Created on 2017年11月20日 下午7:30:08
* @param request request对象
* @return String 浏览器标识
* @author:[全冉]
*/
private static String getBrowserInfo(HttpServletRequest request) {
UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent"));
String browserInfo = userAgent.getBrowser().toString();
return browserInfo;
}
/**
* 在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)
*/
@Override
public void afterCompletion(HttpServletRequest arg0,
HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
}
/**
* 请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)
*/
@Override
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
Object arg2, ModelAndView arg3) throws Exception {
}
}
三.将拦截器注册到拦截器链
package com.xiaojukeji.ecm.interceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
/**
* web MVC 适配器 * 配置拦截器、处理静态资源、配置消息转换等
* Created by camelot on 2017/10/17.
*/
@Component
public class EcmWebMvcConfig extends WebMvcConfigurerAdapter {
@Bean
public EcmSysemLogInterceptor ecmSysemLogInterceptor(){
return new EcmSysemLogInterceptor();
}
/**
* 注册拦截器
* @param registry 拦截器注册中心
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 注册ecm系统操作日志拦截器(凡加了自定义注解的方法都会添加用户操作日志),拦截所有请求
registry.addInterceptor(ecmSysemLogInterceptor()).addPathPatterns("/**");// 拦截器里有@Autowire或者@Resource注入的属性就这么用
// 注册ecm系统请求拦截器(不拦截登录、注销、回调请求,其他都拦截)
registry.addInterceptor(new EcmRequestInterceptor()).addPathPatterns("/**");
// 连接器里没有@Autowire或者@Resource注入的属性就这么用
super.addInterceptors(registry);
}
/**
* 静态资源处理
* 将请求的如css、html等静态资源定位到项目指定位置
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
super.addResourceHandlers(registry);
}
}
四.在想记录用户日志的方法上,加自定义注解
package com.xiaojukeji.ecm.controller;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.xiaojukeji.common.annotation.SystemLogAnnotation;
import com.xiaojukeji.ep.ip.common.model.AdUser;
import com.xiaojukeji.ep.ip.common.utils.ContextHolder;
import com.xiaojukeji.service.GiftVisitorService;
/**
* <p>Description: [gift服务器 相关API接口]</p>
* Created on 2017年11月8日 上午10:45:09
* @author <a href="mailto: 15175223269@163.com">全冉</a>
* @version 1.0
* Copyright (c) 2017 全冉公司
*/
@Api(value = "gift服务器 相关接口", description = "gift服务器 相关接口")
@RestController@RequestMapping("/gift")
public class GiftVisitorController {
@Autowired
private GiftVisitorService giftVisitorService;
/**
* <p>Discription:[选择文件上传到gift服务器]</p>
* Created on 2017年11月8日 上午10:54:30
* @param request 要上传的文件
* @return String 返回此文件在gift服务器的路径,路径若为空字符串,则需要异常处理
* @author:[全冉]
*/
@ApiOperation("选择文件上传到gift服务器[quanran@camelotchina.com]")
@PostMapping(value = "/upload", consumes = "multipart/*", headers = "content-type=multipart/form-data")
@SystemLogAnnotation(value = "上传文件")
public String upload(@ApiParam(value = "上传的文件", required = true) MultipartFile multipartFile,
HttpServletRequest request) {
// 生成随机fileKey
String fileKey = UUID.randomUUID().toString();
// 获取后缀
String fileName = multipartFile.getOriginalFilename();
String suffix = fileName.substring(fileName.indexOf("."));
}
}
五.启动项目,请求GiftVisitorController 的upload方法,在进入到此方法前,就会对此请求路径进行拦截,将此用户上传文件的操作插入到了数据库中。
另一篇参考地址,可以和我写得相互验证:http://www.jianshu.com/p/43c97352aa1e