REST处理错误的参数

Mat*_*att 5 java rest spring

在RESTful服务中处理错误参数的正确方法是什么?我现在有一个端点,如果发送了错误的数据类型,则返回400.

@ResponseBody
@RequestMapping(produces = "application/json", method = RequestMethod.GET, value="/v1/test")
public MyResponse getSomething(@RequestParam BigDecimal bd) {
    MyResponse r = new MyResponse();
    r.setBd(bd);
    return r;
}
Run Code Online (Sandbox Code Playgroud)

如果最终用户传递一个String而不是BigDecimal,那将是非常好的,响应将返回一个带有响应代码,状态以及我希望包含的任何其他内容的json,而不仅仅是400.有办法做到这一点吗?

更新:我最初的想法是包装每个参数,然后检查它是否是该包装类中的正确类型.这看起来有点傻.是不是有一个验证器,我可以添加到类路径,可以识别这样的东西?

另外,有一种方法可以很容易地使用我可以自己创建的Bean类型来处理这个问题,但是像BigDecimal这样的标准类型呢?

UPDATE-2:此更新解决了使用@ExceptionHandler的答案.

TestController.java

import java.math.BigDecimal;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@RequestMapping("/")
public class TestController {

    //this is where correct input from user is passed, no binding errors
    @RequestMapping(produces = "application/json", method = RequestMethod.GET, value="/v1/test")
    public
    @ResponseBody
    MyResponse getSomething(@RequestParam BigDecimal bd) {
        MyResponse r = new MyResponse();
        r.setBd(bd);
        return r;
    }

    //this will handle situation when you except number and user passess string (A123.00 for example)
    @ExceptionHandler(ServletRequestBindingException.class)
    public @ResponseBody MyErrorResponse handleMyException(Exception exception, HttpServletRequest request) {

        MyErrorResponse r = new MyErrorResponse();
        r.setEexception(exception);

        return r;
    }


}
Run Code Online (Sandbox Code Playgroud)

TestUnitTest.java

public class TestUnitTest {

protected MockMvc mockMvc;

@Autowired
protected WebApplicationContext wac;

@Before
public void setup() {
    this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}


@Test
public void test() throws Exception {
    String url =  "/v1/test?bd=a123.00";

    log.info("Testing Endpoint::: " + url);

    MvcResult result =  mockMvc.perform(get(url))
                        .andExpect(status().isOk())
                        .andReturn();

    log.info("RESPONSE::: " + result.getResponse().getContentAsString());
}

}
Run Code Online (Sandbox Code Playgroud)

MyResponse.java

import java.math.BigDecimal;

public class MyResponse {

    private BigDecimal bd;

    public BigDecimal getBd() {
        return bd;
    }

    public void setBd(BigDecimal bd) {
        this.bd = bd;
    }

}
Run Code Online (Sandbox Code Playgroud)

MyErrorResponse.java

public class MyErrorResponse {

    private Exception exception;

    public Exception getException() {
        return exception;
    }

    public void setEexception(Exception e) {
        this.exception = e;
    }

}
Run Code Online (Sandbox Code Playgroud)

kam*_*mil 3

将 Spring@ExceptionHandler与标准@RequestMapping注释一起使用,如下所示:

//this is where correct input from user is passed, no binding errors
@RequestMapping(produces = "application/json", method = RequestMethod.GET, value="/v1/test")
public
@ResponseBody
MyResponse getSomething(@RequestParam BigDecimal bd) {
    MyResponse r = new MyResponse();
    r.setBd(bd);
    return r;
}

//this will handle situation when there's exception during binding, for example you except number and user passess string (A123.00 for example)
@ExceptionHandler(TypeMismatchException.class)
public 
@ResponseBody
MyErrorResponse handleMyException(Exception exception, HttpServletRequest request) {
    //....
}
Run Code Online (Sandbox Code Playgroud)

TypeMismatchException是尝试设置 bean 属性时抛出的一般异常。您可以进一步概括代码并使用几种方法捕获每个绑定异常,例如:

@ExceptionHandler(TypeMismatchException.class)
public
@ResponseBody
String typeMismatchExpcetionHandler(Exception exception, HttpServletRequest request) {
    return "type mismatch";
}

@ExceptionHandler(MissingServletRequestParameterException.class)
public
@ResponseBody
String missingParameterExceptionHandler(Exception exception, HttpServletRequest request) {
    return "missing param";
}

@ExceptionHandler(Exception.class)
public
@ResponseBody
String generalExceptionHandler(Exception exception, HttpServletRequest request) {
    return "general exception";
}
Run Code Online (Sandbox Code Playgroud)

它非常灵活,允许在签名和返回对象中使用许多参数注释类型ExceptionHandler

@ResponseBody可以返回任何可以序列化为 JSON 的对象。只需要在类路径中包含 jackson 库,但我假设您已经知道这一点