1。自定义注解
@Documented //支持JavaDoc文档注释
@Inherited // 表某个被标注的类型是被继承的
@Target(ElementType.METHOD) //表明该注解对成员方法起作用
@Retention(RetentionPolicy.RUNTIME) //在编译以后仍然起作用
public @interface logRecord {
/**
* @Description: 是否记录日志
* @return: String
* @author: fss
*/
String validate() default AccessLoggingCode.CHECK_API;
/**
* @Description: 操作类型
* @return: String
* @author: fss
*/
String operation() default AccessLoggingCode.SELECT;
/**
* @Description: 操作模块
* @return: String
* @author: fss
*/
String operationModule() default "默认操作模块";
/**
* @Description: 操作备注
* @return: String
* @author: fss
*/
String remark() default "默认备注";
/**
* @Description: 操作平台
* @return: String
* @author: fss
*/
String operationTerrace() default AccessLoggingCode.savingAPP;
}
2。controller
/**
*
* @Title: SupplierLogin
* @Description: app端运营商登录
* @param: @param response
* @param: @param request
* @param: @return
* @return: Map<String,Object>
* @author: FSS
* @throws
*/
@ResponseBody
@DataSourceAuth(validate=DatasourceConfig.dataSourceA)
@PowerAuth(validate=RestPowerAPIcontent.NORMAL_API)
@logRecord(operation=AccessLoggingCode.LOGIN ,operationTerrace = AccessLoggingCode.operatorAPP , operationModule = "app端运营商登录" , remark =AccessLoggingCode.LOGIN)
@RequestMapping(value="/v1/Amd/OperatorLogin/login",method ={RequestMethod.POST},produces="application/json;charset=utf-8")
public Map<String,Object> userLoginaes(@RequestBody Map<String,String> map){
return operatorMemberService.operatorLoginingApp(map);
}
3.在spring.xml配置文件来构建拦截器(xxxx包名)
<!-- 客户端访问日志拦截器 -->
<mvc:interceptor>
<mvc:mapping path="/app/**" />
<mvc:mapping path="/rest/**" />
<mvc:mapping path="/test/**" />
<bean class="com.xxxx.filter.logRecordInterceptor"></bean>
</mvc:interceptor>
4.创建上面配置的拦截器, 来继承HandlerInteceptorAdaptor 或者实现 HandlerInteceptor 接口.这里集成 HandlerInteceptorAdaptor
public class logRecordInterceptor extends HandlerInterceptorAdapter {
@Autowired
private UserAccessLoggingDao useraccessLoggingDao;
/**
* 在拦截器中通过ContentCachingResponseWrapper获取HttpServletResponse响应体中的数据
* @param response
* @return
* @throws IOException
* @author: fss
*/
public static Map<String, Object> readPostJsonData(HttpServletResponse response) throws IOException {
if (response instanceof ContentCachingResponseWrapper) {
/*response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Type", "text/html;charset=UTF-8");*/
ContentCachingResponseWrapper responseWrapper = (ContentCachingResponseWrapper) response;
int contentLenth = ((ContentCachingResponseWrapper) response).getContentSize();
if (contentLenth <= 0) {
return null;
}
byte[] bytes = new byte[contentLenth];
InputStream is = responseWrapper.getContentInputStream();
for (int index = 0; index < contentLenth; index++) {
int value = is.read();
if (value == -1) {
// is.reset();
break;
}
bytes[index] = (byte) value;
}
//responseWrapper.getContentAsByteArray();//这里是为了测试
String data = new String(bytes);
//System.out.println("http util .........data:" + data);
Map<String, Object> map = MapUtils.stringToMap(data);
return map;
}
return null;
}
@Override
public boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler) throws Exception {
return super.preHandle(request, response, handler);
}
// \b 是单词边界(连着的两个(字母字符 与 非字母字符) 之间的逻辑上的间隔),
// 字符串在编译时会被转码一次,所以是 "\\b"
// \B 是单词内部逻辑间隔(连着的两个字母字符之间的逻辑上的间隔)
static String phoneReg = "\\b(ip(hone|od)|android|opera m(ob|in)i" + "|windows (phone|ce)|blackberry" + "|s(ymbian|eries60|amsung)|p(laybook|alm|rofile/midp"
+ "|laystation portable)|nokia|fennec|htc[-_]" + "|mobile|up.browser|[1-4][0-9]{2}x[1-4][0-9]{2})\\b";
static String tableReg = "\\b(ipad|tablet|(Nexus 7)|up.browser" + "|[1-4][0-9]{2}x[1-4][0-9]{2})\\b";
// 移动设备正则匹配:手机端、平板
static Pattern phonePat = Pattern.compile(phoneReg, Pattern.CASE_INSENSITIVE);
static Pattern tablePat = Pattern.compile(tableReg, Pattern.CASE_INSENSITIVE);
/**
* 获取设备名称
* @param userAgent
* @return
*/
protected String getDeviceName(String userAgent) {
if (null == userAgent) {
userAgent = "";
}
// 匹配
Matcher matcherPhone = phonePat.matcher(userAgent);
Matcher matcherTable = tablePat.matcher(userAgent);
if (matcherPhone.find()) {
return matcherPhone.group();
} else if (matcherTable.find()) {
return matcherTable.group();
} else {
return "pc";
}
}
/**
* @Description: 返回处理
* @return: String
* @author: fss
*/
@SuppressWarnings("unchecked")
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
HandlerMethod hm = (HandlerMethod) handler;
logRecord record = hm.getMethodAnnotation(logRecord.class);
if (record != null && record.validate().equals(AccessLoggingCode.CHECK_API)) {
String operation = record.operation();//操作类型
String businessLogic = record.operationModule();//操作模块
String remark = record.remark();//备注
String terrace = record.operationTerrace();//操作平台
String url = request.getRequestURI();// 操作的URI
String ip = CusAccessObjectUtil.getIpAddr(request);//访问ip
String memberId="";
String Agent = request.getHeader("User-Agent");//DEProvinceFuBao/1.89 (iPhone; iOS 12.2; Scale/3.00)
String getDeviceName = getDeviceName(Agent);
try {
//取用户信息
if(terrace.equals(AccessLoggingCode.savingAPP)||terrace.equals(AccessLoggingCode.supplierAPP)){
String memberId1=request.getHeader("memberId");
if(memberId1!=null&&!operation.equals(AccessLoggingCode.LOGIN)){//非登录从Header取用户信息
memberId = memberId1;
}else{ //从response取用户信息
Map<String, Object> parametersAll = readPostJsonData(response);
Map<String, Object> parameters = null;
if(!MapUtils.mapIsAnyBlank(parametersAll, "data")){
parameters = (Map<String, Object>) parametersAll.get("data");
if(!MapUtils.mapIsAnyBlank(parameters, "memberId")){
memberId = parameters.get("memberId").toString();
remark = "请求成功";
}
}else if(MapUtils.mapIsAnyBlank(parametersAll, "data")&&!MapUtils.mapIsAnyBlank(parametersAll, "code")&&!SuccessCodeConfigure.SUCCESS_CODE.equals(parametersAll.get("code"))){//访问失败
String errorMessage = "请求失败";
if(!MapUtils.mapIsAnyBlank(parametersAll, "errorMessage")){
errorMessage = parametersAll.get("errorMessage").toString();
}
remark = "errorMessage:"+errorMessage;
}
}
}else if(terrace.equals(AccessLoggingCode.operatorAPP)){
String cOperatorId=request.getHeader("cOperatorId");
if(cOperatorId!=null&&!operation.equals(AccessLoggingCode.LOGIN)){//非登录从Header取用户信息
memberId = cOperatorId;
}else{//从response取用户信息
Map<String, Object> parametersAll = readPostJsonData(response);
Map<String, Object> parameters = null;
if(!MapUtils.mapIsAnyBlank(parametersAll, "data")){
parameters = (Map<String, Object>) parametersAll.get("data");
if(operation.equals(AccessLoggingCode.LOGIN)||operation.equals(AccessLoggingCode.LOGOUT)){
if(!MapUtils.mapIsAnyBlank(parameters, "cOperatorId")){
memberId = parameters.get("cOperatorId").toString();
}
}
}else if(!MapUtils.mapIsAnyBlank(parametersAll, "code")&&!SuccessCodeConfigure.SUCCESS_CODE.equals(parametersAll.get("code"))){//访问失败
String errorMessage = "请求失败";
if(!MapUtils.mapIsAnyBlank(parametersAll, "errorMessage")){
errorMessage = parametersAll.get("errorMessage").toString();
}
remark = "errorMessage:"+errorMessage;
}
}
}
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
//执行日志记录(此处根据自己业务逻辑写持久化代码)
}
super.postHandle(request, response, handler, modelAndView);
}
/**
* 从request中获得参数Map,并返回可读的Map
*
* @param request
* @return
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public static Map<String,Object> getParameterMap(HttpServletRequest request) {
// 参数Map
Map<String,Object> properties = request.getParameterMap();
// 返回值Map
Map<String,Object> returnMap = new HashMap();
Iterator entries = properties.entrySet().iterator();
Map.Entry entry;
String name = "";
String value = "";
while (entries.hasNext()) {
entry = (Map.Entry) entries.next();
name = (String) entry.getKey();
Object valueObj = entry.getValue();
if(null == valueObj){
value = "";
}else if(valueObj instanceof String[]){
String[] values = (String[])valueObj;
for(int i=0;i<values.length;i++){
value = values[i] + ",";
}
value = value.substring(0, value.length()-1);
}else{
value = valueObj.toString();
}
returnMap.put(name, value);
}
return returnMap;
}
}
其实利用拦截器还可以做简单的权限控制、一些敏感词过滤、简单的数据统计