Spring Boot IO

1、Caching

1.1、Supported Cache Providers

1.1.1、 Generic

1.1.2、 JCache (JSR-107)

1.1.3、Hazelcast

1.1.4、Infinispan

1.1.5、Couchbase

1.1.6、Redis

1.1.6.1、引入依赖

  <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-redis</artifactId>
  </dependency>

1.1.6.2、配置RestTemplate实例

import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;

import static org.springframework.data.redis.serializer.StringRedisSerializer.UTF_8;

@EnableCaching
@Configuration
public class RedisConfig {

    @Bean
    @SuppressWarnings(value = {"rawtypes" })
    public RedisTemplate<String, Object> redisTemplate(final RedisConnectionFactory connectionFactory) {
        final RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);

        template.setKeySerializer(UTF_8);
        template.setValueSerializer(UTF_8);

        template.setHashKeySerializer(UTF_8);
        template.setHashValueSerializer(UTF_8);

        template.afterPropertiesSet();
        return template;
    }

}

1.1.6.2、缓存的设置和读取

读写缓存序列化参考 Jackson工具类

1.1.7. Caffeine

1.1.8. Cache2k

1.1.9. Simple

1.1.10. None

2、Hazelcast

3、Quartz Scheduler

4、Sending Email

5、Validation

5.1、验证手机号是否有效示例

5.1.1、引入依赖

  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
  </dependency>

5.1.2、定义验证注解类

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE_USE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import javax.validation.Constraint;
import javax.validation.Payload;

@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = { MobileValidator.class })
public @interface IsMobile {

    boolean required() default true;

    String message() default "手机号码格式错误";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

}

5.1.3、定义验证核心类

import static org.springframework.util.StringUtils.hasText;

import java.util.regex.Pattern;

public class MobileValidator implements javax.validation.ConstraintValidator<IsMobile, String> {

    private static final Pattern mobile_pattern = Pattern.compile("[1]([3-9])[0-9]{9}$");
    private boolean              required       = false;

    @Override
    public boolean isValid(String value, javax.validation.ConstraintValidatorContext context) {
        if (required) {
            return isMobile(value);
        } else {
            if (!hasText(value)) {
                return true;
            } else {
                return isMobile(value);
            }
        }
    }

    @Override
    public void initialize(IsMobile constraintAnnotation) {
        required = constraintAnnotation.required();
    }

    private boolean isMobile(String mobile) {
        if (!hasText(mobile)) {
            return false;
        }

        return mobile_pattern.matcher(mobile).matches();
    }
}

5.1.4、验证异常统一处理

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;

import org.springframework.util.CollectionUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice
public class GlobalExceptionAdvice {

    /**
     * 参数校验不通过时抛出的异常处理
     * 针对 {@code @org.springframework.web.bind.annotation.PathVariable}和{@code @org.springframework.web.bind.annotation.RequestParam}获取参数的方式
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public Map<String, Object> handleConstraintViolationException(ConstraintViolationException e) {
        final Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
        if (!CollectionUtils.isEmpty(constraintViolations)) {
            for (ConstraintViolation<?> constraintViolation : constraintViolations) {
                return new HashMap<String, Object>(2) {

                    {
                        put("code", 500);
                        put("msg", constraintViolation.getMessage());
                    }

                };
            }
        }

        return new HashMap<String, Object>(2) {

            {
                put("code", 500);
                put("msg", "参数异常");
            }

        };
    }

    /**
     * 参数校验不通过时抛出的异常处理
     * 针对{@code @org.springframework.web.bind.annotation.RequestBody}获取参数的方式 
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Map<String, Object> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        final BindingResult bindingResult = e.getBindingResult();
        if (Objects.nonNull(bindingResult)) {
            final List<FieldError> fieldErrors = bindingResult.getFieldErrors();
            if (!CollectionUtils.isEmpty(fieldErrors)) {
                for (FieldError fieldError : fieldErrors) {
                    return new HashMap<String, Object>(2) {

                        {
                            put("code", 500);
                            put("msg", fieldError.getDefaultMessage());
                        }

                    };
                }
            }
        }

        return new HashMap<String, Object>(2) {

            {
                put("code", 500);
                put("msg", "参数异常");
            }

        };
    }

}

5.1.5、控制器引入验证

注意事项:

  • 针对@RequestParam或@PathVariable注解参数验证,须要在类上添加@Validated;
  • 使用@RequestBody注解参数验证,须要在该参数前加@Validated;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;

import java.util.Collections;
import java.util.Map;
import java.util.UUID;

import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;

import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Validated
public class IndexController {

    @GetMapping(path = "/index", produces = APPLICATION_JSON_VALUE)
    public Map<String, Object> execute(@RequestParam @Min(value = 1, message = "年龄不能小于 7周岁") @Max(value = 20, message = "年龄不能大于18周岁") Integer age,
            @RequestParam @NotBlank(message = "姓名不能为空") String name,
            @RequestParam @NotBlank(message = "手机号不能为空") @IsMobile String mobile) {
        return Collections.singletonMap("uuid", UUID.randomUUID());
    }

    @PostMapping(path = "/show", produces = APPLICATION_JSON_VALUE)
    public Map<String, Object> handlerValidated(@Validated @RequestBody Student student) {
        return Collections.singletonMap("uuid", UUID.randomUUID());
    }
}

class Student {

    @Min(value = 1, message = "年龄不能小于 7周岁")
    @Max(value = 18, message = "年龄不能大于18周岁")
    private int age;

    @NotBlank(message = "姓名不能为空")
    private String name;

    @NotBlank(message = "手机号不能为空")
    @IsMobile
    private String mobile;

    public int getAge() {
        return age;
    }

    public String getName() {
        return name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getMobile() {
        return mobile;
    }

    public void setMobile(String mobile) {
        this.mobile = mobile;
    }

}

5.1.6、启动服务验证

$ curl -L -X GET 'http://127.0.0.1:8080/index?age=10&name=Jbos&mobile=13800138000' -H 'Content-Type: application/json'
{"uuid": "94694a9e567241999bd4259aca7b7e7a"}

$ curl -L -X GET 'http://127.0.0.1:8080/index?age=1&name=Jbos&mobile=13800138000' -H 'Content-Type: application/json'
{"code": 500, "msg": "年龄不能小于 7周岁"}

$ curl -L -X POST 'http://127.0.0.1:8080/show' -H 'Accept: application/json' -H 'Content-Type: application/json' --data-raw '{"age": 10, "name": "Jobs", "mobile": "03800138000"}'
{"uuid": "94694a9e567241999bd4259aca7b7e7a"}

$ curl -L -X POST 'http://127.0.0.1:8080/show' -H 'Accept: application/json' -H 'Content-Type: application/json' --data-raw '{"age": 1, "name": "Jobs", "mobile": "03800138000"}'
{"code": 500, "msg": "年龄不能小于 7周岁"}

6、Calling REST Services

7、Web Services

8、Distributed Transactions With JTA

9、What to Read Next

posted @ 2022-11-07 23:02  Bruce.Chang.Lee  阅读(174)  评论(0编辑  收藏  举报