首页 > 解决方案 > SpringBoot 处理 @RequestParam 异常

问题描述

我有控制器和方法 deleteFolder 有@RequestParam:

@RestController
    public class FolderController extends BaseController {

@DeleteMapping(path = Const.APIVersions.API_V1 + "/folders", params = "id")
public ResponseEntity<HttpStatus> deleteFolder(KeycloakAuthenticationToken authentication, @RequestParam Long id) throws EntityNotFoundException {
    folderService.deleteFolder(id, authentication.getName());
    return ResponseEntity.ok(HttpStatus.OK);
}

父类:

public abstract class BaseController {
    @ExceptionHandler({MissingServletRequestParameterException.class,
            UnsatisfiedServletRequestParameterException.class, MethodArgumentTypeMismatchException.class,
            IllegalArgumentException.class})
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ResponseEntity<ErrorResponse> handleMissingServletRequestParameter(MissingServletRequestParameterException exception) {
        return ResponseEntity
                .status(HttpStatus.BAD_REQUEST)
                .body(new ErrorResponse(HttpStatus.BAD_REQUEST.value(), exception.getMessage()));
    }

当缺少所需的参数时,我想处理异常。但是该异常处理程序不想捕获从 deletFolder 方法引发的异常。

任何其他处理程序都可以工作。

标签: springspring-bootexceptionhandlerspring-restcontroller

解决方案


您必须创建自定义ConstraintValidator并捕获ConstraintViolationException,以便您的基本控制器变为


import org.springframework.http.*;
import org.springframework.web.bind.annotation.*;

import javax.validation.*;

public abstract class BaseController {


    @ExceptionHandler({ConstraintViolationException.class})
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ResponseEntity<ErrorResponse> handlerFolderNotFoundException(ConstraintViolationException exception) {
        return ResponseEntity
                .status(HttpStatus.BAD_REQUEST)
                .body(new ErrorResponse(HttpStatus.BAD_REQUEST.value(), exception.getMessage()));
    }
}

验证注解


import javax.validation.*;
import java.lang.annotation.*;

@Constraint(validatedBy = FolderValidationConstraint.class)
@Target({ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ValidateFolder {

    String message() default "Error validating folder name";

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

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

}

验证器类

import lombok.extern.slf4j.*;

import javax.validation.*;
import java.io.*;

@Slf4j
public class FolderValidationConstraint implements ConstraintValidator<ValidateFolder, String> {

    @Override
    public boolean isValid(String path, ConstraintValidatorContext constraintValidatorContext) {
        return new File("/home/ashish/Documents/test-delete/" + path).exists();
    }
}

控制器

import org.springframework.validation.annotation.*;
import org.springframework.web.bind.annotation.*;

import java.io.*;
import java.util.*;

@Validated
@RestController
@RequestMapping(path = "/folders")
public class FolderController extends BaseController {

    @GetMapping
    public Map<String, Boolean> delete(@ValidateFolder @RequestParam("name") String folderName) {
        final File path = new File("/home/ashish/Documents/test-delete/" + folderName);
        return Map.of("exists", path.exists());
    }
}

请确保在 pom.xml 中添加依赖项

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

推荐阅读