我故意下载一个大文件以获得异常。处理控制器:
@RequestMapping(value = "/uploadFile", method = RequestMethod.POST, produces={"application/text; charset=UTF-8"})
@ResponseBody
public ResponseEntity<?> uploadFile(
@RequestParam("uploadfile") MultipartFile uploadfile) throws Exception {
String fileName = storageService.uploadFile(uploadfile);
return new ResponseEntity<String>(fileName, HttpStatus.OK);
}
我有一个全局拦截器:
@ControllerAdvice
public class GlobalControllerExceptionHandler extends ResponseEntityExceptionHandler implements ErrorViewResolver {
private static final Logger LOG = LoggerFactory.getLogger(GlobalControllerExceptionHandler.class);
private static final String DEFAULT_ERROR_VIEW = "error";
@ExceptionHandler(value = {MultipartException.class})
@ResponseBody
ResponseEntity<?> uploadFile(HttpServletRequest request, MultipartException ex) {
LOG.error("Exception in uploadFile at request " + request.getRequestURL(), ex);
return new ResponseEntity<String>(ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
}
@ExceptionHandler(value = {Exception.class})
public ModelAndView defaultErrorHandler(HttpServletRequest request, Exception e) {
ModelAndView mav = new ModelAndView(DEFAULT_ERROR_VIEW);
LOG.error("Exception at request " + request.getRequestURL(), e);
mav.addObject("timestamp", new Date());
mav.addObject("error", e.getMessage());
mav.addObject("path", request.getRequestURL());
return mav;
}
@Override
public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus httpStatus, Map<String, Object> map) {
ModelAndView mav = new ModelAndView(DEFAULT_ERROR_VIEW);
LOG.error(map.toString());
/**
timestamp --- Fri Oct 20 09:46:58 MSK 2017
status --- 404
error --- Not Found
message --- /hudo
path --- /hudo
**/
map.forEach(mav::addObject);
return mav;
}
}
捕获Exception MultipartException
2017-10-23 14:44:13.635 ERROR 15680 --- [nio-8080-exec-2] s.web.GlobalControllerExceptionHandler : Exception in uploadFile at request http://localhost:8080/painter/uploadFile
org.springframework.web.multipart.MultipartException: Could not parse multipart servlet request; nested exception is java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.FileUploadBase$FileSizeLimitExceededException: The field uploadfile exceeds its maximum permitted size of 3145728 bytes.
所以,传递给客户端的消息和状态(调用是在ajax)。答案是:
POST http://localhost:8080/painter/uploadFile net::ERR_CONNECTION_ABORTED
status - 0 error - undefined
如何从拦截器获得响应?
答案 0 :(得分:0)
我为ExceptionHandler的问题做了一个小实验;为了简单起见,我只使用POJO作为方法输入,这样我就可以使用Postman或curl
轻松测试。您可以尝试将我的方法应用于MultiPartFile输入。以下是部分:
**pom.xml**
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.7.RELEASE</version>
</parent>
<groupId>com.test</groupId>
<artifactId>test-app</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.6</version>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.11.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Spring Boot App @SpringBootApplication 公共类TestApplication扩展了SpringBootServletInitializer {
private static final Logger log = LoggerFactory.getLogger(TestApplication.class);
@Autowired
Environment env;
public static void main(String[] args) {
SpringApplication.run(TestApplication.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(TestApplication.class);
}
@Bean
public ConversionService conversionService() {
return new DefaultConversionService();
}
}
控制器
@RestController
@RequestMapping("/api")
public class TestController {
@RequestMapping(value = "/upload", method = RequestMethod.POST, produces={"application/json"})
@ResponseBody
@ResponseStatus(HttpStatus.OK)
public TestResponse uploadFile(@RequestBody TestRequest request) throws MultipartException {
if ("danger.txt".equalsIgnoreCase(request.getFileName())) {
throw new MultipartException("Danger. Get outta there now!");
} else {
return new TestResponse("all good");
}
}
}
异常处理程序
@ControllerAdvice
public class GlobalExceptionHandler {
private static final Logger LOG = LoggerFactory.getLogger(GlobalExceptionHandler.class);
@ExceptionHandler(value = {MultipartException.class})
@ResponseBody
ResponseEntity<ErrorResponse> handleFileUploadException(HttpServletRequest request, MultipartException ex) {
LOG.error("Exception in uploadFile at request " + request.getRequestURL(), ex);
ErrorResponse response = new ErrorResponse("Dangerous file", "The file was pretty scary.");
return new ResponseEntity<ErrorResponse>(response, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
请求/响应POJO
public class TestRequest {
private String fileName;
public TestRequest() {
}
public TestRequest(String fileName) {
this.fileName = fileName;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
}
public class TestResponse {
private String message;
public TestResponse() {
}
public TestResponse(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
错误回应POJO
import com.fasterxml.jackson.annotation.JsonProperty;
public class ErrorResponse {
@JsonProperty("error")
private String error;
@JsonProperty("error_description")
private String errorDescription;
public ErrorResponse() {
}
public ErrorResponse(String error, String errorDescription) {
super();
this.error = error;
this.errorDescription = errorDescription;
}
public String getError() {
return error;
}
public String getErrorDescription() {
return errorDescription;
}
}
我用mvn spring-boot:run
运行应用程序。然后使用curl
来测试API。
卷曲请求
curl -d '{"fileName":"danger.txt"}' -H "Content-Type: application/json" -X POST http://localhost:8080/api/upload -v
卷曲回复
Note: Unnecessary use of -X or --request, POST is already inferred.
* timeout on name lookup is not supported
* Trying ::1...
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Connected to localhost (::1) port 8080 (#0)
> POST /api/upload HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.49.1
> Accept: */*
> Content-Type: application/json
> Content-Length: 25
>
} [25 bytes data]
* upload completely sent off: 25 out of 25 bytes
< HTTP/1.1 500
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Fri, 27 Oct 2017 07:07:26 GMT
< Connection: close
<
{ [81 bytes data]
100 100 0 75 100 25 2343 781 --:--:-- --:--:-- --:--:-- 2343{"error":"Dangerous file","error_description":"The file was pretty scary."}
* Closing connection 0
最后,我根据需要获得了正确的HTTP 500以及客户端可以轻松解析的自定义响应消息。