春季:如何在运行时选择响应类型?
问题内容:
我想在一种方法中选择运行时的响应媒体类型。
例如,以下代码:
@RequestMapping(value = "/getRecord",
produces = {"application/octet-stream", "application/json;charset=UTF-8" })
public byte[] getData(
@RequestParam(value="id", required=true) Integer id)
throws IOException
{
if (id == 1)
return createByteArray();
throw new MyDataException();
}
在此代码中,可能的响应类型实际上是2。
- byte [](通过常规执行路径)
- MyDataException(通过异常执行路径)
MyDataException稍后由异常处理程序处理,并转换为简单的类。可以将其转换为json响应。
首先,我认为如果为注释的produces
选项提供2种响应类型@RequestMapping
,则消息转换器将根据实际的返回对象转换这2种类型。但是事实并非如此。
在spring类中org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor
,writeWithMessageConverters()
如果produces
存在选项,则在选择响应类型时,方法只会忽略实际的返回对象类型。
如何让Spring根据实际的返回对象在运行时选择响应类型?
问题答案:
另一种可能性是在上述两种解决方案之间采用混合方法:
@ControllerAdvice
public class MyExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler({ MyDataException.class })
protected ResponseEntity<Object> handleInvalidRequest(RuntimeException e, WebRequest request) {
MyDataExceptionire = (MyDataException) e;
List<FieldErrorResource> fieldErrorResources = new ArrayList<>();
List<FieldError> fieldErrors = ire.getErrors().getFieldErrors();
for (FieldError fieldError : fieldErrors) {
FieldErrorResource fieldErrorResource = new FieldErrorResource();
fieldErrorResource.setResource(fieldError.getObjectName());
fieldErrorResource.setField(fieldError.getField());
fieldErrorResource.setCode(fieldError.getCode());
fieldErrorResource.setMessage(fieldError.getDefaultMessage());
fieldErrorResources.add(fieldErrorResource);
}
ErrorResource error = new ErrorResource("MyDataException", ire.getMessage());
error.setFieldErrors(fieldErrorResources);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
return handleExceptionInternal(e, error, headers, HttpStatus.UNPROCESSABLE_ENTITY, request);
}}
在此博客上提出的解决方案
编辑 :
我还从博客中添加了FieldError和ErrorResource类,因为将来可能会删除它:
错误资源:
@JsonIgnoreProperties(ignoreUnknown = true)
public class ErrorResource {
private String code;
private String message;
private List<FieldErrorResource> fieldErrors;
public ErrorResource() { }
public ErrorResource(String code, String message) {
this.code = code;
this.message = message;
}
public String getCode() { return code; }
public void setCode(String code) { this.code = code; }
public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; }
public List<FieldErrorResource> getFieldErrors() { return fieldErrors; }
public void setFieldErrors(List<FieldErrorResource> fieldErrors) {
this.fieldErrors = fieldErrors;
}
}
FieldErrorResource:
@JsonIgnoreProperties(ignoreUnknown = true)
public class FieldErrorResource {
private String resource;
private String field;
private String code;
private String message;
public String getResource() { return resource; }
public void setResource(String resource) { this.resource = resource; }
public String getField() { return field; }
public void setField(String field) { this.field = field; }
public String getCode() { return code; }
public void setCode(String code) { this.code = code; }
public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; }}