Bean 处理

bean 管理是指

  1. spring 创建对象
  2. spring 注入属性

    @Autowired 注解

    当我们在一个类上标注 @Service、@Controller、@Component、@Repository 注解之后,spring 的组件扫描就会自动发现它,并且会将其初始化为 spring 应用上下文中的 bean。当需要使用这个 bean 的时候,例如加上 @Autowired 注解的时候,这个 bean 就会被创建。而且初始化是根据无参构造函数

    1. @Data
    2. @Service
    3. public class AutoWiredBean {
    4. private int id;
    5. private String name;
    6. public AutoWiredBean(){
    7. System.out.println("无参构造函数");
    8. }
    9. public AutoWiredBean(int id,String name){
    10. this.id = id;
    11. this.name = name;
    12. }
    13. }
  • @Data 注解是由 Lombok 库提供的,会生成 getter、setter 以及 equals()、hashCode()、toString() 等方法
  • 使用 @Service 注解后,这个 bean 被 spring 通过无参构造函数初始化了,加上 @Autowired 注解的时候,这个 bean 就会被创建

    @Autowired 的用法

  1. 可以标注在属性上、方法上和构造器上,来完成自动装配
  2. 默认是根据属性类型,spring自动将匹配到的属性值进行注入,然后就可以使用这个属性 autoWiredBean 对象的方法
  3. 直接应用于字段是我们使用的最多的一种方式,但是使用构造方法注入从代码层面却是更好的

    @Component 注解

    @Component 是一个元注解,意思是可以注解其他类注解,如 @Controller、@Service、@Repository、@Aspect
    官方说法是:带此注解的类看为组件,当使用基于注解的配置和类路径扫描的时候,这些类就会被实例化。其他类级别的注解也可以被认定为是一种特殊类型的组件,比如 @Repository、@Aspect。所以 @Component 可以注解其他类注解

    @Respository 注解

    用在持久层的接口上,经常标记到 dao 类上。这个注解是将接口的一个实现类交给 spring 管理。
    为什么有时候我们不用 @Repository 来注解接口,我们照样可以注入到这个接口的实现类呢?

  4. spring 配置文件中配置了 MapperScannerConfigurer 这个 bean,它会扫描持久层接口创建实现类并交给 spring 管理

  5. 接口上使用了 @Mapper 注解或者 springboot 中主类上使用了 @MapperScan 注解,和 MapperScannerConfigurer 作用一样

    @Repository 的作用

    它的作用不只是将类识别为 bean,同时它还能将所标注的类中抛出的数据访问异常封装为 Spring 的数据访问异常类型。 Spring 本身提供了一个丰富的并且是与具体的数据访问技术无关的数据访问异常结构,用于封装不同的持久层框架抛出的异常,使得异常独立于底层的框架

    @Service 注解

    用于服务层,经常标注到 Service 类上,常需要注入 dao
    在使用 @Server 注解之前,我们经常要在 spring 的配置文件 applicationContext.xml 中添加如下配置:

    1. <context:component-scan base-package="com.study.persistent" />

    这种方式维护困难、可读性差。如果一个类带了 @Service 注解,将自动注册到 Spring 容器,不需要再在 applicationContext.xml 配置文件中定义 bean 了,类似的还包括 @Component、@Repository、@Controller。例如:

    1. @Service
    2. public class TestService {
    3. ...
    4. }

    相当于在 applicationContext.xml 配置文件里配置如下信息:

    1. <bean class="com.test.tools.service.TestService" scope="prototype">
    2. ......
    3. </bean>

    @Controller 注解

    被 @Controller 标记的类实际上就是个 SpringMVC Controller 对象,它是一个控制器类。其中被 @RequestMapping 标记的方法会被分发处理器扫描识别,将不同的请求分发到对应的接口上

    @RestController 注解

    @RestController 的作用等同于 @Controller + @ResponseBody
    @ResponseBody 表示方法的返回值直接以指定的格式写入Http response body中,而不是解析为跳转路径
    如果要求方法返回的是 json 格式数据,而不是跳转页面,可以直接在类上标注 @RestController,而不用在每个方法中标注 @ResponseBody,简化了开发过程。例如: ```java @RestController @RequestMapping(“/tools”) public class DiffyController {

    @RequestMapping(value = “/get/diffy”,method = RequestMethod.GET) public JsonResult getCommand(){

    1. JsonResult jsonResult = new JsonResult(200,diffyService.getStartCommand(),"success");
    2. return jsonResult;

    }

}

  1. 方法的返回值原本是跳转路径,但加上 @ResponseBody 后,就可以向前端返回一个 json 格式的数据
  2. <a name="g3oNY"></a>
  3. ### @Configuration 注解
  4. 用于定义配置类,可替换 xml 配置文件,被注解的类内部包含有一个或多个被 @Bean 注解的方法,这些方法将会被 AnnotationConfigApplicationContext AnnotationConfigWebApplicationContext 类进行扫描,并用于构建 bean 定义,初始化 Spring 容器
  5. <a name="UzYvl"></a>
  6. ### @Scope 注解
  7. @Scope 注解是 springIoc 容器中的一个作用域,在 Spring IoC 容器中具有以下几种作用域:**基本作用域** singleton(单例)、**prototype**(多例),**Web 作用域**(reqeustsessionglobalsession)、**自定义作用域**<br />声明 Spring Bean 的作用域:
  8. - singleton:唯一 bean 实例,Spring 中的 bean 默认都是单例的
  9. - prototype:每次请求都会创建一个新的 bean 实例
  10. - request:每一次 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 HTTP request 内有效
  11. - session:每一次 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 HTTP session 内有效
  12. <a name="oQqE2"></a>
  13. ## HTTP请求
  14. <a name="xRF2R"></a>
  15. ### @GetMapping 注解
  16. Get 请求,从服务器获取特定资源<br />如果我们想使用之前的 @RequestMapping 注解实现 URL 处理程序,那么它应该是这样的:@RequestMapping(value = “/get/{id}”, method = RequestMethod.GET)<br />新方法可以简化为:@GetMapping("/get/{id}")
  17. <a name="BoChb"></a>
  18. ### @PostMapping 注解
  19. POST请求,从服务器获取特定资源
  20. ```java
  21. @PostMapping("/users")
  22. public ResponseEntity<User> createUser(@Valid @RequestBody UserCreateRequest userCreateRequest) {
  23. return userRespository.save(user);
  24. }

使用 @PosttMapping(“/users” ) 等价于 @RequestMapping(value =”/users”,method = RequestMethod.POST)

@PutMapping 注解

PUT 请求,更新服务器上的资源

@DeleteMapping 注解

从服务器上面删除特定请求

前后端参数传递

@RequestParam 注解

@RequestParam 接收的参数是来自 requestHeader 中,即请求头。通常用于 GET 请求
作用:将请求参数绑定到你控制器的方法参数上
语法:@RequestParam(value=”参数名”,required=”true/false”,defaultValue=” “)

  1. value:请求参数的参数名,作为参数映射名称
  2. required:该参数是否必填,默认为true(必填),当设置成必填时,如果没有传入参数,报错
  3. defaultValue:可设置请求参数的默认值

例:请求路径为:localhost:tools/?md5=xxxx;其中 md5 参数是必须存在的,默认值为1

  1. @RestController
  2. public class ToolsController {
  3. @GetMapping(value = "/tools")
  4. public JsonResult tools(@RequestParam(value = "md5",defaultValue="1") String md5){
  5. Md5Tools md5Tools = new Md5Tools();
  6. JsonResult jsonResult = new JsonResult(200, md5Tools.getMd5(md5),"success");
  7. return jsonResult;
  8. }
  9. }

@PathVariable 注解

作用:接收请求路径中占位符的值
语法:@PathVariable(“xxx”)
通过 @PathVariable 可以将 URL 中占位符参数 {xxx} 绑定到处理器类的方法形参中 @PathVariable(“xxx“) 。
例:请求路径为:localhost:tools/md5/xxx;

  1. @RestController
  2. @RequestMapping("/tools")
  3. public class ToolsController {
  4. @RequestMapping(value = "/md5/{md5}",method = RequestMethod.GET)
  5. public JsonResult tools(@PathVariable String md5){
  6. Md5Tools md5Tools = new Md5Tools();
  7. JsonResult jsonResult = new JsonResult(200, md5Tools.getMd5(md5),"success");
  8. return jsonResult;
  9. }
  10. }

@RequestBody 注解

@RequestBody 接收的参数是来自 requestBody 中(请求体),即前端传递给后端的 json。常用其来处理 application/json 类型的请求数据。
GET 方式无请求体,所以使用 @RequestBody 接收数据时,前端不能使用 GET 方式提交数据。在同一个接收方法里,@RequestBody 与 @RequestParam() 可以同时使用,@RequestBody 最多只能有一个,而 @RequestParam() 可以有多个。

  1. @PostMapping(path = "/post/diffy")
  2. public JsonResult add(@RequestBody DiffyEntity diffyEntity,Exception e){
  3. // TODO
  4. return jsonResult;
  5. }

@ResponseBody 注解

作用是将 Controller 的方法返回的对象通过适当的转换器转换为指定的格式之后,写入到 response 对象的 body 区,通常用来返回 JSON 数据。需要注意的呢,在使用此注解之后不会再走试图处理器,而是直接将数据写入到输入流中,他的效果等同于通过 response 对象输出指定格式的数据。
假如 User 中有字段:userName、pwd。如果前端想要接收到的 json 数据为:’{“userName”:”xxx”,”pwd”:”xxx”}’。可以这样写:

  1. @RequestMapping("/login")
  2. @ResponseBody
  3. public User login(User user){
  4.   return user;
  5. }
  6. // 效果等同于如下代码:
  7. @RequestMapping("/login")
  8. public void login(User user, HttpServletResponse response){
  9.   response.getWriter.write(JSONObject.fromObject(user).toString());
  10. }

读取配置

@value 注解

作用:将我们配置文件的属性读出来,有 @Value(“${}”) 和 @Value(“#{}”) 两种方式

@Value(“${}”) 和 @Value(“#{}”) 的区别

@Value 的值有两类:

  1. ${ property : default_value }:注入的是外部配置文件对应的 property,default_value 是前面的值为空时的默认值
  2. { obj.property? :default_value }:是SpEL表达式对应的内容,default_value 是前面的值为空时的默认值。这里面的 obj 代表的是一个对象

    @Value(“${}”) 的使用

    application.propertites 配置文件中有属性如下:

    1. #1.项目启动的端口
    2. server.port=18902
    3. #2.mysql的驱动
    4. jdbc.driver=com.mysql.cj.jdbc.Driver
    5. # TODO

    如果要读取 jdbc.driver 属性的值,可以使用 @Value 注解:

    1. @Configuration
    2. public class DataSourceConfiguration {
    3. @Value("${jdbc.driver}")
    4. private String jdbcDriver;
    5. // TODO
    6. }

    @ConfigurationProperties 注解

    这个注解的作用是将配置文件中的配置,以属性的形式自动注入到 bean 中,和上面的 @Value 注解有点相似,但 @ConfiggurationProperties 注解方式更安全一些
    例如,在 application.properties 文件中有这些参数:

    1. #1.项目启动的端口
    2. server.port=18902
    3. #2.mysql的驱动
    4. jdbc.driver=com.mysql.cj.jdbc.Driver
    5. #3.数据库连接
    6. jdbc.url=jdbc:mysql://127.0.0.1:3306/tools?useUnicode=true&characterEncoding=utf-8&useSSL=false

    使用 @ConfigurationProperties 注解来获取属性:

    1. @Data
    2. @Configuration
    3. @ConfigurationProperties(prefix = "jdbc")
    4. public class DataSourceConfiguration {
    5. private String jdbcDriver;
    6. private String jdbcUrl;
    7. private String jdbcUsername;
    8. private String jdbcPassword;
    9. }

    @ConfigurationProperties 的基本用法:为每个要捕获的外部属性提供一个带有字段的类。请注意以下几点:

  • 前缀定义了哪些外部属性将绑定到类的字段上
  • 根据 Spring Boot 的宽松绑定规则,类的属性名称必须与外部属性的名称匹配
  • 我们可以简单地用一个值初始化一个字段来定义一个默认值
  • 类本身可以是包私有的
  • 类的字段必须有公共 setter 方法

    @PropertySource 注解

    @PropertySource 注解用于指定资源文件读取的位置,它不仅能读取 properties 文件,也能读取 xml 文件,并且通过 YAML 解析器,配合自定义 PropertySourceFactory 实现解析 YAML 文件

    参数校验

    Bean 字段验证注解

    使用 Bean 字段验证的注解前,需要添加依赖项:
    1. <dependency>
    2. <groupId>org.springframework.boot</groupId>
    3. <artifactId>spring-boot-starter-validation</artifactId>
    4. </dependency>
  1. @NotEmpty :被注释的字符串的不能为 null 也不能为空
  2. @NotBlank :被注释的字符串非 null,并且必须包含一个非空白字符
  3. @Email :被注释的元素必须是 Email 格式

常用的见 SpringBoot使用Validation校验参数

@Valid 注解

在 Controller 对应方法上,在变量之前添加 @Valid 注解,表示我们对这个对象属性需要进行验证

  1. @RestController
  2. @RequestMapping("/tools")
  3. public class DiffyController {
  4. @PostMapping(path = "/post/diffy")
  5. public JsonResult add(@Valid @RequestBody DiffyEntity diffyEntity,BindingResult bindingResult){
  6. // TODO 异常处理,包括参数异常
  7. return jsonResult;
  8. }
  9. }

添加了 @Valid 注解,表示要对 diffyEntity 这个对象进行参数验证。而 BindingResult 是用来保存验证结果的

@Validated 注解

@Validated 注解是 @Valid 的一个升级版,在使用 @Valid 进行验证的时候,我们需要用一个对象去接收校验结果,最后根据校验结果判断,从而提示用户。
使用 @Validated 进行校验的时候,当校验不通过的时候,程序会抛出400异常,阻止方法中的代码执行,这时需要再写一个全局校验异常捕获处理类,然后返回校验提示

  1. @RestController
  2. @RequestMapping("/tools")
  3. public class DiffyController {
  4. @PostMapping(path = "/post/diffy")
  5. public JsonResult add(@Validated(Insert.class) @RequestBody DiffyEntity diffyEntity,Exception e){
  6. // 异常处理,包括参数异常
  7. if (e instanceof MethodArgumentNotValidException) {
  8. MethodArgumentNotValidException exception = (MethodArgumentNotValidException)e;
  9. return JsonResult.warn(exception.getBindingResult().getFieldErrors().get(0).getDefaultMessage());
  10. }
  11. return jsonResult;
  12. }
  13. }

@Valid 和 @Validated 的区别

  • @Valid 和 @Validated 两者都可以对数据进行校验,待校验字段上打的规则注解(@NotNull, @NotEmpty等)都可以对 @Valid 和 @Validated 生效
  • @Valid 进行校验的时候,需要用 BindingResult 来做一个校验结果接收。当校验不通过的时候,如果手动不 return ,则并不会阻止程序的执行
  • @Validated 进行校验的时候,当校验不通过的时候,程序会抛出400异常,阻止方法中的代码执行,这时需要再写一个全局校验异常捕获处理类,然后返回校验提示
  • 总体来说,@Validated 使用起来要比 @Valid 方便一些,它可以帮我们节省一定的代码,并且使得方法看上去更加的简洁

    统一异常处理

    @ControllerAdvice 注解

    @ControllerAdvice 注解的学名是 Controller 增强器,作用是给 Controller 控制器添加统一的操作或处理,内部包含 @Component 所以可以被 Spring 扫描到
    @ControllerAdvice 是在类上声明的注解,其用法主要有三点:
  1. 结合方法型注解 @ExceptionHandler,用于捕获 Controller 中抛出的指定类型的异常,从而达到不同类型的异常区别处理的目的
  2. 结合方法型注解 @InitBinder,用于 request 中自定义参数解析方式进行注册,从而达到自定义指定格式参数的目的
  3. 结合方法型注解 @ModelAttribute,表示其注解的方法将会在目标 Controller 方法执行之前执行

    1. @ControllerAdvice
    2. public class GlobalExceptionHandler {
    3. // 声明要捕获的异常
    4. @ExceptionHandler(Error.class)
    5. @ResponseBody
    6. public JsonResult defaultError(HttpServletRequest request, Error e) {
    7. if (e instanceof NoClassDefFoundError) {
    8. return JsonResult.fail("找不到类错误" + e.getMessage());
    9. }
    10. // 未知错误
    11. e.printStackTrace();
    12. return JsonResult.fail("项目运行异常, 请联系技术人员...");
    13. }
    14. // 声明要捕获的异常
    15. @ExceptionHandler(Exception.class)
    16. @ResponseBody
    17. public JsonResult defaultException(HttpServletRequest request, Exception e) {
    18. // 请求方式有误
    19. if (e instanceof HttpRequestMethodNotSupportedException) {
    20. return JsonResult.warn("请求方式POST/GET有误");
    21. }
    22. // TODO
    23. }

    @ExceptionHandler 注解

    注解声明异常处理方法,表示遇到这个问题,就执行标注的方法,具体用法见上方
    更多见在Controller中使用@Validated注解模块

    注解的参数

    @ExceptionHandler 注解中可以添加参数,参数是某个异常类的 class,代表这个方法专门处理该类异常,比如上面例子中 @ExceptionHandler 注解的参数有 Error.class 和 Exception.class。表示只有方法抛出 Error 和 Exception 时,才会调用该异常处理的方法

    JPA数据持久化

    @Entity 注解

    @Entity 说明这个 class 是实体类,并且使用默认的 orm 规则,即 class 名即数据库表中表名,class 字段名即表中的字段名
    @Entity 注解指名这是一个实体 Bean

    @Table 注解

    设置表名

    @Id 注解

    声明一个字段为主键

    @GeneratedValue 注解

    @GeneratedValue 注解的意义主要就是为一个实体生成一个唯一标识的主键(JPA要求每一个实体Entity,必须有且只有一个主键)
    @GeneratedValue 提供了主键的生成策略:

  • GenerationType.TABLE:持久化引擎通过关系数据库的一张特定的表格来生成主键
  • GenerationType.SEQUENCE:随机序列
  • GenerationType.IDENTITY:主键自增长
  • GenerationType.AUTO:持久化引擎会根据数据库在以上三种主键生成策略中选择

    @Column 注解

    用来标识实体类中属性与数据表中字段的对应关系

    @Column 属性详解

  • name:定义了被标注字段在数据库表中所对应字段的名称

  • unique:表示该字段是否为唯一标识,默认为false
  • nullable:表示该字段是否可以为null值,默认为true
  • insertable:表示在使用“INSERT”脚本插入数据时,是否需要插入该字段的值
  • updatable:表示在使用“UPDATE”脚本插入数据时,是否需要更新该字段的值

例如,指定字段“tradeNo”交易编号的长度为50,且值不能为null

  1. @Column(name = "tradeNo", length = 50, nullable = false)
  2. private String tradeNo;

@Transient 注解

实体类中使用了 @Table 注解后,想要添加表中不存在的字段,就要使用 @Transient 这个注解了
使用 @Transient 表示该属性并非是一个要映射到数据库表中的字段,只是起辅助作用。ORM 框架将会忽略该属性

  1. // 表示该属性并非一个到数据库表的字段的映射
  2. @Transient
  3. private String departmentName;
  4. @Column(name = "USER_POSITION")
  5. private String userPosition;

如上,userPosition 字段是数据库表字段的映射,使用了 @Column 注解;然而 departmentName 字段数据库中不存在,所以直接使用 @Transient ,而不再使用 @Column 注解

@Modifying 注解

涉及到数据修改操作,可以使用 @Modifying 注解;加在dao方法上,提示是修改操作

@Transactional 注解

在需要事务管理的地方加 @Transactional 注解。@Transactional 注解可以被应用于接口定义和接口方法、类定义和类的 public 方法上。
@Tranasctional 注解是 Spring 框架提供的声明式注解事务解决方案,我们在开发中使用事务保证方法对数据库操作的原子性,要么全部成功,要么全部失败。
使用 @Transactional 注解时需要注意以下问题:

  1. @Transactional 注解只能用在 public 方法上,如果用在 protected 或者 private 的方法上,不会报错,但是该注解不会生效
  2. @Transactional 注解只能回滚非检查型异常,具体为 RuntimeException 及其子类和 Error 子类,可以从 Spring 源码的 DefaultTransactionAttribute 类里找到判断方法 rollbackOn
  3. 使用 rollbackFor 属性来定义回滚的异常类型,使用 propagation 属性定义事务的传播行为
  4. @Transactional 注解不能回滚被 try{} catch() 捕获的异常
  5. @Transactional 注解只能对在被 Spring 容器扫描到的类下的方法生效

Exception 分为运行时异常 RuntimeException 和非运行时异常。在 @Transactional 注解中如果不配置 rollbackFor属性,那么事物只会在遇到 RuntimeException 的时候才会回滚,加上 rollbackFor=Exception.class,可以让事物在遇到非运行时异常时也回滚

  • 注解作用于类上:表示所有该类的 public 方法都配置相同的事务属性信息
  • 注解作用于方法上:当类配置了 @Transactional,方法也配置了 @Transactional,方法的事务会覆盖类的事务配置信息

    @Transactional 注解的可用参数

  • readOnly:用于设置当前事务是否为只读事务,设置为 true 表示只读,false 则表示可读写,默认值为 false

  • rollbackFor:用于设置需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,则进行事务回滚,如:
    • 指定单一异常类:@Transactional(rollbackFor=RuntimeException.class)
    • 指定多个异常类:@Transactional(rollbackFor={RuntimeException.class, BusnessException.class})
  • rollbackForClassName:用于设置需要进行回滚的异常类名称数组,当方法中抛出指定异常名称数组中的异常时,则进行事务回滚。如:
    • 指定单一异常类名称:@Transactional(rollbackForClassName=“RuntimeException”)
    • 指定多个异常类名称:@Transactional(rollbackForClassName={“RuntimeException”,“BusnessException”})
  • timeout:设置事务的超时秒数,默认值为-1表示永不超时
  • propagation:用于设置事务的传播行为
  • isolation:设置底层数据库的事务隔离级别

    Json格式处理

    @JsonIgnoreProperties 注解

    作用在类上用于过滤掉特定字段不返回或者不解析

    1. //生成json时将userRoles属性过滤
    2. @JsonIgnoreProperties({"userRoles"})
    3. public class User {
    4. private String userName;
    5. private String fullName;
    6. private String password;
    7. @JsonIgnore
    8. private List<UserRole> userRoles = new ArrayList<>();
    9. }

    @JsonIgnore 注解

    用来完全忽略被注解的字段和方法对应的属性,即便这个字段或方法可以被自动检测到或者还有其他的注解,一般标记在属性或者方法上,返回的json数据即不包含该属性,作用和上面的 @JsonIgnoreProperties 一样

    @JsonFormat 注解

    @JsonFormat 注解是一个时间格式化注解,比如存储在 mysql 中的数据是 dateTime 类型,程序读取出来封装在实体类中的时候,就会变成英文时间格式,而不是 yyyy-MM-dd HH:mm:ss 格式的时间,因此 @JsonFormat 注解就可以用来格式化时间。 ```java public class Student { private int id; private String username;

    @JsonFormat(pattern=”yyyy-MM-dd HH:mm:ss”,timezone=”GMT+8”) private Date createDate; // getter setter省略 }

  1. 上面例子中当 @ResponseBody 输出 json 数据的时候,@JsonFormat 注解标识的 date 属性就会自动返回 yyyy-MM-dd HH:mm:ss 格式的时间
  2. ```java
  3. @PostMapping("/api/getStudent")
  4. @ResponseBody
  5. public Map<String,Object> findStudentById(Long stuId){
  6. Map<String,Object> resultMap = new HashMap<>();
  7. Student stu = studentService.findStudentById(stuId);
  8. resultMap.put("result",stu);
  9. return resultMap;
  10. }

@JsonUnwrapped 注解

@JsonUnwrapped 表明属性应该以扁平化的形式进行序列化,即目标属性将不会序列化为 JSON 对象,但其属性将序列化为包含它的对象的属性
例:有以下的实体类

  1. @Data
  2. public class Money {
  3. private double remain;
  4. }
  5. @Data
  6. public class PersonInfo {
  7. private String name;
  8. private int id;
  9. }
  10. @Data
  11. public class Account {
  12. private Money money;
  13. private PersonInfo personInfo;
  14. }

在 api中 返回序列化之后是这样的:

  1. {
  2. "money": {
  3. "remain": 1030.0
  4. },
  5. "personInfo": {
  6. "name": "xiaoming",
  7. "id": 1
  8. }
  9. }

但是你如果想要扁平对象,只要内层对象,可以使用 @JsonUnwrapped 来扁平对象

  1. @Data
  2. public class Account {
  3. @JsonUnwrapped
  4. private Money money;
  5. @JsonUnwrapped
  6. private PersonInfo personInfo;
  7. }

结果:

  1. {
  2. "remain": 1030.0,
  3. "name": "xiaoming",
  4. "id": 1
  5. }

使用 @JsonUnwrapped 可能出现名称冲突的情况,可以用 @JsonUnwrapped#prefix、@JsonUnwrapped#suffix 解决。如:@JsonUnwrapped(prefix = “dept-“)

测试处理

@ActiveProfiles 注解

常作用于测试类上,用于指定这个测试类里的测试方式运行时的配置文件

  1. @RunWith(SpringRunner.class)
  2. @SpringBootTest
  3. @ActiveProfiles("dev")
  4. public class Tests {
  5. @Test
  6. public void contextLoads() {}
  7. }

@Test 注解

@Test 注解是 TestNG 的核心注解,被打上该注解的方法,表示为一个测试方法
语法:@Test(param1 = …, param2 = …)
参数常见取值:

  • alwaysRun : 如果 =true,表示即使该测试方法所依赖的前置测试有失败的情况,也要执行
  • dataProvider : 选定传入参数的构造器
  • dataProviderClass : 确定参数构造器的 Class 类。(参数构造器首先会在当前测试类里面查找,如果参数构造器不在当前测试类定义,那么必须使用该属性来执行它所在的 Class 类)
  • dependsOnGroups : 确定依赖的前置测试组别
  • dependsOnMethods : 确定依赖的前置测试方法
  • description:测试方法描述信息(建议为每个测试方法添加有意义的描述信息,这将会在最后的报告中展示出来)
  • enabled : 默认为 true,如果指定为 false,表示不执行该测试方法
  • expectedExceptions:指定期待测试方法抛出的异常,多个异常以逗号(,)隔开
  • groups : 指定该测试方法所属的组,可以指定多个组,以逗号隔开
  • invocationCount: 指定测试方法需要被调用的次数
  • invocationTimeOut:每一次调用的超时时间,如果 invocationCount 没有指定,该参数会被忽略。应用场景可以为测试获取数据库连接,超时就认定为失败。单位是毫秒
  • priority:指定测试方法的优先级,数值越低,优先级越高,将会优先与其他数值高的测试方法被调用。(注意是针对一个测试类的优先级)
  • timeout:指定整个测试方法的超时时间。单位是毫秒

    1. public class TestNGTest {
    2. @BeforeTest
    3. public void beforeTest() {
    4. System.out.println();
    5. }
    6. //这个case不会被执行
    7. @Test(enabled = false,description = "enabled = false")
    8. public void test1() {
    9. System.out.println(this.getClass().getName() + "test1");
    10. }
    11. //priority的值越小则优先级越高,invocationCount代表case被执行的次数
    12. @Test(priority = 3, invocationCount = 2,description = "描述")
    13. public void test2() {
    14. System.out.println(this.getClass().getName() + "test2");
    15. }
    16. @Test
    17. public void test3() {
    18. System.out.println(this.getClass().getName() + "test3");
    19. }
    20. }

    @WithMockUser 注解

    Spring Security 提供的,用来模拟一个真实用户,并且可以赋予权限

    配置启动

    @SpringBootApplication 注解

    @SpringBootApplication 注解是 Spring Boot 最核心、最基础的注解。@SpringBootApplication 是一个复合注解,包括 @ComponentScan,和 @SpringBootConfiguration、@EnableAutoConfiguration

  1. @ComponentScan,扫描当前包及其子包下被 @Component,@Controller,@Service,@Repository 注解标记的类并纳入到 spring 容器中进行管理
  2. @SpringBootConfiguration 继承自 @Configuration,二者功能也一致,标注当前类是配置类,并会将当前类内声明的一个或多个以 @Bean 注解标记的方法的实例纳入到 srping 容器中,并且实例名就是方法名
  3. @EnableAutoConfiguration 的作用启动自动的配置,@EnableAutoConfiguration 注解的意思就是 Springboot 根据你添加的 jar 包来配置你项目的默认配置,比如根据 spring-boot-starter-web ,来判断你的项目是否需要添加了 webmvc 和 tomcat,就会自动的帮你配置 web 项目中所需要的默认配置

    1. SpringBootApplication
    2. public class ToolsApplication {
    3. public static void main(String[] args) {
    4. SpringApplication.run(ToolsApplication.class, args);
    5. }
    6. }

    @Configuration 注解

    该注解表示一个类声明了一个或多个 @Bean 方法,并且可以由 Spring 容器进行处理,以在运行时为这些 bean 生成 bean 定义和服务请求,例如:

    1. @Configuration
    2. public class AppConfig {
    3. @Bean
    4. public MyBean myBean() {
    5. // 实例化,配置并返回Bean ...
    6. }
    7. }

    @EnableAutoConfiguration 注解

    类级别的注解,这个注解告诉 SpringBoot 根据添加的 jar 依赖猜测你想如何配置 Spring。上面的 @SpringBootApplication 注解中已提到

    @ComponentScan 注解

    标注哪些路径下的类需要被 Spring 扫描。上面的 @SpringBootApplication 注解中已提到

    @Conditional 注解

    通过 @Conditional 注解可以根据代码中设置的条件装载不同的 bean,也是SpringBoot实现自动配置的基石