欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

spring-boot 自定义xml配置web请求拦截器

程序员文章站 2022-04-30 15:51:11
...

spring boo 拦截器教程推荐:http://lihao312.iteye.com/blog/2078139

自定义web请求参数校验拦截器,通过xml(request-validation.xml)配置url对应的字段进行校验,使校验代码通过配置文件分开,保持代码完整,更加符合领域驱动设计模式。

1.配置spring mvc的拦截器WebMvcConfigurerAdapter 

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
public class WebMvcConfiguration extends WebMvcConfigurerAdapter {

	/**
	 * 添加拦截器
	 */
	public void addInterceptors(InterceptorRegistry registry) {
		registry.addInterceptor(new ValidationHandlerInterceptor());
    }
}

 2、配置拦截器

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.whtr.nginf.infrastructure.util.JsonUtil;
import com.whtr.nginf.infrastructure.web.validation.DateValidation;
import com.whtr.nginf.infrastructure.web.validation.DatetimeValidation;
import com.whtr.nginf.infrastructure.web.validation.DigitValidation;
import com.whtr.nginf.infrastructure.web.validation.GEValidation;
import com.whtr.nginf.infrastructure.web.validation.GTValidation;
import com.whtr.nginf.infrastructure.web.validation.LEValidation;
import com.whtr.nginf.infrastructure.web.validation.LTValidation;

public class ValidationHandlerInterceptor implements HandlerInterceptor {
	
	public static Map<String, ValidationConfig> vcMap = new ConcurrentHashMap<>();
	
	protected Map<String, ParameterValidation> validationMap = new ConcurrentHashMap<>();
	
	public ValidationHandlerInterceptor() {
                //参数拦截拦截项参考附件
		List<ParameterValidation> list = new ArrayList<>();
		list.add(new StringNotBlankValidation());
		list.add(new StringLengthValidation());
		list.add(new DatetimeValidation());
		list.add(new DateValidation());
		list.add(new DigitValidation());
		list.add(new NumberValidation());
		list.add(new RegexValidation());
		list.add(new GEValidation());
		list.add(new GTValidation());
		list.add(new LEValidation());
		list.add(new LTValidation());
		
		list.forEach((validation) -> validationMap.put(validation.getName(), validation));
		
		if(validationMap.size() != list.size()) {
			throw new RuntimeException("验证器名称有重复,请检查");
		}
	}
	
	/**
	 * 预处理
	 */
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
		String url = request.getRequestURI();
		ValidationConfig vc = vcMap.get(url);
		if(vc != null) {
			for(ValidationItem item : vc.getItems()) {
				ParameterValidation pv = validationMap.get(item.getType());
				String value = request.getParameter(item.getName());
				boolean result = pv.validation(value, item.getAttach());
				if(!result) {
					/**
					 * 验证失败,直接返回
					 */
					response.setCharacterEncoding("UTF-8");
					response.setContentType("application/json");
					response.getWriter().write(JsonUtil.toJson(new ResponseResult(item.getMsg(), -1)));
					return false;
				}
			}
		}
		return true;
	}

	/**
	 * 
	 */
	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
		//空方法
	}

	/**
	 * 
	 */
	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
		//空方法
	}
}

 3、解析request-validation.xml,并且注册注册到拦截器

 

package com.whtr.nginf.application.initializer;

import java.io.IOException;
import java.io.InputStream;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;


public final class ValidationInitializer {
	
	private ValidationInitializer() {
	    throw new IllegalAccessError("Utility class");
	  }
	
	private static final Logger LOG = LoggerFactory.getLogger(ValidationInitializer.class);

	private static boolean initializationed = false;

	/**
	 * doInitialization
	 */
	public static void doInitialization() {
		if (initializationed) {
			throw new RuntimeException("ValidationInitializer 已经初始化了");
		}

		try {
			loadValidationConfig();
		} catch (Exception e) {
			LOG.error(e.getMessage(),e);
			throw new RuntimeException("初始化验证配置出错", e);
		}

		initializationed = true;
	}

	/**
	 * 加载配置
	 * @throws IOException 
	 * @throws ParserConfigurationException 
	 * @throws SAXException 
	 * 
	 * @throws Exception
	 */
	private static void loadValidationConfig() throws IOException, ParserConfigurationException, SAXException {
		try (InputStream input = ClassLoader.getSystemResourceAsStream("request-validation.xml")) {
			int count = 0;

			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			DocumentBuilder builder = factory.newDocumentBuilder();
			Document doc = builder.parse(input);
			NodeList nl = doc.getElementsByTagName("validation");

			for (int i = 0; i < nl.getLength(); i++) {
				Element node = (Element) nl.item(i);
				String enable = node.getAttribute("enable");

				if (StringUtils.isBlank(enable) || "true".equals(enable)) {
					NodeList items = node.getElementsByTagName("item");

					if (items.getLength() > 0) {

						ValidationConfig vc = new ValidationConfig();
						vc.setId(node.getAttribute("id"));

						for (int index = 0; index < items.getLength(); index++) {
							Element item = (Element) items.item(index);
							vc.addItem(new ValidationItem(item.getAttribute("name"), item.getAttribute("type"),
									item.getAttribute("msg"), item.getAttribute("attach")));
						}

						count++;
						ValidationHandlerInterceptor.vcMap.put(vc.getId(), vc);
					}
				}
			}

			if (ValidationHandlerInterceptor.vcMap.size() != count) {
				throw new RuntimeException("request-validation.xml 配置重复,请检查是否有相同的ID");
			}

			LOG.info("读取配置成功,总共读取" + count + "个配置项");
		}
	}
}
 4、配置request-validate.xml
<?xml version="1.0" encoding="UTF-8"?>
<validations>

	<validation id="/demo/list" enable="true">
		<item name="orderKey" type="regex" msg="排序key只能是1、2、3" attach="[1|2|3]"/>
		<item name="clientType" type="digit" msg="clientType只能是整数" />
		<item name="endDate" type="date" msg="结束日期错误,正确格式:(yyyy-MM-dd)" />
		<item name="name" type="length" msg="用户名称长度不能超过10" attach="10"/>
		<item name="amount" type="gt" msg="本金必须大于0" attach="0"/>
		<item name="balance" type="number" msg="金额必须是数字" />
		<item name="accountType" type="notBlank" msg="账户类型不能为空" />
	</validation>
	
	<validation id="/demo/xxx" enable="true">
		<item name="age" type="notBlank" msg="数据不能为空" />
	</validation>
</validations>