在JavaWeb开发的过程中,我们经常需要处理前台表单页面传递过来的参数信息,通常情况下我们先是校验参数信息的合法性,然后对于不合法的参数信息,我们不仅仅要将该异常信息抛出,同时我们还要在抛出异常信息时定位该出错点,因而下面的程序对于处理上述功能要求来说就变得比较的合适。
该程序引入的依赖中包括Bean Validation表单验证,lombok插件,最强大的日志log4j2,以及主流的jackson。实现的功能是对于页面表单的信息校验,当信息验证不通过时在日志中抛出该异常信息,方便于后续的项目维护。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>throw-exception-parentartifactId>
<groupId>com.lycgroupId>
<version>1.0-SNAPSHOTversion>
parent>
<modelVersion>4.0.0modelVersion>
<artifactId>param-throw-exceptionartifactId>
<packaging>jarpackaging>
<name>param-throw-exceptionname>
<url>http://maven.apache.orgurl>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-compiler-pluginartifactId>
<configuration>
<source>1.8source>
<target>1.8target>
configuration>
plugin>
plugins>
build>
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
properties>
<dependencies>
<dependency>
<groupId>javax.validationgroupId>
<artifactId>validation-apiartifactId>
<version>2.0.1.Finalversion>
dependency>
<dependency>
<groupId>org.hibernate.validatorgroupId>
<artifactId>hibernate-validatorartifactId>
<version>6.0.7.Finalversion>
dependency>
<dependency>
<groupId>org.glassfishgroupId>
<artifactId>javax.elartifactId>
<version>3.0.1-b08version>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>1.16.20version>
<scope>providedscope>
dependency>
<dependency>
<groupId>org.apache.logging.log4jgroupId>
<artifactId>log4j-slf4j-implartifactId>
<version>2.10.0version>
dependency>
<dependency>
<groupId>org.apache.logging.log4jgroupId>
<artifactId>log4j-coreartifactId>
<version>2.10.0version>
dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatypegroupId>
<artifactId>jackson-datatype-guavaartifactId>
<version>2.5.3version>
dependency>
dependencies>
project>
package com.lyc.exception.entity;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
@Setter
@Getter
@Builder
public class Param {
@NotNull(message = "id字段不能为空!")
private Integer id;
@NotBlank(message = "姓名不能为空!")
@Size(min = 2,max = 12,message = "姓名介于2-12之间!")
private String name;
@NotNull(message = "age字段不能为空!")
private Integer age;
}
package com.lyc.exception.util;
import com.google.common.collect.Maps;
import lombok.NoArgsConstructor;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Set;
@NoArgsConstructor
public class ParamValidateUtil<T>{
//初始化ValidatorFactory
private static final ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
private Set> constraintViolations;
/** * 构造方法 * 利用泛型,传入实体类,进行表单验证。 * @param t */
public ParamValidateUtil(T t) {
Validator validator = factory.getValidator();
this.constraintViolations = validatorParamValite(t,validator);
}
/** * 利用泛型,传入实体类表单,传入Validator进行表单验证 * @param t * @param validator * @return */
private Set> validatorParamValite(T t,Validator validator){
return validator.validate( t );
}
/** * 获取验证的返回信息 * @return */
public LinkedHashMap getMessage(){
LinkedHashMap errors = Maps.newLinkedHashMap();
if(getSize() > 0){
Iterator> iterator = constraintViolations.iterator();
while(iterator.hasNext()){
ConstraintViolation constraintViolation = iterator.next();
errors.put(constraintViolation.getPropertyPath(),constraintViolation.getMessage());
}
}
return errors;
}
/** * 获取错误的信息条数 * @return */
public int getSize(){
return constraintViolations.size();
}
/** * 判断参数校验是否通过 * @return */
public boolean checkParam(){
return getSize() > 0;
}
}
package com.lyc.exception.util;
import lombok.NoArgsConstructor;
@NoArgsConstructor
public class ParamExceptionUtil extends RuntimeException {
public ParamExceptionUtil(String message) {
super(message);
}
public ParamExceptionUtil(String message, Throwable cause) {
super(message, cause);
}
public ParamExceptionUtil(Throwable cause) {
super(cause);
}
protected ParamExceptionUtil(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
package com.lyc.exception;
import com.lyc.exception.entity.Param;
import com.lyc.exception.util.ParamExceptionUtil;
import com.lyc.exception.util.ParamValidateUtil;
import lombok.extern.slf4j.Slf4j;
import org.junit.Assert;
import org.junit.Test;
import java.util.LinkedHashMap;
@Slf4j
public class ParamExceptionTest {
/**
* 校验正确的结果
*/
@Test
public void testSuccessfull(){
Param param = Param.builder()
.id(1)
.name("zhangsan")
.age(21)
.build();
ParamValidateUtil paramParamValidateUtil = new ParamValidateUtil(param);
int count = paramParamValidateUtil.getSize();
Assert.assertEquals(0,count);
log.info("错误信息条数为:{}",count);
LinkedHashMap errors = paramParamValidateUtil.getMessage();
errors.forEach((k,v) -> log.info("打印的错误信息内容为:{},{}",k.toString(),v.toString())); } /** * 校验Name错误的结果 */ @Test public void testParamNameError(){ Param param = Param.builder() .id(1) .name("z") .age(21) .build(); ParamValidateUtil<Param> paramParamValidateUtil = new ParamValidateUtil(param); int count = paramParamValidateUtil.getSize(); log.info("错误信息条数为:{}",count); LinkedHashMap errors = paramParamValidateUtil.getMessage(); errors.forEach((k,v) -> log.info("打印的错误信息内容为:{},{}",k.toString(),v.toString())); if(paramParamValidateUtil.checkParam()){ throw new ParamExceptionUtil("testParamNameError()->姓名参数校验失败!"); } } /** * 校验age错误的结果。 */ @Test public void testParamAgeError(){ Param param = Param.builder() .id(1) .name("zhangsan") .age(null) .build(); ParamValidateUtil<Param> paramParamValidateUtil = new ParamValidateUtil(param); int count = paramParamValidateUtil.getSize(); log.info("错误信息条数为:{}",count); LinkedHashMap errors = paramParamValidateUtil.getMessage(); errors.forEach((k,v) -> log.info("打印的错误信息内容为:{},{}",k.toString(),v.toString())); if(paramParamValidateUtil.checkParam()){ throw new ParamExceptionUtil("testParamAgeError()->年龄参数校验失败!"); } } /** * 校验空表单 */ @Test public void testParamAllError(){ Param param = Param.builder() .id(null) .name(null) .age(null) .build(); ParamValidateUtil<Param> paramParamValidateUtil = new ParamValidateUtil(param); int count = paramParamValidateUtil.getSize(); log.info("错误信息条数为:{}",count); LinkedHashMap errors = paramParamValidateUtil.getMessage(); errors.forEach((k,v) -> log.info("打印的错误信息内容为:{},{}",k.toString(),v.toString())); if(paramParamValidateUtil.checkParam()){ throw new ParamExceptionUtil("testParamAllError()->全部参数校验失败!"); } } }
我们以测试中的最后一个方法testParamAllError()为例来进行说明,由于该方法中,我们所创建的实体类中所有的参数均为null,因而它会产生三条错误信息。
我们在Param实体类中将所有的参数信息全部赋值为null,然后初始化ParamValidateUtil类。该类中有一个泛型的构造方法,通过传入一个实体类,我们将可以完成其初始化操作,之后我们将其错误信息条数打印到控制台中。
接下来我们就获取错误信息的内容,通过paramParamValidateUtil.getMessage()方法,返回一个LinkedHashMap数组,我们通过java8中的lambda表达式,将该LinkedHashMap数组中的信息一一输出到控制台中。
最后就是异常信息抛出,我们采用throw的方式将该异常信息抛出到日志中,同时我建议在抛出异常信息前,我们在所抛出的信息中添加抛出该信息的方法名以及故障原因,这样显示出来的异常信息中,将不仅仅包含类名,还包含调用该方法的方法名以及相应的错误异常信息。
下面是其在控制台中打印出来的异常信息:
2018-02-05 15:56:51 INFO main org.hibernate.validator.internal.util.Version.(Version.java:21) - HV000001: Hibernate Validator 6.0.7.Final
2018-02-05 15:56:51 INFO main com.lyc.exception.ParamExceptionTest.testParamAllError(ParamExceptionTest.java:91) - 错误信息条数为:3
2018-02-05 15:56:51 INFO main com.lyc.exception.ParamExceptionTest.lambda$testParamAllError$3(ParamExceptionTest.java:93) - 打印的错误信息内容为:id,id字段不能为空!
2018-02-05 15:56:51 INFO main com.lyc.exception.ParamExceptionTest.lambda$testParamAllError$3(ParamExceptionTest.java:93) - 打印的错误信息内容为:age,age字段不能为空!
2018-02-05 15:56:51 INFO main com.lyc.exception.ParamExceptionTest.lambda$testParamAllError$3(ParamExceptionTest.java:93) - 打印的错误信息内容为:name,姓名不能为空!
com.lyc.exception.util.ParamExceptionUtil: testParamAllError()->全部参数校验失败!
at com.lyc.exception.ParamExceptionTest.testParamAllError(ParamExceptionTest.java:95)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
...
项目源码:throw-exception-parent