一、参数校验工具Validator
借鉴简书:https://www.jianshu.com/p/0bfe2318814f
1. Hibernate Validator 简介
平时项目中,难免需要对参数 进行一些参数正确性的校验,这些校验出现在业务代码中,让我们的业务代码显得臃肿,而且,频繁的编写这类参数校验代码很无聊。鉴于此,觉得 Hibernate Validator 框架刚好解决了这些问题,可以很优雅的方式实现参数的校验,让业务代码 和 校验逻辑 分开,不再编写重复的校验逻辑。
Hibernate Validator 是 Bean Validation 的参考实现 . Hibernate Validator 提供了 JSR 303 规范中所有内置 constraint 的实现,除此之外还有一些附加的 constraint。
Bean Validation 为 JavaBean 验证定义了相应的元数据模型和API。缺省的元数据是 Java Annotations,通过使用 XML 可以对原有的元数据信息进行覆盖和扩展。Bean Validation 是一个运行时的数据验证框架,在验证之后验证的错误信息会被马上返回。
2. Hibernate Validator 的作用
- 验证逻辑与业务逻辑之间进行了分离,降低了程序耦合度;
- 统一且规范的验证方式,无需你再次编写重复的验证代码;
- 你将更专注于你的业务,将这些繁琐的事情统统丢在一边。
3. Hibernate Validator 的使用
项目中,主要用于接口api 的入参校验和 封装工具类 在代码中校验两种使用方式。
package com.mmall.util;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.mmall.exception.ParamException;
import org.apache.commons.collections.MapUtils;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
public class BeanValidator {
//构建工厂
private static ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
//验证参数
public static <T> Map<String, String> validate(T t, Class... groups) {
Validator validator = validatorFactory.getValidator();
Set validateResult = validator.validate(t, groups);
if (validateResult.isEmpty()) {
return Collections.emptyMap();
} else {
LinkedHashMap errors = Maps.newLinkedHashMap();
Iterator iterator = validateResult.iterator();
while (iterator.hasNext()) {
ConstraintViolation violation = (ConstraintViolation)iterator.next();
errors.put(violation.getPropertyPath().toString(), violation.getMessage());
}
return errors;
}
}
//列表类型的参数
public static Map<String, String> validateList(Collection<?> collection) {
Preconditions.checkNotNull(collection);
Iterator iterator = collection.iterator();
Map errors;
do {
if (!iterator.hasNext()) {
return Collections.emptyMap();
}
Object object = iterator.next();
errors = validate(object, new Class[0]);
} while (errors.isEmpty());
return errors;
}
//对象类型的验证
public static Map<String, String> validateObject(Object first, Object... objects) {
if (objects != null && objects.length > 0) {
return validateList(Lists.asList(first, objects));
} else {
return validate(first, new Class[0]);
}
}
//检查参数是否符合类型
public static void check(Object param) throws ParamException {
Map<String, String> map = BeanValidator.validateObject(param);
if (MapUtils.isNotEmpty(map)) {
throw new ParamException(map.toString());
}
}
}
二、获取Spring上下文
获取spring上下文:ApplicationContext配置了bean的各中关系,中上下文中就可以还获取bean信息
package com.mmall.common;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
//获取spring上下文:ApplicationContext配置了bean的各中关系,中上下文中就可以还获取bean信息
@Component("applicationContextHelper")
public class ApplicationContextHelper implements ApplicationContextAware {
private static ApplicationContext applicationContext;
public void setApplicationContext(ApplicationContext context) throws BeansException {
applicationContext = context;
}
public static <T> T popBean(Class<T> clazz) {
if (applicationContext == null) {
return null;
}
return applicationContext.getBean(clazz);
}
public static <T> T popBean(String name, Class<T> clazz) {
if (applicationContext == null) {
return null;
}
return applicationContext.getBean(name, clazz);
}
}
三、Http前后监听
package com.mmall.common;
import com.mmall.util.JsonMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
//http前后监听
public class HttpInterceptor extends HandlerInterceptorAdapter {
private static final Logger log = LoggerFactory.getLogger(HttpInterceptor.class);
private static final String START_TIME = "requestStartTime";
//请求处理之前
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String url = request.getRequestURI().toString();
Map parameterMap = request.getParameterMap();
log.info("request start. url:{}, params:{}", url, JsonMapper.obj2String(parameterMap));
long start = System.currentTimeMillis();
request.setAttribute(START_TIME, start);//记录开始处理时间
return true;
}
//请求正常处理完调用
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
removeThreadLocalInfo();
}
//请求处理完(正常异常都)调用
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
String url = request.getRequestURI().toString();
long start = (Long) request.getAttribute(START_TIME);
long end = System.currentTimeMillis();//记录结束处理时间
log.info("request completed. url:{}, costTime:{}", url, end - start);//记录总花费时间
removeThreadLocalInfo();
}
public void removeThreadLocalInfo() {
RequestHolder.remove();;
}
}
四、使用ThreadLocal存放用户信息
package com.mmall.common;
import com.mmall.model.SysUser;
import javax.servlet.http.HttpServletRequest;
public class RequestHolder {
//用户登陆后把用户信息放进ThreadLocal,需要的时候拿来用就好
//map-->key:当前进程
private static final ThreadLocal<SysUser> userHolder = new ThreadLocal<SysUser>();
private static final ThreadLocal<HttpServletRequest> requestHolder = new ThreadLocal<HttpServletRequest>();
//放入user
public static void add(SysUser sysUser) {
userHolder.set(sysUser);
}
public static void add(HttpServletRequest request) {
requestHolder.set(request);
}
public static SysUser getCurrentUser() {
return userHolder.get();
}
public static HttpServletRequest getCurrentRequest() {
return requestHolder.get();
}
//移除:不然会一直占用内存
public static void remove() {
userHolder.remove();
requestHolder.remove();
}
}