The word “spring / 8000” is close to the common annotation of spring! Arrange!

Time:2020-11-9

Preface

Hello, I’m brother guide! This is my 221 high quality original articles. If you want to reprint, please indicate the address at the beginning of the article, crab!

This article has been included in my 75K star Java open source project javaguide: https://github.com/Snailclimb/JavaGuide Related reading: v2.0 version of “javaguide interview surprise edition” is coming! Here comes the online version of it!

It is no exaggeration to say that the spring / springboot common annotations described in this article have basically covered most of the common scenarios you encounter in your work. For each annotation, I have said the specific usage, master to understand, using spring boot to develop projects is basically no big problem!

The whole directory is as follows, with a little more content:

The word

Why write this article?

Recently, I saw an article on the Internet about the common annotations of springboot, which was reprinted more. After reading the content of the article, I felt that the quality was a little low, and it would mislead people who did not have much practical experience (these people occupied the majority). So, I simply spent about two days to summarize.

Because my personal ability and energy is limited, if there is anything wrong or need to be improved, please help to point out! Thank you very much!

1. @SpringBootApplication

I’ll take it out of here alone@SpringBootApplicationNote that although we don’t usually use it on our own initiative.

Brother Guide: this annotation is the cornerstone of the spring boot project. After the spring boot project is created, it will be added to the main class by default.

@SpringBootApplication
public class SpringSecurityJwtGuideApplication {
      public static void main(java.lang.String[] args) {
        SpringApplication.run(SpringSecurityJwtGuideApplication.class, args);
    }
}

We can put@SpringBootApplicationSee as@Configuration@EnableAutoConfiguration@ComponentScanA collection of annotations.

package org.springframework.boot.autoconfigure;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
        @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
        @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
   ......
}

package org.springframework.boot;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {

}

According to the official website of springboot, the functions of the three annotations are as follows:

  • @EnableAutoConfiguration: enable the automatic configuration mechanism of springboot
  • @ComponentScan: scan by@Component (@Service,@Controller)Annotated bean. By default, the annotation will scan all classes under the package in which the class is located.
  • @Configuration: allows you to register additional beans or import other configuration classes in the spring context

2. Spring bean

2.1. @Autowired

Automatically import objects into classes. The injected classes are also managed by spring container. For example, service class is injected into controller class.

@Service
public class UserService {
  ......
}

@RestController
@RequestMapping("/users")
public class UserController {
   @Autowired
   private UserService userService;
   ......
}

2.2. Component,@Repository,@Service, @Controller

We usually use it@AutowiredAnnotations let the spring container help us assemble beans automatically. To identify a class as available for@AutowiredAnnotation automatically assembled bean class can be implemented with the following annotations:

  • @Component: general annotation, which can mark any class asSpringComponent. If a bean doesn’t know which layer it belongs to, you can use the@ComponentAnnotation.
  • @Repository: the corresponding persistence layer, namely Dao layer, is mainly used for database related operations.
  • @Service: corresponding to the service layer, which mainly involves some complex logic and needs to use DAO layer.
  • @Controller: corresponding to the spring MVC control layer, the main user accepts the user request and calls the service layer to return data to the front-end page.

2.3. @RestController

@RestControllerThe note is@Controller and@ResponseBodyIt means that this is a controller bean, and the return value of the function is directly filled into the HTTP response body. It is a rest style controller.

Brother Guide: now the front and back end are separated. To be honest, I haven’t used it for a long time@Controller。 If your project is too old, think I didn’t say it.

Use alone@ControllerNo@ResponseBodyIt is generally used to return a view. This case belongs to the application of traditional spring MVC, corresponding to the situation that the front end and the back end are not separated.@Controller +@ResponseBodyReturn data in JSON or XML form

about@RestControllerand@ControllerPlease see this article: @ restcontroller vs @ controller.

2.4. @Scope

To declare the scope of spring bean, use the following method:

@Bean
@Scope("singleton")
public Person personSingleton() {
    return new Person();
}

The scope of four common spring beans:

  • Singleton: the only bean instance. Beans in spring are singleton by default.
  • Prototype: each request creates a new bean instance.
  • Request: each HTTP request generates a new bean that is valid only within the current HTTP request.
  • Session: each HTTP request generates a new bean that is valid only within the current HTTP session.

2.5. Configuration

It is generally used to declare configuration classes. You can use the@ComponentNote substitution, but useConfigurationThe annotation declaration configuration class is more semantic.

@Configuration
public class AppConfig {
    @Bean
    public TransferService transferService() {
        return new TransferServiceImpl();
    }

}

3. Handle common HTTP request types

Five common request types:

  • GET: request to get a specific resource from the server. for instance:GET /users(get all students)
  • POST: creates a new resource on the server. for instance:POST /users(create students)
  • PUT: update the resource on the server (the client provides the whole updated resource). for instance:PUT /users/12(update student number 12)
  • DELETE: removes a specific resource from the server. for instance:DELETE /users/12(delete student number 12)
  • PATCH: update the resources on the server (the client provides the changed properties, which can be seen as partial updates). The usage is relatively small, so we will not give an example here.

3.1. Get request

@GetMapping("users")Equivalent to@RequestMapping(value="/users",method=RequestMethod.GET)

@GetMapping("/users")
public ResponseEntity<List<User>> getAllUsers() {
 return userRepository.findAll();
}

3.2. Post request

@PostMapping("users")Equivalent to@RequestMapping(value="/users",method=RequestMethod.POST)

about@RequestBodyThe use of annotations is described in the section “value passing from front to back” below.

@PostMapping("/users")
public ResponseEntity<User> createUser(@Valid @RequestBody UserCreateRequest userCreateRequest) {
 return userRespository.save(user);
}

3.3. Put request

@PutMapping("/users/{userId}")Equivalent to@RequestMapping(value="/users/{userId}",method=RequestMethod.PUT)

@PutMapping("/users/{userId}")
public ResponseEntity<User> updateUser(@PathVariable(value = "userId") Long userId,
  @Valid @RequestBody UserUpdateRequest userUpdateRequest) {
  ......
}

3.4. Delete request

@DeleteMapping("/users/{userId}")Equivalent to@RequestMapping(value="/users/{userId}",method=RequestMethod.DELETE)

@DeleteMapping("/users/{userId}")
public ResponseEntity deleteUser(@PathVariable(value = "userId") Long userId){
  ......
}

3.5. Patch request

In general, in actual projects, we use patch request to update data when put is not enough.

  @PatchMapping("/profile")
  public ResponseEntity updateStudent(@RequestBody StudentUpdateRequest studentUpdateRequest) {
        studentRepository.updateDetail(studentUpdateRequest);
        return ResponseEntity.ok().build();
    }

4. Front and rear end value transmission

Mastering the correct posture of the front and rear transmission is the first step for you to start crud!

4.1. @PathVariableand@RequestParam

@PathVariableUsed to get path parameters,@RequestParamUsed to get query parameters.

Take a simple example

@GetMapping("/klasses/{klassId}/teachers")
public List<Teacher> getKlassRelatedTeachers(
         @PathVariable("klassId") Long klassId,
         @RequestParam(value = "type", required = false) String type ) {
...
}

If the URL we requested is:/klasses/{123456}/teachers?type=web

Then the data obtained by our service is:klassId=123456,type=web

4.2. @RequestBody

Used to read the body part of a request request (possibly a post, put, delete, get request), andContent type is application / JSONAfter receiving the data, the data will be bound to the Java object automatically. The system will useHttpMessageConverterOr customHttpMessageConverterConvert the JSON string in the requested body into a Java object.

I use a simple example to demonstrate the basic use!

We have a registered interface:

@PostMapping("/sign-up")
public ResponseEntity signUp(@RequestBody @Valid UserRegisterRequest userRegisterRequest) {
  userService.save(userRegisterRequest);
  return ResponseEntity.ok().build();
}

UserRegisterRequestParticipants:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserRegisterRequest {
    @NotBlank
    private String userName;
    @NotBlank
    private String password;
    @FullName
    @NotBlank
    private String fullName;
}

We send a post request to this interface, and the body carries the JSON data:

{"userName":"coder","fullName":"shuangkou","password":"123456"}

In this way, our back-end can directly map the data in JSON format to ourUserRegisterRequestClass.

The word

It should be noted that:A request method can have only one@RequestBody, but there can be more than one@RequestParamand@PathVariable。 If you have to use two methods@RequestBodyTo accept data, the rate is probably your database design or system design problems!

Read configuration information 5

Many times, we need to put some commonly used configuration information, such as alicloud OSS, sending SMS, wechat authentication related configuration information into the configuration file.

Let’s take a look at how spring provides us with ways to read this configuration information from a configuration file.

Our data sourcesapplication.ymlThe contents are as follows:

Wuhan2020: novel coronavirus broke out in Wuhan in early 2020, and the epidemic was serious. But I believe everything will be over. Come on, Wuhan! Go China!

my-profile:
  Name: Guide
  email: [email protected]

library:
  Location: Wuhan, Hubei, China
  books:
    -Basic law of genius
      Description: on the day of his father's diagnosis of Alzheimer's disease, 22-year-old Lin Chaoxi learned that Pei Zhi, a campus God whom he had been in love with for many years, was about to go abroad for further study. The school that her father had given up for her was the school that her father had given up for her.
    -Name: order of time
      Description: why do we remember the past, not the future? What does the "passing of time" mean? Do we exist in time, or does time exist in us? Carlo Lowe uses poetic words to invite us to think about this eternal puzzle, the nature of time.
    -Name: Great me
      Description: how to form a new habit? How to make the mind more mature? How to have a high quality relationship? How to get out of the difficult time of life?

5.1. @value(commonly used)

use@Value("${property}")Read simple configuration information:

@Value("${wuhan2020}")
String wuhan2020;

5.2. @ConfigurationProperties(commonly used)

adopt@ConfigurationPropertiesRead the configuration information and bind it to the bean.

@Component
@ConfigurationProperties(prefix = "library")
class LibraryProperties {
    @NotEmpty
    private String location;
    private List<Book> books;

    @Setter
    @Getter
    @ToString
    static class Book {
        String name;
        String description;
    }
  Omit getter / setter
  ......
}

You can inject it into a class just like you use a normal spring bean.

5.3. PropertySource(not commonly used)

@PropertySourceRead the specified properties file

@Component
@PropertySource("classpath:website.properties")

class WebSite {
    @Value("${url}")
    private String url;

  Omit getter / setter
  ......
}

For more information, check out my article, “how does springboot gracefully read configuration files in 10 minutes?”? 》 。

6. Parameter verification

The importance of data verification is needless to say. Even when the front-end verifies the data, we still need to verify the data passed in to the back-end again to avoid users bypassing the browser and directly requesting some illegal data from the back-end through some HTTP tools.

JSR(Java Specification Requests)Is a set of JavaBean parameter validation standards, it defines a lot of commonly used validation annotations, we can directly add these annotations to our JavaBean properties, so that we can verify when we need to verify, very convenient!

What we actually use for verification isHibernate ValidatorFramework. Hibernate validator is the original data validation framework of Hibernate team. Hibernate validator 4. X is the reference implementation of bean validation 1.0 (JSR 303), hibernate validator 5. X is the reference implementation of bean validation 1.1 (JSR 349). The latest version of Hibernate validator 6. X is the reference implementation of bean validation 2.0 (JSR 380).

The hibernate validator package already exists in the spring boot starter web dependency of the springboot project, so there is no need to refer to the dependency. As shown in the following figure (generated by idea plug-in Maven helper)

The word

Non spring boot projects need to introduce dependency packages themselves. I will not explain them here. For details, please see my article: how to do parameter verification in spring / spring boot? All you need to know is here! 》。

It should be noted that:For all annotations, JSR annotation is recommendedjavax.validation.constraints, rather thanorg.hibernate.validator.constraints

6.1. Notes on some commonly used field validation

  • @NotEmptyThe of the annotated string cannot be null or empty
  • @NotBlankThe annotated string is not null and must contain a non white space character
  • @NullThe annotated element must be null
  • @NotNullThe annotated element must not be null
  • @AssertTrueThe annotated element must be true
  • @AssertFalseThe annotated element must be false
  • @Pattern(regex=,flag=)The annotated element must conform to the specified regular expression
  • @EmailThe annotated element must be in email format.
  • @Min(value)The annotated element must be a number and its value must be greater than or equal to the specified minimum value
  • @Max(value)The annotated element must be a number and its value must be less than or equal to the specified maximum value
  • @DecimalMin(value)The annotated element must be a number and its value must be greater than or equal to the specified minimum value
  • @DecimalMax(value)The annotated element must be a number and its value must be less than or equal to the specified maximum value
  • @Size(max=, min=)The size of the annotated element must be within the specified range
  • @Digits (integer, fraction)The annotated element must be a number and its value must be within an acceptable range
  • @PastThe annotated element must be a past date
  • @FutureThe annotated element must be a future date
  • ……

6.2. Request body

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {

    @Notnull (message = CLassID cannot be empty)
    private String classId;

    @Size(max = 33)
    @Notnull (message = "name cannot be empty")
    private String name;

    @Pattern (regexp = "(^ man $| woman $| ^ UGM $)", message: "sex value is not in the optional range")
    @Notnull (message = "sex cannot be empty")
    private String sex;

    @Email (message: "email format is incorrect")
    @Notnull (message = email cannot be empty)
    private String email;

}

We add the parameters that need to be verified@ValidAnnotation, which is thrown if validation failsMethodArgumentNotValidException

@RestController
@RequestMapping("/api")
public class PersonController {

    @PostMapping("/person")
    public ResponseEntity<Person> getPerson(@RequestBody @Valid Person person) {
        return ResponseEntity.ok().body(person);
    }
}

6.3. Verify request parameters (path variables and request parameters)

Make sure you don’t forget to addValidatedNote that this parameter can tell spring to verify method parameters.

@RestController
@RequestMapping("/api")
@Validated
public class PersonController {

    @GetMapping("/person/{id}")
    Public responseentity < integer > getpersonbyid (@ valid @ pathvariable ("Id") @ max (value = 5, message = beyond the range of ID ") integer ID){
        return ResponseEntity.ok().body(id);
    }
}

For more information on how to perform parameter verification in spring projects, please refer to how to do parameter verification in spring / spring boot? All you need to know is here! 》This article.

7. Handle controller layer exception globally

Let’s introduce the necessary global handling of controller layer exceptions for our spring project.

Related notes:

  1. @ControllerAdvice: annotation defines the global exception handling class
  2. @ExceptionHandler: annotations declare exception handling methods

How to use it? Let’s take an example in Section 5. If the method parameter is not correct, it will be thrownMethodArgumentNotValidExceptionLet’s handle this exception.

@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler {

    /**
     *Exception handling of request parameters
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<?> handleMethodArgumentNotValidException(MethodArgumentNotValidException ex, HttpServletRequest request) {
       ......
    }
}

For more on spring boot exception handling, please see my two articles:

  1. Several common postures of spring boot for handling exceptions
  2. Use enumeration to encapsulate an elegant spring boot global exception handling!

8. JPA related

8.1. Create table

@EntityDeclare that a class corresponds to a database entity.

@TableSetting indication

@Entity
@Table(name = "role")
public class Role {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String description;
    Omit getter / setter
}

8.2. Create primary key

@Id: declare a field as a primary key.

use@IdAfter the declaration, we also need to define the generation strategy of the primary key. We can use it@GeneratedValueSpecifies the primary key generation policy.

1. Pass@GeneratedValueThe four primary key generation strategies provided by JPA are directly used to specify the primary key generation strategy.

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

JPA uses enumeration to define the common primary key generation strategies in 4, as follows:

Brother Guide: a usage of enumeration instead of constant

public enum GenerationType {

    /**
     *Use a specific database table to hold the primary key
     *The persistence engine generates primary keys from a specific table in a relational database,
     */
    TABLE,

    /**
     *In some databases, the self growth of primary keys is not supported, such as Oracle and PostgreSQL, which provide a mechanism called "sequence" to generate primary keys
     */
    SEQUENCE,

    /**
     *Primary key self growth
     */
    IDENTITY,

    /**
     *Give the primary key generation strategy to the persistence engine,
     *The persistence engine selects one of the three primary key generation strategies based on the database
     */
    AUTO
}

@GeneratedValueThe default policy for annotations isGenerationType.AUTO

public @interface GeneratedValue {

    GenerationType strategy() default AUTO;
    String generator() default "";
}

Generally, MySQL is usedGenerationType.IDENTITYThe strategy is more common (for distributed systems, you need to consider using distributed IDS).

2. Pass@GenericGeneratorDeclare a primary key policy, and then@GeneratedValueUse this strategy

@Id
@GeneratedValue(generator = "IdentityIdGenerator")
@GenericGenerator(name = "IdentityIdGenerator", strategy = "identity")
private Long id;

Equivalent to:

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

The primary key generation strategies provided by JPA are as follows:

public class DefaultIdentifierGeneratorFactory
        implements MutableIdentifierGeneratorFactory, Serializable, ServiceRegistryAwareService {

    @SuppressWarnings("deprecation")
    public DefaultIdentifierGeneratorFactory() {
        register( "uuid2", UUIDGenerator.class );
        register( "guid", GUIDGenerator.class );            // can be done with UUIDGenerator + strategy
        register( "uuid", UUIDHexGenerator.class );            // "deprecated" for new use
        register( "uuid.hex", UUIDHexGenerator.class );     // uuid.hex is deprecated
        register( "assigned", Assigned.class );
        register( "identity", IdentityGenerator.class );
        register( "select", SelectGenerator.class );
        register( "sequence", SequenceStyleGenerator.class );
        register( "seqhilo", SequenceHiLoGenerator.class );
        register( "increment", IncrementGenerator.class );
        register( "foreign", ForeignGenerator.class );
        register( "sequence-identity", SequenceIdentityGenerator.class );
        register( "enhanced-sequence", SequenceStyleGenerator.class );
        register( "enhanced-table", TableGenerator.class );
    }

    public void register(String strategy, Class generatorClass) {
        LOG.debugf( "Registering IdentifierGenerator strategy [%s] -> [%s]", strategy, generatorClass.getName() );
        final Class previous = generatorStrategyToClassNameMap.put( strategy, generatorClass );
        if ( previous != null ) {
            LOG.debugf( "    - overriding [%s]", previous.getName() );
        }
    }

}

8.3. Set field type

@ColumnDeclaration field.

Example:

Set the database field name corresponding to the property username as user_ Name, length is 32, not empty

@Column(name = "user_name", nullable = false, length=32)
private String userName;

Setting the field type and adding default values is quite common.

Column(columnDefinition = "tinyint(1) default 1")
private Boolean enabled;

8.4. Specify that specific fields are not persisted

@Transient: declare fields that do not need to be mapped to the database, and do not need to be saved into the database when saving.

If we want tosecrectThis field is not persisted and can be used@TransientKeyword declaration.

Entity(name="USER")
public class User {

    ......
    @Transient
    private String secrect; // not persistent because of @Transient

}

except@TransientYou can also use the following methods for keyword declaration:

static String secrect; // not persistent because of static
final String secrect = “Satish”; // not persistent because of final
transient String secrect; // not persistent because of transient

There are many ways to use annotations.

8.5. Declare large fields

@Lob: declare a field as a large field.

@Lob
private String content;

More detailed statement:

@Lob
//Specify the acquisition strategy for lob type data, FetchType.EAGER  Indicates non delayed loading, while fetchtype. Lazy means delayed loading;
@Basic(fetch = FetchType.EAGER)
//The columndefinition property specifies the lob field type corresponding to the data table
@Column(name = "content", columnDefinition = "LONGTEXT NOT NULL")
private String content;

8.6. Creating fields of enumeration type

You can use fields of enumeration type, but enumeration fields use@EnumeratedAnnotation modification.

public enum Gender {
    Male,
    Female ("female");

    private String value;
    Gender(String str){
        value=str;
    }
}
@Entity
@Table(name = "role")
public class Role {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String description;
    @Enumerated(EnumType.STRING)
    private Gender gender;
    Omit getter / setter
}

The corresponding storage in the database is mail / femail.

8.7. Add audit function

As long as we inheritAbstractAuditBaseThe following four fields are added by default.

@Data
@AllArgsConstructor
@NoArgsConstructor
@MappedSuperclass
@EntityListeners(value = AuditingEntityListener.class)
public abstract class AbstractAuditBase {

    @CreatedDate
    @Column(updatable = false)
    @JsonIgnore
    private Instant createdAt;

    @LastModifiedDate
    @JsonIgnore
    private Instant updatedAt;

    @CreatedBy
    @Column(updatable = false)
    @JsonIgnore
    private String createdBy;

    @LastModifiedBy
    @JsonIgnore
    private String updatedBy;
}

The corresponding audit function configuration class may be as follows (spring security project)


@Configuration
@EnableJpaAuditing
public class AuditSecurityConfiguration {
    @Bean
    AuditorAware<String> auditorAware() {
        return () -> Optional.ofNullable(SecurityContextHolder.getContext())
                .map(SecurityContext::getAuthentication)
                .filter(Authentication::isAuthenticated)
                .map(Authentication::getName);
    }
}

Here is a brief introduction to some notes designed above:

  1. @CreatedDate: indicates that the field is the creation time time field. When the entity is inserted, the value will be set
  2. @CreatedBy: indicates that the field is the creator. When the entity is inserted, the value will be set

    @LastModifiedDate@LastModifiedByIn the same way.

@EnableJpaAuditingOpen JPA: audit function.

8.8. Delete / modify data

@ModifyingThe annotation prompts JPA that this operation is a modification operation, and it should be cooperated with@TransactionalAnnotation use.

@Repository
public interface UserRepository extends JpaRepository<User, Integer> {

    @Modifying
    @Transactional(rollbackFor = Exception.class)
    void deleteByUserName(String userName);
}

8.9. Relationship

  • @OneToOneStatement of one-to-one relationship
  • @OneToManyDeclare a one to many relationship
  • @ManyToOneDeclare a many to one relationship
  • MangToMangDeclare many to many relationships

For more articles on spring boot JPA, please see my article: how to use JPA correctly in spring boot.

9. Affairs@Transactional

Use on the method to open the transaction@TransactionalAnnotation is enough!

@Transactional(rollbackFor = Exception.class)
public void save() {
  ......
}

We know that exceptions are divided into runtime exceptions, runtimeexceptions and non runtime exceptions. stay@TransactionalIf not configured in the annotationrollbackForProperty, then things will only encounterRuntimeExceptionAnd then roll backrollbackFor=Exception.class, which allows things to roll back when they encounter non runtime exceptions.

@TransactionalAnnotations are usually used in theclassperhapsmethodGo ahead.

  • Acting on classesWhen@When a transactional annotation is placed on a class, it represents all thePublic methods are configured with the same transaction attribute information.
  • Acting on Methods: when the class is configured@Transactional, method is also configured@TransactionalThe transaction of the method will override the transaction configuration information of the class.

For more information about spring transactions, please see:

  1. Perhaps the most beautiful spring transaction management details
  2. Say six @ transactional annotation invalidation scenarios in one breath

10. JSON data processing

10.1. Filtering JSON data

@JsonIgnorePropertiesUsed on classes to filter out specific fields that do not return or resolve.

//Filter the userroles attribute when generating JSON
@JsonIgnoreProperties({"userRoles"})
public class User {

    private String userName;
    private String fullName;
    private String password;
    @JsonIgnore
    private List<UserRole> userRoles = new ArrayList<>();
}

@JsonIgnoreIt is generally used for the properties of classes, functions and the above@JsonIgnorePropertiesThe same.

public class User {

    private String userName;
    private String fullName;
    private String password;
   //Filter the userroles attribute when generating JSON
    @JsonIgnore
    private List<UserRole> userRoles = new ArrayList<>();
}

10.2. Format JSON data

@JsonFormatIt is generally used to format JSON data. :

For example:

@JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", timezone="GMT")
private Date date;

10.3. Flattening objects

@Getter
@Setter
@ToString
public class Account {
    @JsonUnwrapped
    private Location location;
    @JsonUnwrapped
    private PersonInfo personInfo;

  @Getter
  @Setter
  @ToString
  public static class Location {
     private String provinceName;
     private String countyName;
  }
  @Getter
  @Setter
  @ToString
  public static class PersonInfo {
    private String userName;
    private String fullName;
  }
}

Before flattening:

{
    "location": {
        "Provincename": Hubei Province,
        "Countyname": Wuhan
    },
    "personInfo": {
        "userName": "coder1234",
        "fullName": "shaungkou"
    }
}

use@JsonUnwrappedAfter flattening the object:

@Getter
@Setter
@ToString
public class Account {
    @JsonUnwrapped
    private Location location;
    @JsonUnwrapped
    private PersonInfo personInfo;
    ......
}
{
  "Provincename": Hubei Province,
  "Countyname": Wuhan,
  "userName": "coder1234",
  "fullName": "shaungkou"
}

11. Test related

@ActiveProfilesIt generally acts on the test class and is used to declare the spring configuration file that takes effect.

@SpringBootTest(webEnvironment = RANDOM_PORT)
@ActiveProfiles("test")
@Slf4j
public abstract class TestBase {
  ......
}

@TestDeclare a method as a test method

@TransactionalThe data of the declared test method is rolled back to avoid contamination of the test data.

@WithMockUserSpring security provides, used to simulate a real user, and can be granted permissions.

    @Test
    @Transactional
    @WithMockUser(username = "user-id-18163138155", authorities = "ROLE_TEACHER")
    void should_import_student_success() throws Exception {
        ......
    }

Let’s sum it up for the time being! Although it took a long time to complete, some commonly used annotations may have been missed. Therefore, I synchronized the article to GitHub. GitHub address: https://github.com/Snailclimb/JavaGuide/blob/master/docs/system-design/framework/spring/spring-annotations.md Welcome to perfect!

This article has been included in my 75K star Java open source project javaguide: https://github.com/Snailclimb/JavaGuide 。