springboot+后端校验+实体类映射工具+全局异常捕获+返回值封装

一.Java 实体映射工具 MapStruct

声明:
1、DO(业务实体对象),DTO(数据传输对象)。
2、我的代码中用到了 Lombok ,不了解的可以自行了解一下,了解的忽略这条就好。

在一个成熟的工程中,尤其是现在的分布式系统中,应用与应用之间,还有单独的应用细分模块之后,DO 一般不会让外部依赖,这时候需要在提供对外接口的模块里放 DTO 用于对象传输,也即是 DO 对象对内,DTO对象对外,DTO 可以根据业务需要变更,并不需要映射 DO 的全部属性。

这种 对象与对象之间的互相转换,就需要有一个专门用来解决转换问题的工具,毕竟每一个字段都 get/set 会很麻烦。

MapStruct 就是这样的一个属性映射工具,只需要定义一个 Mapper 接口,MapStruct 就会自动实现这个映射接口,避免了复杂繁琐的映射实现。MapStruct官网地址: http://mapstruct.org/

1.pom文件依赖

<!--实体类与Model类转换的利器-->
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>1.3.0.Final</version>
        </dependency>

2.定义vo实体与dto传输对象

@NoArgsConstructor
@AllArgsConstructor
@Data
public class Person {
    private Long id;
    private String name;
    private String email;
    private Date birthday;
    private User user;
}

@NoArgsConstructor
@AllArgsConstructor
@Data
public class User {
    private Integer age;
}

@NoArgsConstructor
@AllArgsConstructor
@Data
public class PersonDTO {
    private Long id;
    private String name;
    /**
     * 对应 Person.user.age
     */
    private Integer age;
    private String email;
    /**
     * 与 DO 里面的字段名称(birthDay)不一致
     */
    private Date birth;
    /**
     * 对 DO 里面的字段(birthDay)进行拓展,dateFormat 的形式
     */
    private String birthDateFormat;
    /**
     * 对 DO 里面的字段(birthDay)进行拓展,expression 的形式
     */
    private String birthExpressionFormat;

}

3. Mapper 接口

package com.zsc.shixun.model.article;

import com.zsc.shixun.entity.Article;
import org.mapstruct.Mapper;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * <p>
 *
 * </p>
 *
 * @author ZWYZY
 * @since 2020/6/18
 */
@Service
@Mapper(componentModel = "spring")
public interface ArticleMapping {

    /**
     * @param article
     * @return
     */
    ArticleVO entityToVo(Article article);

    /**要实现列表转换必须先实现上面的映射
     * entity to vo
     *
     * @param articleList
     * @return
     */
    List<ArticleVO> entitysToVos(List<Article> articleList);
}

4. 编译MapStruct之后,手工编译

<!--实体转vo必要的配置-->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.5.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <annotationProcessorPaths>
                        <path>
                            <groupId>org.mapstruct</groupId>
                            <artifactId>mapstruct-processor</artifactId>
                            <version>1.3.0.Final</version>
                        </path>
                        <path>
                            <!--实体与dto使用了lombok插件,必须添加这个-->
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                            <version>1.18.10</version>
                        </path>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>

会自动在 target/classes 下生成对应的实现类

5.注解关键词

@Mapper //只有在接口加上这个注解, MapStruct 才会去实现该接口
    @Mapper //里有个 componentModel 属性,主要是指定实现类的类型,一般用到两个
    default//默认,可以通过 Mappers.getMapper(Class) 方式获取实例对象
    spring://在接口的实现类上自动添加注解 @Component,可通过 @Autowired 方式注入
@Mapping//属性映射,若源对象属性与目标对象名字一致,会自动映射对应属性
    source://源属性
    target://目标属性
    dateFormat://String 到 Date 日期之间相互转换,通过 SimpleDateFormat,该值为 SimpleDateFormat              的日期格式
    ignore: //忽略这个字段
@Mappings//配置多个@Mapping
@MappingTarget //用于更新已有对象
@InheritConfiguration //用于继承配置

二.后端验证

1.pom文件依赖

 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>

2.实体类添加校验

package demo.rest;
 
import lombok.Data;
 
import javax.validation.constraints.NotNull;
 
/**
 * description:
 * author: yangzihe
 * date: 2019-05-16 15:50
 **/
@Data
public class User {
 
    @NotNull(message = "用户名不可为空")
    private String name;
 
    @NotNull(message = "密码不可为空")
    private String password;
 
    
}

3.控制层添加校验

@RestController
public class DemoController {
 
    @GetMapping("valid")
    public String test1(@Validated User user, BindingResult result) {//@Valid注解也可
        System.out.println(user);
        System.out.println("result=" + result);
        if (result.hasErrors()) {
            StringBuilder sb = new StringBuilder();
            for (ObjectError error : result.getAllErrors()) {
                sb.append(error.getDefaultMessage() + ";");
            }
            System.out.println(sb.toString());
            return sb.toString();
        }
        return "success";
    }
 
}

注意:如果要校验的不是java bean 要在控制器添加@Validated 而不是在参数旁加,否则会失效

img

参考资料: 1.嵌套验证:https://blog.csdn.net/weixin_33853794/article/details/85992438

​ 2.常用注解: https://blog.csdn.net/weixin_34234829/article/details/93407285

三.全局异常处理及返回值封装

1.返回值封装

package com.zsc.shixun.common;

import lombok.NoArgsConstructor;
import org.springframework.stereotype.Component;

/**
 * <p>
 *     返回值封装类
 * </p>
 *
 * @author Administrator
 */
@Component
@NoArgsConstructor
public class CommonResult<T> {
    public Integer getCode() {
        return code;
    }

    public String getMsg() {
        return msg;
    }

    public Object getData() {
        return data;
    }

    public CommonResult(Integer code, String msg, T data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    private Integer code;

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

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

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

    private String msg;
    private T data;
    public CommonResult(Integer code, String msg) {
        this.code = code;
        this.msg = msg;
    }
    public CommonResult(ResultCode code) {
        this.code = code.getCode();
        this.msg = code.getMsg();
    }
}

2.返回值异常状态码

package com.zsc.shixun.common;

import lombok.AllArgsConstructor;
import lombok.Getter;

/**
 * <p>
 * 响应码及描述常量
 * </p>
 *
 * @author ZWYZY
 * @since 2020/4/21
 */
@Getter
@AllArgsConstructor
public enum ResultCode {
    //ctrl+shift+u ,小写变大写
    LIKE_CLICK_FAIL(900001,"点赞失败"),
    COMMENT_DELETE_FAIL(800005,"不好意思,删除评论失败哦,亲"),
    USER_DELETE_YOURSELF_FAIL(700004,"不好意思,你自己不能删除自己哦,亲"),
    USER_MANAGE_INSERT_FAIL(700003,"不好意思,管理员创建失败哦,亲"),
    USER_MANAGE_DELETE_FAIL(700002,"不好意思,用户删除失败哦,亲"),
    USER_MANAGE_UPDATE_FAIL(700001,"不好意思,用户更改失败哦,亲"),
    COLLECT_HAS_EXIST(600004,"不好意思,已有该收藏夹类型哦,亲"),
    COLLECT_INSERT_FAIL(600003,"不好意思,收藏夹创建失败哦,亲"),
    COLLECT_DELETE_FAIL(600002,"不好意思,收藏夹删除失败哦,亲"),
    COLLECT_UPDATE_FAIL(600001,"不好意思,收藏夹更改失败哦,亲"),
    TYPE_HAS_EXIST(500004,"不好意思,已有该文章类型了哦,亲"),
    TYPE_INSERT_FAIL(500003,"不好意思,类型创建失败哦,亲"),
    TYPE_DELETE_FAIL(500002,"不好意思,类型删除失败哦,亲"),
    TYPE_UPDATE_FAIL(500001,"不好意思,类型更改失败哦,亲"),
    ARTICLE_INSERT_FAIL(400003,"不好意思,创建文章失败哦,亲"),
    ARTICLE_DELETE_FAIL(400002,"不好意思,文章删除失败哦,亲"),
    ARTICLE_UPDATE_FAIL(400001,"不好意思,文章修改失败哦,亲"),
    NOTICE_DELETE_FAIL(300003,"不好意思,公告删除失败哦,亲"),
    NOTICE_INSERT_FAIL(300002,"不好意思,公告插入失败哦,亲"),
    NOTICE_UPDATE_FAIL(300001,"不好意思,公告更改失败,亲"),
    USER_UPDATE_FAIL(200002,"本次操作未能成功,亲!"),
    FILE_UPLOAD_ERROR(200001,"文件上传失败"),
    AUTHORITY_HAS_EXIST(403,"亲,当前操作没有权限哦!"),
    USERNAME_HAS_EXIST(100002,"用户名太受欢迎了,请换一个吧,亲"),
    USER_HAS_EXIST(100001,"邮箱已注册"),
    EXCEL_NOT_DATA(-7,"当前没数据"),
    USER_NOT_FOUND(10000, "用户不存在"),
    ERROR(-1, "未知错误"),
    SUCCESS(200, "响应成功"),
    CHANGE(1, "改变成功"),
    CHANGE_NOT(0, "改变失败"),
    EMAIL_NOT_FOUND(10000,"该邮箱还没注册"),
    DATA_ERROR(-2, "输入数据错误"),
    USER_PASSWORD_NOT_FOUND(4001001, "用户名密码不匹配"),
    USER_BAN(4001002, "该用户已经被禁用请联系管理员"),
    CODE_NULL(4001003, "验证码失效请重新获取"),
    CODE_ERROR(4001004, "请输入正确的验证码"),
    USERNAME_HAS(4001005, "该账号已被占用"),
    REGIST_ERROR(4001006, "注册失败"),
    PHONE_NOT_TRUE(4001007, "手机号格式错误"),
    SEND_MAX(4001008, "当日发送已上限"),
    USER_HAS_LOGIN(4001009,"用户已经登录无需再登录"),
    DATABASE_DEPENDENT_ERROR(-3, "数据库数据之间依赖错误"),
    File_ERROR(-4, "上传的文件错误"),
    EXCELDATA_ERROR(-5, "文件内容错误,操作全部取消"),
    DATA_NULL(-6, "查询的信息为空");
    private Integer code;
    private String msg;
}

3.返回值异常工具类

package com.zsc.shixun.common;

/**
 * <p>
 *  返回值封装工具类
 * </p>
 *
 * @author ZWYZY
 * @since 2020/4/21
 */
public class ResultUtil {
    public static<T> CommonResult<T> success(T t) {
        CommonResult<T> result = new CommonResult<>();
        result.setCode(ResultCode.SUCCESS.getCode());
        result.setMsg(ResultCode.SUCCESS.getMsg());
        result.setData(t);
        return result;
    }


    public static CommonResult success() {
        return success(null);
    }

    public static<T> CommonResult<T> error(Integer code, String msg) {
        CommonResult<T> result = new CommonResult<>();
        result.setCode(code);
        result.setMsg(msg);
        result.setData(null);
        return result;
    }

    public static<T> CommonResult<Object> error(Integer code, String msg, String data) {
        CommonResult<Object> result = new CommonResult<>();
        result.setCode(code);
        result.setMsg(msg);
        result.setData(data);
        return result;
    }

    public static<T> CommonResult<T> error(ResultCode resultCode) {
        CommonResult<T> result = new CommonResult<>();
        result.setCode(resultCode.getCode());
        result.setMsg(resultCode.getMsg());
        result.setData(null);
        return result;
    }



}

4.全局异常捕获处理

package com.zsc.shixun.exception;


import com.zsc.shixun.common.CommonResult;
import com.zsc.shixun.common.ResultUtil;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.stream.Collectors;

/**
 * @author winner
 * @description: ZWYZY 定义的全局异常处理
 * @date 2020/4/14
 */
@Configuration
@RestControllerAdvice
public class ErrorExceptionHandler<T> {

    /**ApiException为自定义运行时异常类子类
     * api异常处理返回json封装字符串对象
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = ApiException.class)
    public CommonResult<Object> paramError(ApiException e) {
        return ResultUtil.error(e.getCode(), e.getMessage(), e.getData());
    }


    /**
     * 校验异常处理
     *
     * @param e
     * @return
     */
    @ExceptionHandler(BindException.class)
    @ResponseBody
    public CommonResult bindExceptionHandler(BindException e) {
        String message = e.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining(","));
        return ResultUtil.error(400, message);
    }

    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    @ResponseBody
    public CommonResult methodArgumentTypeMismatchExceptionHandler(MethodArgumentTypeMismatchException e) {
//        String message = e.getLocalizedMessage().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining());
        return ResultUtil.error(400, "数据验证错误");
    }


    /**
     * 校验异常处理
     *
     * @param e
     * @return
     */
    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseBody
    public CommonResult constraintViolationExceptionHandler(ConstraintViolationException e) {
        String message = e.getConstraintViolations().stream().map(ConstraintViolation::getMessage).collect(Collectors.joining());
        return ResultUtil.error(400, message);
    }


    /**
     * 校验异常处理
     *
     * @param e
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public CommonResult methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
        String message = e.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining());
        return ResultUtil.error(400, message);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值