拦截器(Interceptor),主要完成请求参数的解析、将页面表单参数赋给值栈中相应属性、执行功能检验、程序异常调试等工作。
1、基于springboot拦截器记录操作日志
2、Request 获取Post请求 body的参数(地址:https://blog.csdn.net/qq_42227281/article/details/106899303)
3、工具类里调用Dao或Service为null解决办法(提示信息:Non-static field cannot be referenced from a static context)
自定义拦截器实现HandlerInterceptor接口,@Component注解一定不要忘记
@component (把普通pojo实例化到spring容器中,相当于配置文件中的
)
@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 自定义拦截器,拦截请求路径
*
* @Author: 王文龙
* @Date: 2020/6/1917:18
* @Version: 1.0
* @Describe: 描述:用户拦截器
*/
@Component
public class RequestUrlInterceptor implements HandlerInterceptor {
private Logger logger = LoggerFactory.getLogger(RequestUrlInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
logger.info("请求开始 --- Url : " + request.getRequestURI());
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
logger.info("请求结束");
if (ex != null) {
logger.error("报错信息 : ", ex);
}
}
}
将拦截器配置到Springboot环境中
package com.it.conformity.common.interceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.annotation.Resource;
/**
* @Author: 王文龙
* @Date: 2020/6/1918:16
* @Version: 1.0
* @Describe: 描述:mvc配置
*/
@Configuration
public class RequestConfig implements WebMvcConfigurer {
@Resource
private RequestUrlInterceptor requestUrlInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 添加拦截器,配置拦截地址
registry.addInterceptor(requestUrlInterceptor).addPathPatterns("/**");
}
}
必须加上@Configuration注解,Spring才能统一管理当前的拦截器实例。
addPathPatterns("/api/**")配置拦截路径,其中/**表示当前目录以及所有子目录(递归),/*表示当前目录,不包括子目录。
现在Springboot拦截器就已经生效了
1、在拦截器的afterCompletion方法中调用保存日志的方法
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// 保存日志
SysLogUtil.saveLog(request, ex, null);
logger.info("请求结束");
if (ex != null) {
logger.error("报错信息 : ", ex);
}
}
2、日志类(有一点需要注意,保存日志的方法用的是静态方法,但是静态方法无法引入非静态方法,所以这里利用反射将Dao或Service注入到工具类中)
package com.it.conformity.common.util;
import com.alibaba.fastjson.JSON;
import com.it.conformity.testdemo.dao.SysLogDao;
import com.it.conformity.testdemo.pojo.SysLog;
import org.springframework.util.Assert;
import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 保存日志的工具类
*
* @Author: 王文龙
* @Date: 2020/6/2011:39
* @Version: 1.0
* @Describe: 描述:
*/
public class SysLogUtil {
private static SysLogDao sysLogDao = SpringUtil.getApplicationContext().getBean(SysLogDao.class);
/**
* 保存日志
*/
public static void saveLog(HttpServletRequest request, Exception ex, String title) throws Exception {
SysLog log = new SysLog();
log.setTitle(title);
log.setType(ex == null ? "1" : "2");
//登陆人获取这块还没法实现,这个框架是我私下整合其他插件用框架,后面把Shiro或者SpringSecruity整合到Springboot之后,就可以拿到当前登陆人的信息了
log.setCreateBy("王文龙");
log.setRemoteAddr(StringUtils.getRemoteAddr(request));
log.setUserAgent(request.getHeader("user-agent"));
log.setRequestUri(request.getRequestURI());
log.setParamsMap(request.getParameterMap());log.setMethod(request.getMethod());
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String format = simpleDateFormat.format(new Date());
log.setCreateDate(format);
// 保存日志
boolean insert = sysLogDao.insert(log);
Assert.isTrue(insert,"添加系统日志失败");
}
}
3、SpringUtil
package com.it.conformity.common.util;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
* Spring 工具包 获取bean类
* @Author: 王文龙
* @Date: 2020/6/2013:58
* @Version: 1.0
* @Describe: 描述:
*/
@Component
public class SpringUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (SpringUtil.applicationContext == null) {
SpringUtil.applicationContext = applicationContext;
}
}
//获取applicationContext
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
//通过name获取 Bean.
public static Object getBean(String name) {
return getApplicationContext().getBean(name);
}
//通过class获取Bean.
public static T getBean(Class clazz) {
return getApplicationContext().getBean(clazz);
}
//通过name,以及Clazz返回指定的Bean
public static T getBean(String name, Class clazz) {
return getApplicationContext().getBean(name, clazz);
}
}
4、StringUtils
pom
org.apache.commons
commons-lang3
3.10
package com.it.conformity.common.util;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringEscapeUtils;
import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @Author: 王文龙
* @Date: 2020/6/2011:46
* @Version: 1.0
* @Describe: 描述:
*/
public class StringUtils extends org.apache.commons.lang3.StringUtils{
private static final char SEPARATOR = '_';
private static final String CHARSET_NAME = "UTF-8";
/**
* 转换为字节数组
*
* @param str
* @return
*/
public static byte[] getBytes(String str) {
if (str != null) {
try {
return str.getBytes(CHARSET_NAME);
} catch (UnsupportedEncodingException e) {
return null;
}
} else {
return null;
}
}
/**
* 转换为Boolean类型 'true', 'on', 'y', 't', 'yes' or '1' (case insensitive) will return true. Otherwise, false is
* returned.
*/
public static Boolean toBoolean(final Object val) {
if (val == null) {
return false;
}
return BooleanUtils.toBoolean(val.toString()) || "1".equals(val.toString());
}
/**
* 转换为字节数组
*
*/
public static String toString(byte[] bytes) {
try {
return new String(bytes, CHARSET_NAME);
} catch (UnsupportedEncodingException e) {
return EMPTY;
}
}
/**
* 如果对象为空,则使用defaultVal值 see: ObjectUtils.toString(obj, defaultVal)
*
* @param obj
* @param defaultVal
* @return
*/
public static String toString(final Object obj, final String defaultVal) {
return obj == null ? defaultVal : obj.toString();
}
/**
* 缩略字符串(不区分中英文字符)
*
* @param str 目标字符串
* @param length 截取长度
* @return
*/
public static String abbr(String str, int length) {
if (str == null) {
return "";
}
try {
StringBuilder sb = new StringBuilder();
int currentLength = 0;
for (char c : replaceHtml(StringEscapeUtils.unescapeHtml4(str)).toCharArray()) {
currentLength += String.valueOf(c).getBytes("GBK").length;
if (currentLength <= length - 3) {
sb.append(c);
} else {
sb.append("...");
break;
}
}
return sb.toString();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return "";
}
/**
* 是否包含字符串
*
* @param str 验证字符串
* @param strs 字符串组
* @return 包含返回true
*/
public static boolean inString(String str, String... strs) {
if (str != null) {
for (String s : strs) {
if (str.equals(trim(s))) {
return true;
}
}
}
return false;
}
/**
* 替换掉HTML标签方法
*/
public static String replaceHtml(String html) {
if (isBlank(html)) {
return "";
}
String regEx = "<.+?>";
Pattern p = Pattern.compile(regEx);
Matcher m = p.matcher(html);
String s = m.replaceAll("");
return s;
}
/**
* 替换为手机识别的HTML,去掉样式及属性,保留回车。
*
* @param html
* @return
*/
public static String replaceMobileHtml(String html) {
if (html == null) {
return "";
}
return html.replaceAll("<([a-z]+?)\\s+?.*?>", "<$1>");
}
/**
* 转换为Double类型
*/
public static Double toDouble(Object val) {
if (val == null) {
return 0D;
}
try {
return Double.valueOf(trim(val.toString()));
} catch (Exception e) {
return 0D;
}
}
/**
* 转换为Float类型
*/
public static Float toFloat(Object val) {
return toDouble(val).floatValue();
}
/**
* 转换为Long类型
*/
public static Long toLong(Object val) {
return toDouble(val).longValue();
}
/**
* 转换为Integer类型
*/
public static Integer toInteger(Object val) {
return toLong(val).intValue();
}
/**
* 获得用户远程地址
*/
public static String getRemoteAddr(HttpServletRequest request) {
String remoteAddr = request.getHeader("X-Real-IP");
if (isNotBlank(remoteAddr)) {
remoteAddr = request.getHeader("X-Forwarded-For");
} else if (isNotBlank(remoteAddr)) {
remoteAddr = request.getHeader("Proxy-Client-IP");
} else if (isNotBlank(remoteAddr)) {
remoteAddr = request.getHeader("WL-Proxy-Client-IP");
}
return remoteAddr != null ? remoteAddr : request.getRemoteAddr();
}
/**
* 驼峰命名法工具
*
* @return toCamelCase("hello_world") == "helloWorld" toCapitalizeCamelCase("hello_world") == "HelloWorld"
* toUnderScoreCase("helloWorld") = "hello_world"
*/
public static String toCamelCase(String s) {
if (s == null) {
return null;
}
s = s.toLowerCase();
StringBuilder sb = new StringBuilder(s.length());
boolean upperCase = false;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == SEPARATOR) {
upperCase = true;
} else if (upperCase) {
sb.append(Character.toUpperCase(c));
upperCase = false;
} else {
sb.append(c);
}
}
return sb.toString();
}
/**
* 驼峰命名法工具
*
* @return toCamelCase("hello_world") == "helloWorld" toCapitalizeCamelCase("hello_world") == "HelloWorld"
* toUnderScoreCase("helloWorld") = "hello_world"
*/
public static String toCapitalizeCamelCase(String s) {
if (s == null) {
return null;
}
s = toCamelCase(s);
return s.substring(0, 1).toUpperCase() + s.substring(1);
}
/**
* 驼峰命名法工具
*
* @return toCamelCase("hello_world") == "helloWorld" toCapitalizeCamelCase("hello_world") == "HelloWorld"
* toUnderScoreCase("helloWorld") = "hello_world"
*/
public static String toUnderScoreCase(String s) {
if (s == null) {
return null;
}
StringBuilder sb = new StringBuilder();
boolean upperCase = false;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
boolean nextUpperCase = true;
if (i < (s.length() - 1)) {
nextUpperCase = Character.isUpperCase(s.charAt(i + 1));
}
if ((i > 0) && Character.isUpperCase(c)) {
if (!upperCase || !nextUpperCase) {
sb.append(SEPARATOR);
}
upperCase = true;
} else {
upperCase = false;
}
sb.append(Character.toLowerCase(c));
}
return sb.toString();
}
/**
* 转换为JS获取对象值,生成三目运算返回结果
*
* @param objectString 对象串 例如:row.user.id 返回:!row?'':!row.user?'':!row.user.id?'':row.user.id
*/
public static String jsGetVal(String objectString) {
StringBuilder result = new StringBuilder();
StringBuilder val = new StringBuilder();
String[] vals = split(objectString, ".");
for (int i = 0; i < vals.length; i++) {
val.append("." + vals[i]);
result.append("!" + (val.substring(1)) + "?'':");
}
result.append(val.substring(1));
return result.toString();
}
}
拦截器拦截了所有的接口,这时候随便调一个接口试一试,成功后,日志表应该已经有自己想要的东西了