Why write this article?

Recently, I saw an article about SpringBoot common annotations on the Internet that has been reprinted a lot. After reading the article, I really think the quality is a little low, and a little misleading to people who don’t have much practical experience in using SpringBoot (these people occupy the majority). So, I simply spent about two days to sum up.

Because my personal ability and energy are limited, if there is any wrong or need to improve, please help to point out! Guide brother is very grateful!

1. @SpringBootApplication

I’m going to point out the @SpringBootApplication annotation, although we don’t usually use it actively.

Guide: This annotation is the cornerstone of the SpringBoot project and is added to the main class by default after a SpringBoot project is created.

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

We can think of @SpringBootApplication as a collection of @Configuration, @EnableAutoConfiguration, and @ComponentScan 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 {

}
Copy the code

According to The SpringBoot website, the three annotations are:

  • @EnableAutoConfiguration: Enables SpringBoot automatic configuration
  • @ComponentScan: scan be@Component (@Service.@ControllerAnnotated beans, which by default scan all classes in the package that class is in.
  • @Configuration: Allows registering additional beans or importing additional configuration classes in the Spring context

2. Spring Bean correlation

2.1. @Autowired

Automatically import objects into classes. The injected classes are also managed by the Spring container. For example, the Service class is injected into the Controller class.

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

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

We typically use the @Autowired annotation to have the Spring container automatically assemble our beans for us. To identify a class as a bean that can be used with the @AutoWired annotation auto-assembly, use the following annotation:

  • @Component: generic annotation that can mark any class asSpringComponents. This can be used if a Bean does not know which layer it belongs to@ComponentAnnotation annotation.
  • @Repository: Corresponds to the Dao layer, which is mainly used for database operations.
  • @Service: Corresponds to the service layer, which mainly involves some complex logic and requires the Dao layer.
  • @Controller: Corresponds to the Spring MVC control layer, which is mainly used to accept user requests and call the Service layer to return data to the front-end page.

2.3. @RestController

The @RestController annotation is a combination of @Controller and @responseBody, indicating that this is a Controller bean and that the return value of the function is inserted directly into the body of the HTTP response, which is a REST-style Controller.

Guide brother: Now are front and back end separation, to tell the truth I have not used for a long time@Controller. If your project is too old, forget it.

Using @controller alone without @responseBody is usually used when you want to return a view, which is a more traditional Spring MVC application, corresponding to the case where the front and back end are not separated. @controller + @responseBody Returns JSON or XML data

For a comparison of @RestController and @Controller, see this article: @RestController vs @Controller.

2.4. @Scope

Declare the scope of the Spring Bean using:

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

There are four common Spring Bean scopes:

  • Singleton: A unique 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 for the current HTTP session.

2.5. @Configuration

The @Component annotation is used to declare Configuration classes, but using the @Configuration annotation to declare Configuration classes is more semantic.

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

3. Handle common HTTP request types

There are five common request types:

  • GET: Requests a specific resource from the server. Here’s an example:GET /users(Get all students)
  • POST: Creates a new resource on the server. Here’s an example:POST /users(Create student)
  • PUT: Updates the resource on the server (the client provides the updated entire resource). Here’s an example:PUT /users/12(Update student no. 12)
  • DELETE: Deletes a specific resource from the server. Here’s an example:DELETE /users/12(Delete student no. 12)
  • PATCH: Updates resources on the server (the client provides the changed properties, which can be regarded as partial updates). It is rarely used, so there are no examples here.

3.1. The GET request

@getMapping (“users”) = @requestMapping (value=”/users”,method= requestmethod.get)

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

3.2. A POST request

@postmapping (“users”) = @requestMapping (value=”/users”,method= requestmethod.post)

The use of the @RequestBody annotation is covered in the section “Passing values back and forth” below.

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

3.3 PUT request

@putMapping (“/users/{userId}”) = @requestMapping (value=”/users/{userId}”,method= requestmethod.put)

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

3.4. The DELETE request

@deletemapping (“/users/{userId}”) = @requestMapping (value=”/users/{userId}”,method= requestmethod.delete)

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

3.5. PATCH request

In general, in actual projects, PATCH request is used to update data after PUT is insufficient.

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

4. Send values to the front and back ends

Mastering the correct posture for passing values back and forth is your first step to CRUD!

4.1. @PathVariable@RequestParam

@pathVariable is used to get path parameters, and @requestParam is used to get query parameters.

Here’s a simple example:

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

/klasses/{123456}/teachers? type=web

KlassId =123456,type=web.

4.2. @RequestBody

It is used to read the body of a Request (POST,PUT,DELETE,GET) and its content-type is in application/ JSON format. After receiving the data, it will automatically bind the data to a Java object. The system uses HttpMessageConverter or a custom HttpMessageConverter to convert the JSON string in the body of the request 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();
}
Copy the code

UserRegisterRequest objects:

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

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

{"userName":"coder","fullName":"shuangkou","password":"123456"}
Copy the code

This allows our back end to map json data directly to oursUserRegisterRequestOn the class.Note that:There can only be one request method@RequestBodyBut there can be more than one@RequestParamand@PathVariable. If your method has to use two@RequestBodyTo accept the data, the probability is your database design or system design problems!

5. Read the configuration information

Most of the time, we need to put some common configuration information, such as Ali cloud OSS, SMS, wechat authentication and other relevant configuration information into the configuration file.

Let’s take a look at some of the ways That Spring provides us to read this configuration information from a configuration file.

Our data source application.yml is as follows:

At the beginning of 2020, there was a novel Coronavirus outbreak in Wuhan. However, I believe that everything will pass! Come on, Wuhan! Come on China! My-profile: Name: Guide Email: [email protected] Library: Location: Wuhan, Hubei, Come On, China come on books: - name: Genius Basic Law Description: Lin Zhaoxi, 22, was diagnosed with Alzheimer's disease when he learned that pei Zhi, the campus boy he had been in love with for years, was going abroad for further study -- the school he was admitted to was the one his father had given up for her. - Name: Order of time description: Why do we remember the past and not the future? What does it mean for time to "go by"? Do we exist within time, or does time exist within us? In poetic prose, Carlo Rovelli invites us to consider this age-old conundrum: the nature of time. Description: How to make a new habit? How to let the mind become more mature? How to have quality relationships? How do you get through tough times in your life?Copy the code

5.1. @value(common)

Use @value (“${property}”) to read simpler configuration information:

@Value("${wuhan2020}")
String wuhan2020;
Copy the code

5.2. @ConfigurationProperties(common)

The configuration information is read and bound to the bean via @ConfigurationProperties.

@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...... }Copy the code

You can inject it into a class just like you would with a normal Spring bean.

5.3. PropertySource(not often used)

PropertySource Reads the specified properties file

@Component @PropertySource("classpath:website.properties") class WebSite { @Value("${url}") private String url; Omit the getter/setter... }Copy the code

For more on SpringBoot: How to Gracefully Load Configuration Files in 10 Minutes? .

6. Verify parameters

The importance of data verification goes without saying. Even in the case of data verification in the front end, we still need to verify the data passed to the back end again to avoid users bypassing the browser directly through some HTTP tools directly request some illegal data to the back end.

JSR(Java Specification Requests) is a set of Java Specification Requests (JSR) standards for validation of JavaBean parameters. It defines a number of commonly used validation annotations that can be added directly to the properties of javabeans so that validation can be performed when needed. Very convenient!

We actually use the Hibernate Validator framework for validation. Hibernate Validator 4.x is a reference implementation for Bean Validation 1.0 (JSR 303). Hibernate Validator 5.x is a reference implementation for Bean Validation 1.1 (JSR 349). The latest version of Hibernate Validator 6.x is a reference implementation for Bean Validation 2.0 (JSR 380).

The SpringBoot project already has the Hibernate-Validator package in its spring-boot-starter-web dependency and does not need to reference the dependency. As shown below (via the IDEA plugin — Maven Helper) :Non-springboot projects need to import their own dependency packages, which I won’t explain here. For details, see my article:How to verify parameters in Spring/Spring Boot? Everything you need to know is here!”. Note that:For all annotations, it is recommended to use JSR annotations, i.ejavax.validation.constraintsRather thanorg.hibernate.validator.constraints

6.1. Some common annotations for field validation

  • @NotEmptyThe annotated string cannot be null or null
  • @NotBlankThe annotated string is non-null and must contain a non-whitespace 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 whose value must be greater than or equal to the specified minimum
  • @Max(value)The annotated element must be a number whose value must be less than or equal to the specified maximum
  • @DecimalMin(value)The annotated element must be a number whose value must be greater than or equal to the specified minimum
  • @DecimalMax(value)The annotated element must be a number whose value must be less than or equal to the specified maximum
  • @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. Validating the RequestBody

@data @allargsconstructor @noargsconstructor public class Person {@notnull (message = "classId cannot be null ") private String classId; @size (Max = 33) @notnull (message = "name cannot be empty ") private String name; @Pattern(regexp = "((^Man$|^Woman$|^UGM$))", Message = "sex ") @notnull (message = "sex ") private String sex; @email (message = "Email format is incorrect ") @notnull (message =" Email cannot be empty ") private String Email; }Copy the code

We need to verify the parameters with the @ Valid annotations, if validation fails, it throws MethodArgumentNotValidException.

@RestController @RequestMapping("/api") public class PersonController { @PostMapping("/person") public ResponseEntity<Person> getPerson(@RequestBody @Valid Person person) { return ResponseEntity.ok().body(person); }}Copy the code

6.3. Validate the Request Parameters (Path Variables and Request Parameters)

Make sure, make sure you don’t forget to add to the classValidatedAnnotated, this parameter tells Spring to validate method arguments.

@RestController @RequestMapping("/api") @Validated public class PersonController { @GetMapping("/person/{id}") public ResponseEntity<Integer> getPersonByID(@valid@pathVariable ("id") @max (value = 5,message = "out of id") Integer id) {ResponseEntity<Integer> getPersonByID(@valid@pathvariable ("id") @max (value = 5,message =" out of id") Integer id) { return ResponseEntity.ok().body(id); }}Copy the code

For more information on how to validate parameters in Spring projects, see “How to Validate Parameters in Spring/Spring Boot?” This article.

7. Handle the Controller layer exception globally

Describe the global handling of Controller layer exceptions that our Spring project must have.

Related notes:

  1. @ControllerAdviceAnnotation defines the global exception handling class
  2. @ExceptionHandler: annotation declares exception handling methods

How do you use it? Take, for example, the section on parameter verification in Section 5. If the method parameters wrong words will be thrown MethodArgumentNotValidException, we to handle this exception.

@controlleradvice @responseBody public class GlobalExceptionHandler {/** * Request exception handling */ @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity<? > handleMethodArgumentNotValidException(MethodArgumentNotValidException ex, HttpServletRequest request) { ...... }}Copy the code

For more on Spring Boot exception handling, see my two articles:

  1. SpringBoot handles several common poses for exceptions
  2. Use enumerations to simply encapsulate an elegant Spring Boot global exception handling!

8. JPA

8.1. Create the tables

Entity declares that a class corresponds to a database Entity.

@table Sets the Table name

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

8.2. Create a primary key

@id: Declare a primary key for a field.

After using the @ID declaration, we also need to define a primary key generation strategy. We can specify a primary key generation strategy using @GeneratedValue.

1. By@GeneratedValueSpecify the primary key generation strategy directly using the four primary key generation strategies provided by JPA built-in.

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

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

Guide: An alternative use of enumerations for constants

Public enum GenerationType {/** * The persistence engine generates the primary key from a specific TABLE in the relational database, */ TABLE, /** * Some databases do not support self-growth of primary keys. For example, Oracle and PostgreSQL provide a mechanism called "sequence" to generate primary key */ sequence, /** * self-growth of primary keys */ IDENTITY, /** * Pass the primary key generation strategy to the persistence engine, which will choose one of the three primary key generation strategies based on the database */ AUTO}Copy the code

The @GeneratedValue annotation uses the generationType.auto policy by default

public @interface GeneratedValue {

    GenerationType strategy() default AUTO;
    String generator() default "";
}
Copy the code

Generationtype. IDENTITY is a common policy for MySQL databases (distributed ids are also considered for distributed systems).

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

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

Is equivalent to:

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

Jpa provides the following primary key generation strategies:

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() ); }}}Copy the code

8.3. Set the field type

@column declares the field.

Example:

Set the name of the database field corresponding to userName to user_name. The length is 32 and the field is not empty

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

Set the field type and add the default value, this is quite common.

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

8.4. Specify not to persist a specific field

@TRANSIENT: declare a field that does not need to be mapped to the database and does not need to be saved to the database when saved.

If we want secrect not to be persisted, we can declare it with the @TRANSIENT keyword.

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

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

}
Copy the code

In addition to the @TRANSIENT keyword declaration, you can also use the following methods:

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
Copy the code

There are many ways to use annotations.

8.5. Declare large fields

@lob: Declares a field as a large field.

@Lob
private String content;
Copy the code

A more detailed statement:

Fetchtype. EAGER indicates non-lazy loading, and fetchtype. LAZY indicates LAZY loading. @basic (fetch = fetchtype.eager) //columnDefinition specifies the Lob type of the data table. @column (name = "content", columnDefinition = "LONGTEXT NOT NULL") private String content;Copy the code

8.6. Create fields of enumeration type

You can use fields of Enumerated type, but the Enumerated fields are decorated with the @Enumerated annotation.

Public enum Gender {MALE(" MALE "), FEMALE(" FEMALE "); private String value; Gender(String str){ value=str; }}Copy the code
@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 the getter/setter... }Copy the code

MAIL/FEMAIL is stored in the database.

8.7. Add the audit function

Any class that inherits AbstractAuditBase will have the following four fields 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; }Copy the code

The corresponding configuration class for our audit function might look like this (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); }}Copy the code

A brief introduction to some of the comments designed above:

  1. @createdDate: indicates that this field is the creation time field, and the value will be set when the entity is inserted

  2. @createdby: indicates that the field is the creator, and the value is set when the entity is inserted

    @lastModifiedDate, @lastModifiedby.

@enablejpaauditing: Enable the JPA auditing function.

8.8. Delete/Modify data

The @Transactional annotation indicates to JPA that this operation is a modification operation. Note that this operation is also used with the @Transactional annotation.

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

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

8.9. Correlation

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

For more on Spring Boot JPA, see my article: Learn how to use JPA correctly in Spring Boot.

9. The transaction@Transactional

Use the @Transactional annotation on the method you want to start the transaction!

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

Copy the code

We know that exceptions are divided into run-time exceptions and non-run-time exceptions. Without the rollbackFor attribute configured in the @Transactional annotation, things will only rollback when they encounter runtimeExceptions. With rollbackFor= exception.class, things can rollback when they encounter non-runtime exceptions.

The @Transactional annotation is usually used to implement classes or methods.

  • On the class: when theThe @Transactional annotation, when placed ona class, represents all the Transactional annotations of that classPublic methods are configured with the same transaction property information.
  • Method of action: When the class is configured@TransactionalThe method is also configured@TransactionalThe method’s transaction overrides the transaction configuration information of the class.

To learn more about Spring transactions, see:

  1. Probably the most beautiful explanation of Spring transaction management
  2. Rattle off six @Transactional annotation failure scenarios

10. Json data processing

10.1. Filtering JSON Data

@JsonIgnorePropertiesUsed on a class to filter out specific fields without returning or parsing.

@jsonIgnoreProperties ({"userRoles"}) public class User {private String userName; private String fullName; private String password; @JsonIgnore private List<UserRole> userRoles = new ArrayList<>(); }Copy the code

@JsonIgnoreCommonly used on class properties, and above@JsonIgnorePropertiesThe same.

public class User { private String userName; private String fullName; private String password; @jsonignore Private List<UserRole> userRoles = new ArrayList<>(); }Copy the code

10.2. Formatting JSON Data

JsonFormat is used to format JSON data. :

Such as:

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

10.3. Flatten 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; }}Copy the code

Before flattening:

ProvinceName: {" localname ": {"countyName":" wuhan "}, "personInfo": {"userName": "coder1234", "fullName": "shaungkou" } }Copy the code

After using the @jsonunwrapped flat object:

@Getter @Setter @ToString public class Account { @JsonUnwrapped private Location location; @JsonUnwrapped private PersonInfo personInfo; . }Copy the code
{"provinceName":" Hubei ", "countyName":" Wuhan ", "userName": "coder1234", "fullName": "shaungkou"}Copy the code

11. Test relevance

@ActiveProfilesTypically used on test classes to declare valid Spring configuration files.

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

@TestDeclare a method as a test method

@TransactionalData for declared test methods is rolled back to avoid contaminating test data.

@WithMockUserProvided by Spring Security to simulate a real user and grant permissions.

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

By Snailclimb link: SpringBoot+Spring Common notes summary source: Github