Use @value to read a list, a map

# version properties
list=l1,l2,l3
map={'k1':'v1','k2':'v2'}
Copy the code
# yaml version
Do not use "" to wrap all member values of the list, otherwise parsing error.
Map
      
        = map 
       
         = map 
        
          = map 
         
           = map 
          ,string>
         ,string>
        ,string>
       ,string>
      ,string>
list: l1,l2,l3
maps: "{k1: 'v1', k2: 'v2'}"
Copy the code
@Value("#{'${list}'.split(',')}")
private List<String> list;

@Value("#{${maps}}")  
private Map<String,String> maps;
Copy the code

Inject beans based on conditions

Annotation use of conditional injection for SpringBoot base beans

SpringBoot configures Https access

Elegant use of parameter verification

Swagger2

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.2.2</version>
</dependency>
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.2.2</version>
</dependency>
Copy the code
// Create the Swagger2 configuration class
// Create the configuration class Swagger2 for Swagger2 at the application. Java level.

@Configuration
@EnableSwagger2
public class Swagger2 {

    @Bean
    public Docket createRestApi(a) {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.didispace.web"))
                .paths(PathSelectors.any())
                .build();
    }

    private ApiInfo apiInfo(a) {
        return new ApiInfoBuilder()
                .title("Build RESTful APIs with Swagger2 in Spring Boot")
                .description("More Spring Boot related articles please attention: http://blog.didispace.com/")
                .termsOfServiceUrl("http://blog.didispace.com/")
                .contact("Programmer DD")
                .version("1.0") .build(); }}/** As shown in the code above, pass@ConfigurationAnnotation to let Spring load the class configuration. through@EnableSwagger2 annotations to enable Swagger2. After creating the Docket Bean using the createRestApi function, apiInfo() is used to create the Api's basic information, which is shown on the documentation page. The select() function returns an instance of ApiSelectorBuilder that controls which interfaces are exposed to Swagger for presentation. In this case, the package path specified for the scan is defined. Swagger scans all Controller defined apis in the package and produces document contents (except by@ApiIgnoreSpecified request). Adding document Content After completing the above configuration, you can actually produce document content. However, such documents are mainly for the request itself, and the descriptions are mainly generated by naming functions, which is not user-friendly. Therefore, you usually need to add some instructions to enrich the document content. As shown below, we pass@ApiOperationAnnotations to add clarification to the API@ApiImplicitParams,@ApiImplicitParamAnnotations to add clarification to the parameters. * /

@RestController
@RequestMapping(value="/users")     // Set the following mappings under /users, which can be removed
public class UserController {

    static Map<Long, User> users = Collections.synchronizedMap(new HashMap<Long, User>());

    @apiOperation (value=" get user list ", notes="")
    @RequestMapping(value={""}, method=RequestMethod.GET)
    public List<User> getUserList(a) {
        List<User> r = new ArrayList<User>(users.values());
        return r;
    }

    @apiOperation (value=" create User ", notes=" create User from User object ")
    @APIIMPLICITParam (name = "user", value = "user detail entity user", Required = true, dataType = "user")
    @RequestMapping(value="", method=RequestMethod.POST)
    public String postUser(@RequestBody User user) {
        users.put(user.getId(), user);
        return "success";
    }

    @apiOperation (value=" get user details ", notes=" get user details based on URL ID ")
    @APIIMPLICITParam (name = "id", value = "user ID", Required = true, dataType = "Long")
    @RequestMapping(value="/{id}", method=RequestMethod.GET)
    public User getUser(@PathVariable Long id) {
        return users.get(id);
    }

    @apiOperation (value=" update user details ", notes=" specify update object based on URL ID and update user details based on passed user information ")
    @APIIMPLICITParams ({@APIIMPLICITParam (name = "id", value = "user ID", Required = true, dataType = "Long"), @APIIMPLICITParam (name = "user", value = "user detail entity user", Required = true, dataType = "user")})
    @RequestMapping(value="/{id}", method=RequestMethod.PUT)
    public String putUser(@PathVariable Long id, @RequestBody User user) {
        User u = users.get(id);
        u.setName(user.getName());
        u.setAge(user.getAge());
        users.put(id, u);
        return "success";
    }

    @apiOperation (value=" delete user ", notes=" specify delete object based on URL ID ")
    @APIIMPLICITParam (name = "id", value = "user ID", Required = true, dataType = "Long")
    @RequestMapping(value="/{id}", method=RequestMethod.DELETE)
    public String deleteUser(@PathVariable Long id) {
        users.remove(id);
        return "success"; }}Copy the code

Async

Async(@statis); Async(@statis); Async(@statis); Async(@statis); Custom thread poolsCopy the code
// Start by defining a thread pool in the Spring Boot main class, for example:
@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @EnableAsync
    @Configuration
    class TaskPoolConfig {

        @Bean("taskExecutor")
        public Executor taskExecutor(a) {
            ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
            executor.setCorePoolSize(10);
            executor.setMaxPoolSize(20);
            executor.setQueueCapacity(200);
            executor.setKeepAliveSeconds(60);
            executor.setThreadNamePrefix("taskExecutor-");
            executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
            returnexecutor; }}}/** We created a thread pool using ThreadPoolTaskExecutor with the following parameters: core threads 10: maximum number of threads initialized at pool creation time 20: The maximum number of threads in the thread pool will only apply for more than the number of core threads in the thread buffer queue when the buffer queue is full 200: the number of idle seconds allowed by the thread buffer queue to execute the task 60: The number of threads that exceed the core thread will be destroyed when the idle time expires. After this setting, we can conveniently locate the thread pool where the processing task resides. The processing policy of the thread pool on the rejected task is as follows: CallerRunsPolicy policy is adopted here. When the thread pool has no processing capability, this policy will directly run the rejected task in the calling thread of the Execute method. If the executor is closed, the task is discarded using a thread pool Once a thread pool is defined, how do we get asynchronously invoked execution tasks to run using resources from this thread pool? The method is very simple, we just need to in@AsyncSpecify the thread pool name in the annotation, for example: */

@Slf4j
@Component
public class Task {

    public static Random random = new Random();

    @Async("taskExecutor")
    public void doTaskOne(a) throws Exception {
        log.info("Start on task one.");
        long start = System.currentTimeMillis();
        Thread.sleep(random.nextInt(10000));
        long end = System.currentTimeMillis();
        log.info("Complete Task 1, Time:" + (end - start) + "毫秒");
    }

    @Async("taskExecutor")
    public void doTaskTwo(a) throws Exception {
        log.info("Start on task two.");
        long start = System.currentTimeMillis();
        Thread.sleep(random.nextInt(10000));
        long end = System.currentTimeMillis();
        log.info("Complete Task 2, Time:" + (end - start) + "毫秒");
    }

    @Async("taskExecutor")
    public void doTaskThree(a) throws Exception {
        log.info("Start on task three.");
        long start = System.currentTimeMillis();
        Thread.sleep(random.nextInt(10000));
        long end = System.currentTimeMillis();
        log.info("Complete Task 3, Time:" + (end - start) + "毫秒"); }}// Unit tests
// Finally, let's write a unit test to verify

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class ApplicationTests {

    @Autowired
    private Task task;

    @Test
    public void test(a) throws Exception {

        task.doTaskOne();
        task.doTaskTwo();
        task.doTaskThree();
        // Wait for all child threads to terminateThread.currentThread().join(); }}Copy the code

Global exception handling

@RestControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(value = RateLimitException.class)
		public ResponseVO exceptionHandler(RateLimitException e){
		return newResponseVO(e.getResponseStatus()); }}Copy the code

Cross-domain problem handling

/ * * -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 1. Global cross-domain CorsFilter -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - * /
@Configuration
public class GlobalCorsConfig {
    @Bean
    public CorsFilter corsFilter(a) {
        //1. Add CORS configuration information
        CorsConfiguration config = new CorsConfiguration();
          // Which primitive fields are allowed
          config.addAllowedOrigin("*");
          // Whether to send Cookie information
          config.setAllowCredentials(true);
          // Which primitive fields are allowed (request mode)
          config.addAllowedMethod("*");
          // Which raw fields are allowed (header information)
          config.addAllowedHeader("*");
          // Which headers to expose (because cross-domain access does not get all headers by default)
          config.addExposedHeader("*");

        //2. Add a mapping path
        UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
        configSource.registerCorsConfiguration("/ * *", config);

        //3. Return a new CorsFilter.
        return newCorsFilter(configSource); }}/ * * -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 2. Global cross-domain rewrite WebMvcConfigurer -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - * /
@Configuration
public class GlobalCorsConfig {
    @Bean
    public WebMvcConfigurer corsConfigurer(a) {
        return new WebMvcConfigurer() {
            @Override
            // Override the interface provided by the parent class for cross-domain request processing
            public void addCorsMappings(CorsRegistry registry) {
                // Add a mapping path
                registry.addMapping("/ * *")
                        // Which primitive fields are allowed
                        .allowedOrigins("*")
                        // Whether to send Cookie information
                        .allowCredentials(true)
                        // Which primitive fields are allowed (request mode)
                        .allowedMethods("GET"."POST"."PUT"."DELETE")
                        // Which raw fields are allowed (header information)
                        .allowedHeaders("*")
                        // Which headers to expose (because cross-domain access does not get all headers by default)
                        .exposedHeaders("Header1"."Header2"); }}; }}/** -------------------- 3.@CrossOriginYou can also put@Controller] -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - * /
@RequestMapping("/hello")
@ResponseBody
@CrossOrigin("http://localhost:8080") 
public String index( ){
  return "Hello World";
}

/ * * -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 4. Local cross-domain manually set response headers -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - * /
response.addHeader("Access-Control-Allow-Origin"."http://localhost:8080");
Copy the code

Feign Sets the timeout period

ribbon.ConnectTimeout=5000
ribbon.ReadTimeout=5000
Copy the code

Send E-mail

/** Start by introducing the spring-boot-starter-mail dependency in pm.xml:  
       
       
        org.springframework.boot
        
       
        spring-boot-starter-mail
        
       Like other automated configuration modules, after dependency introduction is complete, only the corresponding property content needs to be configured in application.properties. Add the following configuration to the application. Properties file (pay attention to replace your own username and password) : Spring.mail.host=smtp.qq.com spring.mail.username= username spring.mail.password= password spring.mail.properties.mail.smtp.auth=true spring.mail.properties.mail.smtp.starttls.enable=true Spring. The mail. The properties. The mail. The SMTP. Starttls. Required = true sent via a unit test to achieve a simple E-mail: * /

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
public class ApplicationTests {

	@Autowired
	private JavaMailSender mailSender;

	@Test
	public void sendSimpleMail(a) throws Exception {
		SimpleMailMessage message = new SimpleMailMessage();
		message.setFrom("[email protected]");
		message.setTo("[email protected]");
		message.setSubject("Subject: Simple Email");
		message.setText("Test email content"); mailSender.send(message); }}In the example above, we can use SimpleMailMessage to send a simple email, but in practice we can also use attachments, mail modules, etc. At this time, we need to use MimeMessage to set up a more complex message content, let's implement it in turn. Add the following test case to the unit test above (using MimeMessageHelper to send an email with an attachment) : */

@Test
public void sendAttachmentsMail(a) throws Exception {

	MimeMessage mimeMessage = mailSender.createMimeMessage();

	MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
	helper.setFrom("[email protected]");
	helper.setTo("[email protected]");
	helper.setSubject("Subject: Attached");
	helper.setText("Attached mail");

	FileSystemResource file = new FileSystemResource(new File("weixin.jpg"));
	helper.addAttachment("Appendix 1. JPG", file);
	helper.addAttachment("Appendix - 2. JPG", file);

	mailSender.send(mimeMessage);

}

In addition to sending attachments, we may want to embed static resources such as images in the email content to make the email better to read, rather than viewing specific images from the attachment. The following test case demonstrates how to embed static resources in the email body using MimeMessageHelper. * /

@Test
public void sendInlineMail(a) throws Exception {

	MimeMessage mimeMessage = mailSender.createMimeMessage();

	MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
	helper.setFrom("[email protected]");
	helper.setTo("[email protected]");
	helper.setSubject("Topic: Embedding Static Resources");
	helper.setText("<html><body><img src=\"cid:weixin\" ></body></html>".true);

	FileSystemResource file = new FileSystemResource(new File("weixin.jpg"));
	helper.addInline("weixin", file);

	mailSender.send(mimeMessage);

}

/** The name of the resource in the addInline function must correspond to the name of the resource in the body cid:weixin. Only a small portion of the content sent to each user may change. So, a lot of times we use a template engine to set up a template for various types of mail, so that we only need to replace the changing part of the parameter when sending. It is also very easy to use the templating engine in Spring Boot to implement templated mail delivery, using Velocity as an example. Introducing velocity module dependencies:  
       
       
        org.springframework.boot
        
       
        spring-boot-starter-velocity
        
       Under resources/templates/, create a template page template.vm: < HTML >  

We added a test case for sending template mail to the unit test as follows: */
@Test public void sendTemplateMail(a) throws Exception { MimeMessage mimeMessage = mailSender.createMimeMessage(); MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true); helper.setFrom("[email protected]"); helper.setTo("[email protected]"); helper.setSubject("Subject: Template Mail"); Map<String, Object> model = new HashedMap(); model.put("username"."didi"); String text = VelocityEngineUtils.mergeTemplateIntoString( velocityEngine, "template.vm"."UTF-8", model); helper.setText(text, true); mailSender.send(mimeMessage); } // Try running it, and you'll get hello, Didi, this is a template email! In the mail. Here, we replace the ${username} variable in the template in the message content by passing in the username parameter. Copy the code

Integrating the RabbitMQ

/** 
       
       
        org.springframework.boot
        
       
        spring-boot-starter-amqp
        
        Configure RabbitMQ connections and user information in application.properties, and users can go back to the installation above and create users in the admin page. spring.application.name=rabbitmq-hello spring.rabbitmq.host=localhost spring.rabbitmq.port=5672 Rabbitmq. username=spring spring. Rabbitmq. password=123456 Create a Sender. Messages are sent by injecting an instance of the AmqpTemplate interface, which defines a set of basic operations for the AMQP protocol. Its concrete implementation is injected in Spring Boot based on configuration. At that producer, we generate a string and send it to a queue named Hello. * /
      
@Component
public class Sender {

    @Autowired
    private AmqpTemplate rabbitTemplate;

    public void send(a) {
        String context = "hello " + new Date();
        System.out.println("Sender : " + context);
        this.rabbitTemplate.convertAndSend("hello", context); }}Create a message consumer Receiver. The @RabbitListener annotation defines the class to listen on the Hello queue, and the @Rabbithandler annotation specifies what to do with the message. So, the consumer implements consumption of the Hello queue to output the string content of the message.
@Component
@RabbitListener(queues = "hello")
public class Receiver {

    @RabbitHandler
    public void process(String hello) {
        System.out.println("Receiver : "+ hello); }}// Create the RabbitMQ configuration class RabbitConfig to configure advanced information such as queues, switches, and routes. Here we will focus on getting started, with minimal configuration defined to complete a basic production and consumption process.
@Configuration
public class RabbitConfig {

    @Bean
    public Queue helloQueue(a) {
        return new Queue("hello"); }}// Create the main application class:
@SpringBootApplication
public class HelloApplication {

    public static void main(String[] args) { SpringApplication.run(HelloApplication.class, args); }}// Create a unit test class that calls message production:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = HelloApplication.class)
public class HelloApplicationTests {

    @Autowired
    private Sender sender;

    @Test
    public void hello(a) throws Exception { sender.send(); }}/** Now that the program is complete, let's try to run it. First make sure RabbitMQ Server has started, then do the following: start the main application class. From the console, we can see that the application has created a connection to springcloud in 127.0.0.1:5672. o.s.a.r.c.CachingConnectionFactory : Created new connection: SimpleConnection@29836d32 [delegate=amqp://[email protected]:5672/] Meanwhile, via the RabbitMQ control panel, You can see that Connection and Channels contain entries for the current Connection. Running the unit test class, we can see the following output from the console: the message is sent to the RabbitMQ Server's Hello queue. Sender: Hello Sun Sep 25 11:06:11 CST 2016 Switch to the console of the application main class, we can see output like the following, the consumer executes on the listener of the Hello queue and prints the received message information. Receiver : hello Sun Sep 25 11:06:11 CST 2016 */
Copy the code

Loading XML configuration

@Configuration
@ImportResource(locations = { "classpath*:META-INF/config/spring/*.xml" })
public class SpringXmlConfiguration {

    private final static Logger LOGGER = LoggerFactory.getLogger(SpringXmlConfiguration.class);

    public SpringXmlConfiguration(a) {
        LOGGER.info("Spring xml configuration initialized..."); }}Copy the code