美文网首页
[前端学java10-SpringBoot实战] bean赋值转

[前端学java10-SpringBoot实战] bean赋值转

作者: woow_wu7 | 来源:发表于2021-10-17 11:58 被阅读0次

    导航

    [react] Hooks

    [封装01-设计模式] 设计原则 和 工厂模式(简单抽象方法) 适配器模式 装饰器模式
    [封装02-设计模式] 命令模式 享元模式 组合模式 代理模式

    [React 从零实践01-后台] 代码分割
    [React 从零实践02-后台] 权限控制
    [React 从零实践03-后台] 自定义hooks
    [React 从零实践04-后台] docker-compose 部署react+egg+nginx+mysql
    [React 从零实践05-后台] Gitlab-CI使用Docker自动化部署

    [源码-webpack01-前置知识] AST抽象语法树
    [源码-webpack02-前置知识] Tapable
    [源码-webpack03] 手写webpack - compiler简单编译流程
    [源码] Redux React-Redux01
    [源码] axios
    [源码] vuex
    [源码-vue01] data响应式 和 初始化渲染
    [源码-vue02] computed 响应式 - 初始化,访问,更新过程
    [源码-vue03] watch 侦听属性 - 初始化和更新
    [源码-vue04] Vue.set 和 vm.$set
    [源码-vue05] Vue.extend

    [源码-vue06] Vue.nextTick 和 vm.$nextTick
    [部署01] Nginx
    [部署02] Docker 部署vue项目
    [部署03] gitlab-CI

    [数据结构和算法01] 二分查找和排序

    [深入01] 执行上下文
    [深入02] 原型链
    [深入03] 继承
    [深入04] 事件循环
    [深入05] 柯里化 偏函数 函数记忆
    [深入06] 隐式转换 和 运算符
    [深入07] 浏览器缓存机制(http缓存机制)
    [深入08] 前端安全
    [深入09] 深浅拷贝
    [深入10] Debounce Throttle
    [深入11] 前端路由
    [深入12] 前端模块化
    [深入13] 观察者模式 发布订阅模式 双向数据绑定
    [深入14] canvas
    [深入15] webSocket
    [深入16] webpack
    [深入17] http 和 https
    [深入18] CSS-interview
    [深入19] 手写Promise
    [深入20] 手写函数
    [深入21] 数据结构和算法 - 二分查找和排序
    [深入22] js和v8垃圾回收机制
    [深入23] JS设计模式 - 代理,策略,单例

    [前端学java01-SpringBoot实战] 环境配置和HelloWorld服务
    [前端学java02-SpringBoot实战] mybatis + mysql 实现歌曲增删改查
    [前端学java03-SpringBoot实战] lombok,日志,部署
    [前端学java04-SpringBoot实战] 静态资源 + 拦截器 + 前后端文件上传
    [前端学java05-SpringBoot实战] 常用注解 + redis实现统计功能
    [前端学java06-SpringBoot实战] 注入 + Swagger2 3.0 + 单元测试JUnit5
    [前端学java07-SpringBoot实战] IOC扫描器 + 事务 + Jackson
    [前端学java08-SpringBoot实战总结1-7] 阶段性总结
    [前端学java09-SpringBoot实战] 多模块配置 + Mybatis-plus + 单多模块打包部署
    [前端学java010-SpringBoot实战] bean赋值转换 + 参数校验 + 全局异常处理

    (一) 前置知识

    (1) 一些单词

    scalar 纯量
    quote 引用 
    // single quotes 单引号
    // double quotes 双引号
    palette 调色板
    
    implicit 隐式,含蓄
    hibernate 冬眠 休眠
    Advice 建议 通知
    
    persistent 持久的,执着的
    profile 概述 简介 环境 // spring.profile
    assert 断言
    future 未来 将来 // feature 特征
    
    digits 数字 位数
    integer 整数
    fraction 小数
    
    advice 建议 通知 // @ControllerAdvice
    exception 异常
    abstract 抽象的
    
    public 任何对象都可以访问
    private 只能被自己的方法访问,子类和其他任何类都不能访问
    protected 只能被自己和子类访问,其他类型的类不能访问
    final 不能被继承
    static 可以通过类自身和实例来调用
    abstract 抽象类,不自己实现方法,子类需要实现方法
    

    (2) @ConfigurationProperties + @Component 实现配置绑定

    • 注意区分 @Component 和 @Configuration 的区别
    bean
    -------
    // @Component + @ConfigurationProperties 两个组件配合,用来实现 ( 配置绑定 ),绑定application.properties或者application.yml文件中的变量
    // @Component 把组件注册到容器中,即向IOC中添加组件 => 必须在容器中的组件,才能拥有spring提供的强大功能,即容器中的组件才能使用 @ConfigurationProperties
    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @Component // 向IOC中添加组件
    @ConfigurationProperties(prefix = "myapp") // prefix 即 application.yml中的前缀
    public class TestConfigurationPropertiesAndComponentBean {
        String author;
        String email;
    }
    
    
    application.yml
    -------
    myapp: # 通过 @ConfigurationProperties(prefix = "myapp") 指定
      author: woow_wu7
      email: woow.wu7@gmail.com
    

    (3) 复习拦截器 - HandlerInterceptor + WebMvcConfigurer

    (1)
    HandlerInterceptor
      - preHandle => controller目标方法执行前
      - postHandle => controller目标方法执行后
      - afterCompletion => 页面渲染完后
      
    (2)
    具体流程
    1. 在 ( interceptor ) 文件夹中添加拦截器,并实现 ( HandlerInterceptor ) 接口,并在 ( preHandle ) 等中处理逻辑
    2. 在 ( config ) 文件夹中通过实现 ( WebMvcConfigurer ) 接口,然后添加拦截规则
    

    (4) 复习 swagger

    1. 安装
    <!-- Swagger -->
    <!-- 自动生成 ( 接口文档 ) 及 ( 自测工具 ) -->
    <!-- Swagger2 3.0 只需要 ( springfox-boot-starter ) 就可以了 -->
    <!-- Swagger2 2.x 则需要 ( springfox-swagger2 ) 和 ( springfox-swagger-ui )-->
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-boot-starter</artifactId>
        <version>3.0.0</version>
    </dependency>
    
    
    2. 编写配置类
    src/main/java/com.example.demo/config/Swagger2Config.java
    -------
    @Configuration // 标注当前类是一个启动类,即项目启动时就要去加载了
    @EnableSwagger2 // 开启 Swagger2 的配置
    public class Swagger2Config {
        @Bean // 把该组件添加到IOC容器中
        public Docket createRestApi() {
            return new Docket(DocumentationType.SWAGGER_2)
                    .apiInfo(apiInfo())
                    .select()
                    // Swagger2进行包扫描,扫描 controller,这里填写 controller 的文件夹全路径
                    .apis(RequestHandlerSelectors.basePackage("com.example.demo.controller"))
                    .paths(PathSelectors.any())
                    .build();
        }
        private ApiInfo apiInfo() {
            return new ApiInfoBuilder()
                    // 标题
                    .title("react-admin-java-api 使用Swagger2构建RESTful APIs")
                    // 描述
                    .description("react-admin-java-api Swagger2的接口文档")
                    // 作者信息
                    .contact(new Contact("woow_wu7", "https://github.com/woow-wu7/7-react-admin-java", "woow_wu7@gmail.com"))
                    // 服务网址
                    .termsOfServiceUrl("http://120.53.220.141:81/admin-home")
                    .version("1.0")
                    .build();
        }
    }
    
    
    3. 
    访问 http://localhost:7000/swagger-ui/index.html
    即是: 项目启动地址/swagger-ui/index.html
    如果是远程部署后访问地址:服务器地址/swagger-ui/index.html
    

    (5) 复习一些前端的知识

    (1) trim
    - 字符串的 ( trim ) 方法用来去除 ( 字符串 ) 两端的空格,返回一个 ( 新的字符串 ),不改变原字符串
    
    (2) git rm -r --cached 文件夹或者文件
    - 比如:git rm -r --cached dist
    - 表示:把 ( 当前dist ) 的 ( 跟踪记录删除 ),但是 ( 工作区的dist文件夹还是存在 )
    - git rm 
      - 同时从 ( 工作区和索引 ) 中删除文件,即本地文件也被删除了
    - git rm --cached
      - 从 ( 索引中删除 ) 文件,本地文件还是存在,但该文件不被版本所控制了
    - git rm -r
      - 上面的 -r 是 ( recursive ) 递归的意思
      - 总的表示 递归的删除
    

    (6) 多模块配置注意的问题

    • 关于mybatis的xml方式配置
      • mapper模块
        • resources/maybaits/mybatis-config.xmlmybatis/xxx.xml 是在 mapper 模块配置的
      • controller模块
        • 但是关于mybatis的配置文件指定,是在 controller 模块中的 application.yml 文件中配置的,因为在 controller模块中才具有启动类Application

    (7) public private protected static final abstract

    • public
      • 公共访问控制符
      • 将一个类声明为 ( 公共类或方法或属性 ),可以 ( 被任何对象访问 )
      • 一个程序的主要类一定是公共类
    • protected
      • 保护访问控制符
      • 只允许自己和子类访问,其他类型的类不能访问
    • private
      • 私有访问控制符
      • 只允许自己类的方法访问,其他类(包括子类)的方法都不能访问
    • abstract
      • 将一个类声明为 ( 抽象类 ),没有实现的方法,需要子类实现
      • final和abstract不能同时出现
    • final
      • 将一个类声明为 ( 非继承类 ),表示该类 ( 不能被其他类继承 )
      • final和abstract不能同时出现
    • static
      • 修饰的方法和变量,既可以通过 ( 类来调用 ),也可以通过 ( 实例对象调用 )
      • 如果没有通过static修饰,则该类必须先实例化,然后再通过实例对象调用

    (8) java异常分类 - Throwable + Error + Exception

    image.png

    (9) java中的枚举enum类型

    • java中枚举是一种特殊的类,一般用来表示 ( 一组常量 )
    // 枚举 - enum
    // CustomExceptionType - 自定义 异常枚举类型
    
    public enum CustomExceptionType {
        CLIENT_ERROR(400, "客户端错误"),
        SERVICE_ERROR(500, "服务端错误"),
        OTHER_ERROR(999, "未知错误");
    
        private String desc; // 异常描述
        private int code; // 异常状态码
    
        CustomExceptionType(int code, String desc) { // 有参构造器
            this.code = code;
            this.desc = desc;
        }
    
        public int getCode() { // getter
            return code;
        }
    
        public String getDesc() { // setter
            return desc;
        }
    }
    

    (二) java-bean 赋值转换

    image.png
    • VO ( View Object 和前端view层数据结构相对应 )
    • BO/DTO ( Business object / Data Transfer Object 通常是多个PO的组合体 )
    • POPersistent Object 持久对象,该类的成员与数据库字段一一对应 )
    VO(view object)
        ---------------------------------- controller
    BO(business object)
        ---------------------------------- service
    PO(persistent object)
        ---------------------------------- mapper
    

    (三) 参数验证 spring-boot-starter-validation

    • spring-boot-starter-validation
    image.png

    (1) 安装验证相关依赖

    <!--校验组件-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-validation</artifactId>
    </dependency>
    <!--web组件-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    

    (2) 添加验证规则

    • 一般用于POST,PUT请求
    • 1.在bean实体中添加规则 比如:@NotNull
    • 2.在controller的参数中添加 比如:@Validated 或者 @Valid 作用于bean参数
    bean
    -------
    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @Component
    @ApiModel(description = "返回响应的数据") // swagger
    public class MusicBean {
        @ApiModelProperty(value = "歌曲名") // swagger
        String name;
    
        @NotBlank(message = "album不能为空") // spring-boot-starter-validation => @NotBlank只能用于字符串,trim后长度必须大于0
        String album;
    
        @NotNull(message = "singer不能为空") // spring-boot-starter-validation => @NotNull不能为为null,但可以是空字符串
        String singer;
    
        Timestamp startTime;
        Timestamp endTime;
    }
    
    
    
    controller
    -------
    // 增
    @PostMapping("/music")
    public Integer addMusic(
            @Validated // spring-boot-starter-validation 验证插件,然后在music实体中添加具体的验证规则
            @RequestBody MusicBean music
    ) {
        return musicService.addMusic(music);
    }
    

    (3) 上面 2 中存在的问题

    • 如果上面的2中的 singer 为null,后端就会给前端抛出错误,但是写的具体的错误信息不会返回给前端
    • 所以我们需要在controller的方法中添加参数,类型是 BindingResult
    // 增
    @PostMapping("/music")
    public Object addMusic(
            // @Validated // spring-boot-starter-validation 验证插件,然后在music实体中添加具体的验证规则
            @Valid
            @RequestBody MusicBean music,
            BindingResult br
    ) {
        if (br.hasErrors()) {
            log.info(br.getFieldError().getDefaultMessage());
            return br.getFieldError().getDefaultMessage(); // 将错误返回给前端
        }
        return musicService.addMusic(music);
    }
    
    image.png

    (4) 上面 3 中存在的问题

    • 错误是返回了,但是 状态码还是200 则需要使用 HttpServletResponse
    // 增
    @PostMapping("/music")
    public Object addMusic(
            // @Validated // spring-boot-starter-validation 验证插件,然后在music实体中添加具体的验证规则
            @Valid
            @RequestBody MusicBean music,
            BindingResult br, // spring-boot-starter-validation
            HttpServletResponse resp // spring-boot-starter-validation
    ) {
        if (br.hasErrors()) {
            resp.setStatus(412); // 412 一个或者多个请求头字段在当前请求中报错
            log.info(br.getFieldError().getDefaultMessage());
            return br.getFieldError().getDefaultMessage();
        }
        return musicService.addMusic(music);
    }
    

    (5) @NotBlank @NotEmpty @NotNull @NoneNull 的区别

    • @NotEmpty 用于类上 不能为null,并且长度必须大于0
    • @NotNull 用于类的属性上 不能为null,但是可以是空字符串
    • @Blank 用于类的属性上,并且只用于String类型 不能为null,而且调用trim()后,长度必须大于0
    • @NonNull 用于方法或构造函数的参数上使用,生成一个空值检查语句

    (6) @Valid 和 @Validated 的区别


    (四) 全局异常处理

    • @RestControllerAdvice
    • @ExceptionHandler
    • RuntimeException

    (4.1)具体流程

    • 新建exception的package,然后新建三个文件
      • CustomExceptionBean 错误信息收集
      • ApiResponseBean 返回给前端的最终数据结构
      • WebExceptionHandler

    (4.1.1) CustomExceptionBean

    CustomExceptionBean
    -------
    
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class CustomExceptionBean extends RuntimeException{
        public int code;
        public String message;
    }
    

    (4.1.2) ApiResponseBean

    ApiResponseBean
    -------
    
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @Builder
    public class AjaxResponseBean {
        public boolean isOk;
        public int code;
        public String message;
        public Object data;
    
        // 成功 - 无数据
        // 请求成功的响应,返回值不带查询数据,( 用于添加,删除,修改 )
        public AjaxResponseBean success() {
            AjaxResponseBean ajaxResponseBean = new AjaxResponseBean();
            AjaxResponseBean.builder()
                    .isOk(true)
                    .code(200)
                    .message("请求成功")
                    .build();
            return ajaxResponseBean;
        }
    
    
        // 成功 - 带数据
        // 请求成功的响应,返回值带查询数据,( 用于查询 )
        public static AjaxResponseBean success(Object obj) {
            AjaxResponseBean ajaxResponse = new AjaxResponseBean();
            AjaxResponseBean.builder()
                    .isOk(true)
                    .code(200)
                    .message("请求成功")
                    .data(obj)
                    .build();
            return ajaxResponse;
        }
    
        // 失败
        public static AjaxResponseBean error(CustomExceptionBean customExceptionBean) {
            AjaxResponseBean ajaxResponse = new AjaxResponseBean();
            AjaxResponseBean.builder()
                    .isOk(false)
                    .code(customExceptionBean.getCode())
                    .message(customExceptionBean.getMessage())
                    .build();
            return ajaxResponse;
        }
    }
    

    (4.1.3) WebExceptionHandler

    WebExceptionHandler
    -------
    
    @RestControllerAdvice
    public class WebExceptionHandler {
    
        @ExceptionHandler
        public AjaxResponseBean customException(
                CustomExceptionBean customExceptionBean
        ) {
            customExceptionBean.setCode(400);
            return AjaxResponseBean.error(customExceptionBean);
        }
    }
    
    image.png image.png

    资料

    mysql常见crud https://www.jianshu.com/p/49fcde3e4559
    swagger常用注解 https://blog.csdn.net/jiangyu1013/article/details/83107255
    @ControllerAdvice https://fookwood.com/spring-boot-tutorial-11-ca
    public private protected final static abstract 的区别

    相关文章

      网友评论

          本文标题:[前端学java10-SpringBoot实战] bean赋值转

          本文链接:https://www.haomeiwen.com/subject/ryxwoltx.html