springboot 统一格式数据返回、异常捕获 + 数据验证

springboot 验证包含两中一类为JSR-303验证框架,另一个为hibernate-validator在前一个基础上扩展的.

引入spring-boot-starter-web时 都自动引入,无需额外引入包. 


定义全局异常捕获类: GlobalExceptionHandler.java

package com.example.springboot.exception;

import com.example.springboot.response.ReturnEnum;
import com.example.springboot.response.ReturnMsg;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolationException;
import java.util.List;

@RestControllerAdvice
public class GlobalExceptionHandler {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 处理请求对象属性不满足校验规则的异常信息
     *
     * @param request
     * @param exception
     * @return
     * @throws Exception
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public ReturnMsg exception(HttpServletRequest request, MethodArgumentNotValidException exception) {
        BindingResult result = exception.getBindingResult();
        final List<FieldError> fieldErrors = result.getFieldErrors();
        StringBuilder builder = new StringBuilder();

        for (FieldError error : fieldErrors) {
            builder.append(error.getDefaultMessage() + "\n");
        }
        return new ReturnMsg(ReturnEnum.FAIL, builder.toString());
    }

    /**
     * 处理请求单个参数不满足校验规则的异常信息
     *
     * @param request
     * @param exception
     * @return
     * @throws Exception
     */
    @ExceptionHandler(value = ConstraintViolationException.class)
    public ReturnMsg constraintViolationExceptionHandler(HttpServletRequest request, ConstraintViolationException exception) {
        logger.info(exception.getMessage());
        return new ReturnMsg(ReturnEnum.FAIL, exception.getMessage());
    }


    /**
     * 处理未定义的其他异常信息
     *
     * @param request
     * @param exception
     * @return
     */
    @ExceptionHandler(value = Exception.class)
    public ReturnMsg exceptionHandler(HttpServletRequest request, Exception exception) {
        logger.error(exception.getMessage());
        return new ReturnMsg(ReturnEnum.FAIL, exception.getMessage());
    }
}

定义统一返回数据格式

package com.example.springboot.response;

public enum ReturnEnum {

    UN_LOGIN(-1, "未登录"),
    FAIL(0, "系统异常,请联系管理员"),
    SUCCESS(1, "操作成功");


    private Integer code;

    private String message;


    ReturnEnum(Integer code, String message) {
        this.code = code;
        this.message = message;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}


package com.example.springboot.response;

import com.alibaba.fastjson.annotation.JSONField;
import org.springframework.util.StringUtils;

public class ReturnMsg {

    private boolean status;
    @JSONField(ordinal = 1)
    private Integer code;
    @JSONField(ordinal = 2)
    private String msg;
    @JSONField(ordinal = 3)
    private Object data;
    @JSONField(serialize = false)
    private ReturnEnum returnEnum;


    public ReturnMsg() {
        status = true;
        this.returnEnum = ReturnEnum.SUCCESS;
    }

    public ReturnMsg(ReturnEnum returnEnum) {
        this.returnEnum = returnEnum;
    }

    public ReturnMsg(ReturnEnum returnEnum, String msg) {
        this.msg = msg;
        this.returnEnum = returnEnum;
    }

    public Boolean getStatus() {
        return status;
    }

    public void setStatus(Boolean status) {
        this.status = status;
    }

    public Integer getCode() {
        if (returnEnum != null) {
            return returnEnum.getCode();
        }
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMsg() {
        if (!StringUtils.isEmpty(msg)) {
            return msg;
        } else if (returnEnum != null) {
            return returnEnum.getMessage();
        }
        return "";
    }

    public void setMsg(String message) {
        this.msg = message;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }
}

一、传入对象校验

        修改entity: User.java   username 添加不为空校验

package com.example.springboot.entity;

import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Size;

public class User {

    private Long id;
    @NotEmpty
    @Size(min = 2, max = 20, message = "用户名长度为2-20之间")
    private String username;
    private String password;

    public Long getId() {
        return id;
    }

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

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

修改controller: UserController.java   添加save方法

package com.example.springboot.controller;

import com.example.springboot.entity.User;
import com.example.springboot.service.IUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/user")
public class UserController {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private IUserService userService;

    @GetMapping("/get")
    public User getUser(Long id) {
        return userService.get(id);
    }


    
  @PostMapping("/save")
  public ReturnMsg save(@RequestBody User user) {
     userService.save(user);
     return new ReturnMsg();
 }
}

    


启动项目

访问地址:http://127.0.0.1:8000/user/save


    

二、基本类型数据校验   UserController.java   类上 @Validated注解  (基础数据校验必须添加此注解

方法find 参数添加校验@Size(min = 2,max = 20)

package com.example.springboot.controller;

import com.example.springboot.entity.User;
import com.example.springboot.response.ReturnMsg;
import com.example.springboot.service.IUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import javax.validation.constraints.Size;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/user")
@Validated
public class UserController {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private IUserService userService;

    @GetMapping("/get")
    public User getUser(Long id) {
        return userService.get(id);
    }


    @PostMapping("/save")
    public ReturnMsg save(@RequestBody @Valid User user) {
        userService.save(user);
        return new ReturnMsg();
    }

    @GetMapping("/find")
    public ReturnMsg find(@Size(min = 2, max = 20) String name) {
        Map<String, String> whereMap = new HashMap<String, String>();
        whereMap.put("username", name);
        List<User> users = userService.find(whereMap);
        ReturnMsg result = new ReturnMsg();
        result.setData(users);
        return result;
    }
}

访问地址:http://127.0.0.1:8000/user/find?name=1



三、校验提示与的统一配置和国际化

   validator 默认会加载resource目录下的ValidationMessages.properties文件,在文件中配置相关信息

ValidationMessages.properties

user.name.notNull=用户名不能为空
user.name.length=用户名长度必须在2-30之间

调用时:

User.java

package com.example.demo.entity;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

public class User {


    private Long id;
    @NotNull(message = "{user.name.notNull}")
    @Size(min=2, max=30,message ="{user.name.length}" )
    private String username;
    private String password;

    public Long getId(){
      return id;
    }
    public void setId(Long id){
      this.id = id;
    }
    public String getUsername(){
      return username;
    }
    public void setUsername(String username){
      this.username = username;
    }
    public String getPassword(){
      return password;
    }
    public void setPassword(String password){
      this.password = password;
    }
}

这样配置后,会自动获取配置文件中的信息提示


发布了62 篇原创文章 · 获赞 3 · 访问量 2万+
展开阅读全文

关于SpringBoot+myBatis实体的字段返回前端后格式变化的问题

03-08

我的架构是 springBoot(1.5.9)+myBatis ,连接池用的是阿里的druid,以下是配置信息: 启动类: import java.sql.SQLException; import java.util.HashMap; import java.util.Map; import org.apache.ibatis.plugin.Interceptor; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.druid.support.http.StatViewServlet; import com.alibaba.druid.support.http.WebStatFilter; import com.github.pagehelper.PageHelper; /** * * @author wangxufei * */ @SpringBootApplication @EnableAutoConfiguration @MapperScan("com.mofangge.mapper") public class MfgAgencyApplication { @Value("${spring.datasource.username}") private String userName; @Value("${spring.datasource.password}") private String password; @Value("${spring.datasource.url}") private String url; @Bean public ServletRegistrationBean druidServletRegistrationBean() { ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(); servletRegistrationBean.setServlet(new StatViewServlet()); servletRegistrationBean.addUrlMappings("/druid/*"); return servletRegistrationBean; } /** * 注册DruidFilter拦截 * * @return */ @Bean public FilterRegistrationBean duridFilterRegistrationBean() { FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); filterRegistrationBean.setFilter(new WebStatFilter()); Map<String, String> initParams = new HashMap<String, String>(); // 设置忽略请求 initParams.put("exclusions", "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*"); filterRegistrationBean.setInitParameters(initParams); filterRegistrationBean.addUrlPatterns("/*"); return filterRegistrationBean; } /** * 配置DruidDataSource * * @return * @throws SQLException */ @Bean public DruidDataSource druidDataSource() throws SQLException { DruidDataSource druidDataSource = new DruidDataSource(); druidDataSource.setUsername(userName); druidDataSource.setPassword(password); druidDataSource.setUrl(url); druidDataSource.setMaxActive(100); druidDataSource.setFilters("stat,wall"); druidDataSource.setInitialSize(10); return druidDataSource; } @Bean public SqlSessionFactory sqlSessionFactoryBean() throws Exception { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(druidDataSource()); PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath:/mybatis/*.xml")); sqlSessionFactoryBean.setTypeAliasesPackage("com.mofangge.model,com.mofangge.dto"); Interceptor[] interceptors = {new PageHelper()}; sqlSessionFactoryBean.setPlugins(interceptors); return sqlSessionFactoryBean.getObject(); } public static void main(String[] args) { SpringApplication.run(MfgAgencyApplication.class, args); } } properties文件: #server #server.port=8080 server.port=8081 #server.port=8099 #server.servlet-path=/agency ## log logging.level.org.springframework.web: error logging.level.com.mofangge:info logging.file:mfg-agency.log # JPA (JpaBaseConfiguration, HibernateJpaAutoConfiguration) spring.data.jpa.repositories.enabled=true spring.jpa.database=mysql spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect spring.jpa.generate-ddl=false spring.jpa.hibernate.ddl-auto=none spring.jpa.open-in-view=true spring.jpa.show-sql=false 现在遇到的问题是: 实体类中的格式 返回到页面后,字段格式变化了,如下图: 实体: ![图片说明](https://img-ask.csdn.net/upload/201803/08/1520520274_791208.png) 数据库: ![图片说明](https://img-ask.csdn.net/upload/201803/08/1520520307_858101.png) 返回到页面后的值(controller注解了@RestController): ![图片说明](https://img-ask.csdn.net/upload/201803/08/1520520354_282352.png) 第二个字母 应该是大写C 结果变成了小写c。 而且有个现象是: 如果你的字段是 sName 那么前端拿到的是sname 如果你的字段是seName 那么前端拿到的就是seName **不会变化** 也就是说 如果驼峰前字母是2个或2个以上 他就按照原来的格式了,不知道具体是什么原因,求大佬教导。 ps: 我试过很多种方法,只有一种有效果 就是给字段注解 @JsonProperty 但是这种方法会造成我的返回值里会有2个 sname 一个是sname 一个是sName 2个字段都是同样的值 给我一种复制的感觉。。 问答

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览