SpringMVC 参数校验

参数校验虽说大多在前台通过js完成,但是也应该懂得如何在后端实现参数的简单校验。由于本人目前处于初级阶段,所以文章的深度有限。随着时间推移我会逐渐更新。
参数校验的步骤我就不在赘述,推荐:
参数校验的步骤
我感觉这篇文章,博主其实写的还可以。
我这只说参数校验的另外一种方法,通过继承和引用实现参数校验。
首先是Model参数类:
speaker.java

package com.zhiyou100.video.model;

import java.sql.Date;

import javax.validation.constraints.Size;

import org.springframework.web.multipart.MultipartFile;

import com.zhiyou100.video.common.ValidateGroup1;

public class Speaker {

    private int id;
    @Size(min=2,max=5,message="{name.error}",groups={ValidateGroup1.class})
    private String speakerName;
    private String speakerJob;
    private String speakerHeadUrl;
    private String speakerDescr;
    private MultipartFile icon;
    private Date insertTime;
    private Date updateTime;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getSpeakerName() {
        return speakerName;
    }

    public void setSpeakerName(String speakerName) {
        this.speakerName = speakerName;
    }

    public String getSpeakerJob() {
        return speakerJob;
    }

    public void setSpeakerJob(String speakerJob) {
        this.speakerJob = speakerJob;
    }

    public String getSpeakerHeadUrl() {
        return speakerHeadUrl;
    }

    public void setSpeakerHeadUrl(String speakerHeadUrl) {
        this.speakerHeadUrl = speakerHeadUrl;
    }

    public String getSpeakerDescr() {
        return speakerDescr;
    }

    public void setSpeakerDescr(String speakerDescr) {
        this.speakerDescr = speakerDescr;
    }

    public Date getInsertTime() {
        return insertTime;
    }

    public void setInsertTime(Date insertTime) {
        this.insertTime = insertTime;
    }

    public Date getUpdateTime() {
        return updateTime;
    }

    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }

    public MultipartFile getIcon() {
        return icon;
    }

    public void setIcon(MultipartFile icon) {
        this.icon = icon;
    }

    @Override
    public String toString() {
        return "SpeakerModel [id=" + id + ", speakerName=" + speakerName + ", speakerJob=" + speakerJob
                + ", speakerHeadUrl=" + speakerHeadUrl + ", speakerDescr=" + speakerDescr + ", insertTime=" + insertTime
                + ", updateTime=" + updateTime + "]";
    }

}

我这里为方便,只写了一种校验:校验输入的speakername的最小为2最大不超过5.我这里让参数校验不通过,传递到了另外一个页面上。
addError.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
    ${message}
</body>
</html>

如果参数校验不通过会跳转到这个jsp页面上面,给出提示信息。这些信息来源于。
CustomValidationMessage.properties文件

age.error=年龄在1100之间
hobby.error=爱好输入不正确'
name.error=姓名错误

这个东西,在配置校验框架的时候已经提到。
接着就是进行,校验工作。
我这里是将校验安排在了一个父类BaseController.java,和一个工具类BeanValidators.java里面。
而这样,只需要在controller层调用相应的方法即可
BeanValidators.java


package com.zhiyou100.video.util;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Validator;

/**
 * Validator(Hibernate Validator)工具类.
 * 
 * ConstraintViolation中包含propertyPath, message 和invalidValue等信息.
 * 提供了各种convert方法,适合不同的i18n需求: 1. List<String>, String内容为message 2.
 * List<String>, String内容为propertyPath + separator + message 3.
 * Map<propertyPath, message>
 * 
 */
public class BeanValidators {

    /**
     * 调用JSR303的validate方法, 验证失败时抛出ConstraintViolationException.
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public static void validateWithException(Validator validator, Object object, Class<?>... groups)
            throws ConstraintViolationException {
        Set constraintViolations = validator.validate(object, groups);
        if (!constraintViolations.isEmpty()) {
            throw new ConstraintViolationException(constraintViolations);
        }
    }

    /**
     * 辅助方法,
     * 转换ConstraintViolationException中的Set<ConstraintViolations>中为List<message>.
     */
    public static List<String> extractMessage(ConstraintViolationException e) {
        return extractMessage(e.getConstraintViolations());
    }

    /**
     * 辅助方法, 转换Set<ConstraintViolation>为List<message>
     */
    @SuppressWarnings("rawtypes")
    public static List<String> extractMessage(Set<? extends ConstraintViolation> constraintViolations) {
        List<String> errorMessages = new ArrayList<String>();
        for (ConstraintViolation violation : constraintViolations) {
            errorMessages.add(violation.getMessage());
        }
        return errorMessages;
    }

    /**
     * 辅助方法,
     * 转换ConstraintViolationException中的Set<ConstraintViolations>为Map<property,
     * message>.
     */
    public static Map<String, String> extractPropertyAndMessage(ConstraintViolationException e) {
        return extractPropertyAndMessage(e.getConstraintViolations());
    }

    /**
     * 辅助方法, 转换Set<ConstraintViolation>为Map<property, message>.
     */
    @SuppressWarnings("rawtypes")
    public static Map<String, String> extractPropertyAndMessage(
            Set<? extends ConstraintViolation> constraintViolations) {
        Map<String, String> errorMessages = new HashMap<String, String>();
        for (ConstraintViolation violation : constraintViolations) {
            errorMessages.put(violation.getPropertyPath().toString(), violation.getMessage());
        }
        return errorMessages;
    }

    /**
     * 辅助方法,
     * 转换ConstraintViolationException中的Set<ConstraintViolations>为List<propertyPath
     * message>.
     */
    public static List<String> extractPropertyAndMessageAsList(ConstraintViolationException e) {
        return extractPropertyAndMessageAsList(e.getConstraintViolations(), " ");
    }

    /**
     * 辅助方法, 转换Set<ConstraintViolations>为List<propertyPath message>.
     */
    @SuppressWarnings("rawtypes")
    public static List<String> extractPropertyAndMessageAsList(
            Set<? extends ConstraintViolation> constraintViolations) {
        return extractPropertyAndMessageAsList(constraintViolations, " ");
    }

    /**
     * 1234 辅助方法,
     * 转换ConstraintViolationException中的Set<ConstraintViolations>为List<propertyPath
     * +separator+ message>.
     */
    public static List<String> extractPropertyAndMessageAsList(ConstraintViolationException e, String separator) {
        return extractPropertyAndMessageAsList(e.getConstraintViolations(), separator);
    }

    /**
     * 辅助方法, 转换Set<ConstraintViolation>为List<propertyPath +separator+ message>.
     */
    @SuppressWarnings("rawtypes")
    public static List<String> extractPropertyAndMessageAsList(Set<? extends ConstraintViolation> constraintViolations,
            String separator) {
        List<String> errorMessages = new ArrayList<String>();
        for (ConstraintViolation violation : constraintViolations) {
            try {
                errorMessages.add(violation.getPropertyPath() + separator
                        + new String(violation.getMessage().getBytes("ISO-8859-1"), "UTF-8"));
            } catch (UnsupportedEncodingException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        return errorMessages;
    }
}

BaseController.java

package com.zhiyou100.video.controller;

import java.beans.PropertyEditorSupport;
import java.sql.Date;
import java.sql.Timestamp;
import java.util.List;

import javax.validation.ConstraintViolationException;
import javax.validation.Validator;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.validation.BindException;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.InitBinder;

import com.zhiyou100.video.util.BeanValidators;
import com.zhiyou100.video.util.DateUtil;

public class BaseController {
    /*
     * 作业 io nio 今天讲的内容
     * 
     * 明天讲mybatis
     * 
     */

    @Autowired
    protected Validator validator;

    /**
     * 初始化数据绑定 1. 将所有传递进来的String进行HTML编码,防止XSS攻击 2. 将字段中Date类型转换为String类型
     */
    @InitBinder
    protected void initBinder(WebDataBinder binder) {

        // 任何转换器都不配置 按格式输入(yyyy-MM-dd,yyyy-MM-dd HH:mm:ss)不会报错 否则400

        // 转换器配置的两种方式掌握

        // 如果配置了参数校验springmvc 参数绑定如果出现异常就不会报400错误了 但是不能正常赋值

        /*
         * binder.registerCustomEditor(Date.class, new PropertyEditorSupport() {
         * 
         * @Override public void setAsText(String text) {
         * setValue(DateUtil.stringToDateyy(text));
         * 
         * }
         * 
         * });
         */

        binder.registerCustomEditor(Timestamp.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) {
                setValue(new Timestamp(DateUtil.stringToDate(text).getTime()));

            }

        });

    }

    /**
     * 异常处理
     * 
     * @return
     */
    @ExceptionHandler({ BindException.class, IllegalStateException.class })
    public String bindException() {

        return "/error/400";

    }
    /*
     * 权限异常
     * 
     * 业务异常 都可以在这处理
     * 
     * 
     * 
     */

    /**
     * 服务端参数有效性验证
     * 
     * @param object
     *            验证的实体对象
     * @param groups
     *            验证组
     * @return 验证成功:返回true;严重失败:将错误信息添加到 message 中
     */
    protected boolean beanValidator(Model model, Object object, Class<?>... groups) {
        try {

            BeanValidators.validateWithException(validator, object, groups);
        } catch (ConstraintViolationException ex) {
            List<String> list = BeanValidators.extractPropertyAndMessageAsList(ex, ": ");
            list.add(0, "数据验证失败:");
            addMessage(model, list.toArray(new String[] {}));
            return false;
        }
        return true;
    }

    /**
     * 服务端参数有效性验证
     * 
     * @param object
     *            验证的实体对象
     * @param groups
     *            验证组,不传入此参数时,同@Valid注解验证
     * @return 验证成功:继续执行;验证失败:抛出异常跳转400页面。
     */
    protected void beanValidator(Object object, Class<?>... groups) {
        BeanValidators.validateWithException(validator, object, groups);
    }

    /**
     * 添加Model消息
     * 
     * @param message
     */
    protected void addMessage(Model model, String... messages) {
        StringBuilder sb = new StringBuilder();
        for (String message : messages) {
            sb.append(message).append(messages.length > 1 ? "<br/>" : "");
        }
        model.addAttribute("message", sb.toString());
    }

}

配置好这两个类,就可以在controller层进行校验操作:
这里写图片描述

if (!this.beanValidator(model, speaker, ValidateGroup1.class)) {
            return "/admin/speaker/addError";
        }

这个就是核心代码,如果参数为真,那么就执行if里面的return操作,返回到一个jsp页面上显示效果如下:
这里写图片描述
源码我稍后上传GitHub之后,再补个链接出来。有什么问题,或者不对的地方,请指出来,共同进步。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

踏雪须眉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值