Spring Rest ErrorHandling @ControllerAdvice/@Valid

dae*_*nio 12 java rest error-handling spring

我在REST控制器中一起使用@ControllerAdvice@Valid注释时遇到了麻烦.

我有一个休息控制器声明如下:

@Controller
public class RestExample {

    ...

    /**
     * <XmlRequestUser><username>user1</username><password>password</password><name>Name</name><surname>Surname</surname></XmlRequestUser>
     * curl -d "@restAddRequest.xml" -H "Content-Type:text/xml" http://localhost:8080/SpringExamples/servlets/rest/add
     */
    @RequestMapping(value="rest/add", method=RequestMethod.POST)
    public @ResponseBody String add(@Valid @RequestBody XmlRequestUser xmlUser) {
        User user = new User();
        user.setUsername(xmlUser.getUsername());
        user.setPassword(xmlUser.getPassword());
        user.setName(xmlUser.getName());
        user.setSurname(xmlUser.getSurname());

        // add user to the database
        StaticData.users.put(xmlUser.getUsername(), user);
        LOG.info("added user " + xmlUser.getUsername());

        return "added user " + user.getUsername();
    }
}
Run Code Online (Sandbox Code Playgroud)

还有一个ErrorHandler类:

@ControllerAdvice
public class RestErrorHandler extends ResponseEntityExceptionHandler {

    private static Logger LOG = Logger.getLogger(RestErrorHandler.class);


    @ExceptionHandler(RuntimeException.class)
    public ResponseEntity<Object> handleException(final RuntimeException e, WebRequest request) {
        LOG.error(e);

        String bodyOfResponse = e.getMessage();
        return handleExceptionInternal(e, bodyOfResponse, new HttpHeaders(), HttpStatus.CONFLICT, request);
    }
}
Run Code Online (Sandbox Code Playgroud)

问题是,如果我在方法RestExample.add中添加"throw new RuntimeException",则RestErrorHandler类正确处理异常.

但是,当向控制器卷曲无效请求时,RestErrorHandler不会捕获验证器抛出的异常,并且我收到400 BadRequest响应.(对于无效请求,我指的是未指定用户名的xml请求)

请注意,XmlRequestUser类是由插件maven-jaxb2-plugin + krasa-jaxb-tools(pom.xml)自动生成的:

<plugin>
    <groupId>org.jvnet.jaxb2.maven2</groupId>
    <artifactId>maven-jaxb2-plugin</artifactId>
    <executions>
        <execution>
            <goals>
                <goal>generate</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <schemaDirectory>src/main/xsd</schemaDirectory>
        <schemaIncludes>
            <include>*.xsd</include>
        </schemaIncludes>
        <args>
            <arg>-XJsr303Annotations</arg>
            <arg>-XJsr303Annotations:targetNamespace=http://www.foo.com/bar</arg>
        </args>
        <plugins>
            <plugin>
                <groupId>com.github.krasa</groupId>
                <artifactId>krasa-jaxb-tools</artifactId>
                <version>${krasa-jaxb-tools.version}</version>
            </plugin>
        </plugins>
    </configuration>
</plugin>
Run Code Online (Sandbox Code Playgroud)

生成的类在"用户名"和"密码"字段上正确显示了@NotNull注释.

我的context.xml非常简单,只包含一个控制器扫描程序并启用mvc:annotation-driven

<context:component-scan base-package="com.aa.rest" />
<mvc:annotation-driven />
Run Code Online (Sandbox Code Playgroud)

有人知道如何在REST控制器中一起使用@ControllerAdvice和@Valid注释吗?

提前致谢.安东尼奥

mat*_*sev 20

你是在正确的轨道上,但你需要覆盖handleMethodArgumentNotValid()而不是handleException()方法,例如

@ControllerAdvice
public class RestErrorHandler extends ResponseEntityExceptionHandler {

    @Override
    protected ResponseEntity<Object> handleMethodArgumentNotValid(
            MethodArgumentNotValidException exception,
            HttpHeaders headers,
            HttpStatus status,
            WebRequest request) {

        LOG.error(exception);
        String bodyOfResponse = exception.getMessage();
        return new ResponseEntity(errorMessage, headers, status);
    }
}
Run Code Online (Sandbox Code Playgroud)

MethodArgumentNotValidException的JavaDoc :

对使用@Valid注释的参数进行验证失败时抛出的异常.

换句话说,MethodArgumentNotValidException当验证失败时抛出a .它由the handleMethodArgumentNotValid()提供的方法处理,ResponseEntityExceptionHandler如果你想要自定义实现,需要覆盖它.

  • 我在@controllerAdvice中重写handleMethodArgumentNotValid(),但是当所需参数不存在时我无法处理异常 (2认同)