# SpringBoot 学习

# 参数校验

# 简单校验@Valid

@Slf4j
@Api(value = "User Interfaces",tags = "User Interfaces")
@RestController
@RequestMapping("/user")
public class UserController {
    @ApiOperation("Add User")
    @ApiImplicitParam(name="userParam",type="body",dataTypeClass = UserParam.class,required = true)
    @PostMapping("add")
    public ResponseEntity<String> add(@Valid @RequestBody UserParam userParam, BindingResult bindingResult){
        if (bindingResult.hasErrors()) {
            List<ObjectError> errors = bindingResult.getAllErrors();
            errors.forEach(p -> {
                FieldError fieldError = (FieldError) p;
                log.error("Invalid Parameter : object - {},field - {},errorMessage - {}", fieldError.getObjectName(), fieldError.getField(), fieldError.getDefaultMessage());
            });
            return ResponseEntity.badRequest().body("invalid parameter");
        }
        return ResponseEntity.ok("success");
    }
}

# 分组校验@Validated

@Slf4j
@Api(value = "User Interfaces",tags = "User Interfaces")
@RestController
@RequestMapping("/user")
public class UserController {
    @ApiOperation("Add User")
    @ApiImplicitParam(name="userParam",type="body",dataTypeClass = UserParam.class,required = true)
    @PostMapping("add")
    public ResponseEntity<UserParam> add(@Validated(AddValidationGroup.class) @RequestBody UserParam userParam){
        return ResponseEntity.ok(userParam);
    }

    @ApiOperation("Edit User")
    @ApiImplicitParam(name= "userParam",type="body",dataTypeClass = UserParam.class,required = true)
    @PostMapping("edit")
    public  ResponseEntity<UserParam> edit(@Validated(EditValidationGroup.class) @RequestBody UserParam userParam){
        return ResponseEntity.ok(userParam);
    }
}

两者区别:

  1. @Validated:可以用在方法、方法参数、类型上。但是不能用在成员属性(字段)上
  2. @Valid:可以用在方法、方法参数、构造函数和成员属性(字段)上

# 常用校验

  • JSR303/JSR-349 位于javax.validation.constraints下,规定一些校验规范,如@Null,@NotNul,@NotEmpty
  • hibernate validation 新增了注解@Email, @Length,@Range
  • spring validation 二次封装,自动校验

# 自定义校验规则

# 定义注解

@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = {TelephoneNumberValidator.class}) // 指定校验器
public @interface TelephoneNumber {
    String message() default "Invalid telephone number";
    Class<?>[] groups() default { };
    Class<? extends Payload>[] payload() default { };
}

# 定义校验器

public class TelephoneNumberValidator implements ConstraintValidator<TelephoneNumber, String> {
    private static final String REGEX_TEL = "0\\d{2,3}[-]?\\d{7,8}|0\\d{2,3}\\s?\\d{7,8}|13[0-9]\\d{8}|15[1089]\\d{8}";

    @Override
    public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
        try {
            return Pattern.matches(REGEX_TEL, s);
        } catch (Exception e) {
            return false;
        }
    }

}

# 使用

@Data
@Builder
@ApiModel(value = "User", subTypes = {AddressParam.class})
public class UserParam implements Serializable {

    private static final long serialVersionUID = 1L;

    @NotEmpty(message = "{user.msg.userId.notEmpty}", groups = {EditValidationGroup.class})
    private String userId;

    @TelephoneNumber(message = "invalid telephone number") // 这里
    private String telephone;

}

原文链接:https://pdai.tech/md/spring/springboot/springboot-x-interface-param.html

# swagger文档的使用

swagger可以通过配置注解的方式自动为springboot项目生产接口文档,3.0版本支持导出json文件可以在ApiFox中加载使用。

支持在配置全局请求参数,全局响应参数和文档信息,是一种侵入式文档配置

# 添加依赖

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring-boot-starter</artifactId>
            <version>3.0.3</version>
        </dependency>
    </dependencies>

# API配置

/**
 * swagger config for open api.
 *
 * @author 
 */
@Configuration
@EnableOpenApi
public class OpenApiConfig {

    /**
     * open api extension by knife4j.
     */
    private final OpenApiExtensionResolver openApiExtensionResolver;

    @Autowired
    public OpenApiConfig(OpenApiExtensionResolver openApiExtensionResolver) {
        this.openApiExtensionResolver = openApiExtensionResolver;
    }

    /**
     * 配置Docket对象以便生成文档
     * @return swagger config
     */
    @Bean
    public Docket openApi() {
        String groupName = "Test Group";
        return new Docket(DocumentationType.OAS_30) // 指定文档类型
                .groupName(groupName) // 指定分组名称
                .apiInfo(apiInfo())// 设置API文档基本信息
                .select() // 可见性配置
                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))// 只有使用了@ApiOperation注解的方法生成文档
                .paths(PathSelectors.any())// 设置所有路径的配置
                .build() //构建Docket对象
                .globalRequestParameters(getGlobalRequestParameters()) //全局请求参数
                .globalResponses(HttpMethod.GET, getGlobalResponse()) //全局响应参数
                .extensions(openApiExtensionResolver.buildExtensions(groupName)) // 添加API扩展
                .extensions(openApiExtensionResolver.buildSettingExtensions()); // 添加设置扩展
    }

    /**
     * 获取响应码和状态描述
     * @return global response code->description
     */
    private List<Response> getGlobalResponse() {
        return ResponseStatus.HTTP_STATUS_ALL.stream().map(
                a -> new ResponseBuilder().code(a.getResponseCode()).description(a.getDescription()).build())
                .collect(Collectors.toList());
    }

    /**
     * 全局请求参数
     * @return global request parameters
     */
    private List<RequestParameter> getGlobalRequestParameters() {
        List<RequestParameter> parameters = new ArrayList<>();
        parameters.add(new RequestParameterBuilder()
                .name("AppKey")
                .description("应用 Key")
                .required(false)
                .in(ParameterType.QUERY)
                .query(q -> q.model(m -> m.scalarModel(ScalarType.STRING)))
                .required(false)
                .build());
        return parameters;
    }

    /** 设置API文档信息
     * @return api info
     */
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("Swagger/OpenApi")
                .description("api测试")
                .contact(new Contact("hui", "http://huyadish.com", ""))
                .termsOfServiceUrl("http://xxxxxx.com/")
                .version("1.0")
                .build();
    }
}

# YML配置

server:
  port: 8080
knife4j:
  enable: true
  documents:
    - group: Test Group # 文档分类名称
      name: My Documents #文档名称
      locations: classpath:wiki/*
  setting:
    # default lang
    language: en-US
    # footer
    enableFooter: false
    enableFooterCustom: true
    footerCustomContent: MIT | Gaohui
    # header
    enableHomeCustom: true
    homeCustomLocation: classpath:wiki/README.md
    # models
    enableSwaggerModels: true
    swaggerModelName: My Models

# API使用

@Api(value = "用户接口", tags = "用户接口")
@RestController
@RequestMapping("/user")
public class UserController {

    /**
     * http://localhost:8080/user/add .
     *
     * @param userParam user param
     * @return user
     */
    @ApiOperation("添加用户")
    @ApiImplicitParam(name = "userParam", type = "body", dataTypeClass = UserParam.class, required = true)
    @PostMapping("add")
    public ResponseEntity<String> add(@RequestBody UserParam userParam) {
        return ResponseEntity.ok("success");
    }

    /**
     * http://localhost:8080/user/list .
     *
     * @return user list
     */
    @ApiOperation("查询用户列表")
    @GetMapping("list")
    public ResponseEntity<List<UserVo>> list() {
        List<UserVo> userVoList = Collections.singletonList(UserVo.builder().name("hui").age(26).address(
                AddressVo.builder().city("tianjin").zipcode("123465").build()
        ).build());
        return ResponseEntity.ok(userVoList);
    }
}

原文链接 https://www.pdai.tech/md/spring/springboot/springboot-x-interface-doc.html

# Smart-Doc文档

非侵入式,也是繁重的代码

Last Updated: 12/23/2024, 4:18:13 AM