Qual è il modo corretto di gestire un parametro errato in un servizio RESTful? Al momento ho un endpoint che restituisce un 400 se viene inviato il tipo di dati errato.REST Gestione di un parametro errato
@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;
}
Sarebbe davvero bello se l'utente finale dovesse passare, per esempio, una stringa invece di un BigDecimal, che la risposta sarebbe tornato un JSON con il codice di risposta, lo stato, e qualsiasi altra cosa che vorrei per contenere, piuttosto che solo un 400. C'è un modo per farlo?
Aggiornamento: il mio pensiero iniziale era quello di avvolgere tutti i parametri e quindi controllare se è il tipo corretto in quella classe wrapper. Sembra un po 'sciocco. Non c'è un validatore che potrei semplicemente aggiungere al classpath che riconoscerebbe qualcosa del genere?
Inoltre, c'è un modo per gestirlo abbastanza facilmente con un tipo Bean che potrei creare da solo, ma per quanto riguarda i tipi standard come BigDecimal?
UPDATE-2: questo aggiornamento risponde alla risposta che utilizza @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;
}
}
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());
}
}
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;
}
}
MyErrorResponse.java
public class MyErrorResponse {
private Exception exception;
public Exception getException() {
return exception;
}
public void setEexception(Exception e) {
this.exception = e;
}
}
Sarebbe bello se avessi un'eccezione per passarlo. Il mio caso credo sia diverso. Mi piacerebbe essere in grado di convalidare i parametri passati al servizio RESTful. Se credi che posso ancora usare questo, ti dispiacerebbe fare un esempio? Grazie! – Matt
Non sono sicuro di aver capito bene. Quindi vuoi consentire all'utente di passare qualsiasi cosa e quindi convalidarlo? '@ ExceptionHandler' viene chiamato quando viene generata un'eccezione, ad esempio durante i parametri di binding (quando si esclude il numero e la stringa è passata ecc.), Quando si arriva a' @ RequestMapping' significa che l'associazione è corretta e che è possibile convalidare. Potresti spiegare un po 'di più? – kamil
Nell'esempio sopra ho, il metodo dovrebbe prendere un BigDecimal. Ma se l'utente finale supera A123.00, restituisce un 400 (l'errore è che c'è un 'A' davanti a 123.00). Sto arrivando alla conclusione che non puoi farlo a meno che non completi il tipo di dati, come suggerisce Sotirios ... – Matt