在请求目标中找到无效字符时如何自定义springboot中的错误消息

时间:2018-09-11 09:15:21

标签: spring-boot tomcat

我必须在使用springboot 2.0.4.RELEASE开发的REST API中返回自定义的错误结构。 我在下面开发了控制器建议书来完成工作...除非客户端发送包含非法字符的请求。例如:http://mycompany/myapp/myservice?fields=v1[*][*]应该已经过网址编码)。

客户端第一次发送此类请求时,我将此消息记录到日志中

  

2018-09-11 10:41:44.986信息11464-[[io-8080-exec-10]   o.apache.coyote.http11.Http11Processor:解析HTTP请求时出错   标头注意:HTTP标头解析错误的进一步发生将   在调试级别记录。

     

java.lang.IllegalArgumentException:在   请求目标。有效字符在RFC 7230和RFC中定义   3986年   org.apache.coyote.http11.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:479)   〜[tomcat-embed-core-8.5.32.jar:8.5.32]在   org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:684)   〜[tomcat-embed-core-8.5.32.jar:8.5.32]在   org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)   [tomcat-embed-core-8.5.32.jar:8.5.32]在   org.apache.coyote.AbstractProtocol $ ConnectionHandler.process(AbstractProtocol.java:800)   [tomcat-embed-core-8.5.32.jar:8.5.32]在   org.apache.tomcat.util.net.NioEndpoint $ SocketProcessor.doRun(NioEndpoint.java:1471)   [tomcat-embed-core-8.5.32.jar:8.5.32]在   org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)   [tomcat-embed-core-8.5.32.jar:8.5.32]在   java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)   [na:1.8.0_144]在   java.util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:624)   [na:1.8.0_144]在   org.apache.tomcat.util.threads.TaskThread $ WrappingRunnable.run(TaskThread.java:61)   [tomcat-embed-core-8.5.32.jar:8.5.32]在   java.lang.Thread.run(Thread.java:748)[na:1.8.0_144]

...但是没有调用我的控制器建议的任何方法,并且我收到一个http错误400(很好),带有一个空的正文(那是错误的)。接下来的时间里,除了没有记录外,其他都不会记录。

我应该怎么做才能捕获此错误并返回我的自定义错误结构?

这是(我的Controller建议的简化代码):

package com.renault.api.examples.springboot;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.ConversionNotSupportedException;
import org.springframework.beans.TypeMismatchException;
import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
import org.springframework.boot.web.servlet.error.ErrorAttributes;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.validation.BindException;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingPathVariableException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.context.request.async.AsyncRequestTimeoutException;
import org.springframework.web.multipart.support.MissingServletRequestPartException;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

import com.fasterxml.jackson.databind.ObjectMapper;

@ControllerAdvice
public class ExceptionHandler extends ResponseEntityExceptionHandler {
    public static final class CustomError {
        // custom attributes removed for publication
    }

    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
    private static final Logger LOGGER = LoggerFactory.getLogger(ExceptionHandler.class);
    private static final String UNEXPECTED_EXCEPTION_MESSAGE = "An unexpected exception occurred";

    @Override
    protected ResponseEntity<Object> handleTypeMismatch(TypeMismatchException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
System.out.println("handleTypeMismatch");
        return new ResponseEntity<Object>(new CustomError(), headers, status);
    }

    @Override
    protected ResponseEntity<Object> handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException ex,
            HttpHeaders headers, HttpStatus status, WebRequest request) {
System.out.println("handleHttpRequestMethodNotSupported");
        return super.handleHttpRequestMethodNotSupported(ex, headers, status, request);
    }
    @Override
    protected ResponseEntity<Object> handleHttpMediaTypeNotSupported(HttpMediaTypeNotSupportedException ex,
            HttpHeaders headers, HttpStatus status, WebRequest request) {
System.out.println("handleHttpMediaTypeNotSupported");
        return super.handleHttpMediaTypeNotSupported(ex, headers, status, request);
    }
    @Override
    protected ResponseEntity<Object> handleHttpMediaTypeNotAcceptable(HttpMediaTypeNotAcceptableException ex,
            HttpHeaders headers, HttpStatus status, WebRequest request) {
System.out.println("handleHttpMediaTypeNotAcceptable");
        return super.handleHttpMediaTypeNotAcceptable(ex, headers, status, request);
    }
    @Override
    protected ResponseEntity<Object> handleMissingPathVariable(MissingPathVariableException ex, HttpHeaders headers,
            HttpStatus status, WebRequest request) {
System.out.println("handleMissingPathVariable");
        return super.handleMissingPathVariable(ex, headers, status, request);
    }
    @Override
    protected ResponseEntity<Object> handleMissingServletRequestParameter(MissingServletRequestParameterException ex,
            HttpHeaders headers, HttpStatus status, WebRequest request) {
System.out.println("handleMissingServletRequestParameter");
        return super.handleMissingServletRequestParameter(ex, headers, status, request);
    }
    @Override
    protected ResponseEntity<Object> handleServletRequestBindingException(ServletRequestBindingException ex,
            HttpHeaders headers, HttpStatus status, WebRequest request) {
System.out.println("handleServletRequestBindingException");
        return super.handleServletRequestBindingException(ex, headers, status, request);
    }
    @Override
    protected ResponseEntity<Object> handleConversionNotSupported(ConversionNotSupportedException ex,
            HttpHeaders headers, HttpStatus status, WebRequest request) {
System.out.println("handleConversionNotSupported");
        return super.handleConversionNotSupported(ex, headers, status, request);
    }
    @Override
    protected ResponseEntity<Object> handleHttpMessageNotReadable(HttpMessageNotReadableException ex,
            HttpHeaders headers, HttpStatus status, WebRequest request) {
System.out.println("handleHttpMessageNotReadable");
        return super.handleHttpMessageNotReadable(ex, headers, status, request);
    }
    @Override
    protected ResponseEntity<Object> handleHttpMessageNotWritable(HttpMessageNotWritableException ex,
            HttpHeaders headers, HttpStatus status, WebRequest request) {
System.out.println("handleHttpMessageNotWritable");
        return super.handleHttpMessageNotWritable(ex, headers, status, request);
    }
    @Override
    protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex,
            HttpHeaders headers, HttpStatus status, WebRequest request) {
System.out.println("handleMethodArgumentNotValid");
        return super.handleMethodArgumentNotValid(ex, headers, status, request);
    }
    @Override
    protected ResponseEntity<Object> handleMissingServletRequestPart(MissingServletRequestPartException ex,
            HttpHeaders headers, HttpStatus status, WebRequest request) {
System.out.println("handleMissingServletRequestPart");
        return super.handleMissingServletRequestPart(ex, headers, status, request);
    }
    @Override
    protected ResponseEntity<Object> handleBindException(BindException ex, HttpHeaders headers, HttpStatus status,
            WebRequest request) {
System.out.println("handleBindException");
        return super.handleBindException(ex, headers, status, request);
    }
    @Override
    protected ResponseEntity<Object> handleNoHandlerFoundException(NoHandlerFoundException ex, HttpHeaders headers,
            HttpStatus status, WebRequest request) {
System.out.println("handleNoHandlerFoundException");
        return super.handleNoHandlerFoundException(ex, headers, status, request);
    }
    @Override
    protected ResponseEntity<Object> handleAsyncRequestTimeoutException(AsyncRequestTimeoutException ex,
            HttpHeaders headers, HttpStatus status, WebRequest webRequest) {
System.out.println("handleAsyncRequestTimeoutException");
        return super.handleAsyncRequestTimeoutException(ex, headers, status, webRequest);
    }
    @Override
    protected ResponseEntity<Object> handleExceptionInternal(Exception ex, Object body, HttpHeaders headers,
            HttpStatus status, WebRequest request) {
System.out.println("handleExceptionInternal");
        return super.handleExceptionInternal(ex, body, headers, status, request);
    }

    /** Handles all exceptions not processed by spring boot thrown during request processing.
     * <br>this means the errors like "path not found", "wrong argument" are not processed by this method. 
     * @param ex The exception that occurs.
     * @param request The request that sends the exception.
     * @return The response to send to client. For publication, all exceptions are considered unexpected => http error 500
     */
    @org.springframework.web.bind.annotation.ExceptionHandler(value= {Exception.class})
    protected ResponseEntity<Object> handle(Exception ex, WebRequest request) {
        LOGGER.error(UNEXPECTED_EXCEPTION_MESSAGE, ex);
        CustomError response = new CustomError();
        // Fill custom error attributes ... removed for publication
        return handleExceptionInternal(ex, response, new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR, request);
    }

    /** Handles "standard" errors, like "path not found".
     * @return an ErrorAttributes object describing the attributes of the response's body.
     */
    @Bean
    public ErrorAttributes errorAttributes() {
        return new DefaultErrorAttributes() {
            @Override
            public int getOrder() {
System.out.println("getOrder is called");
                return super.getOrder();
            }

            @Override
            public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response,
                    Object handler, Exception ex) {
System.out.println("resolveException is called");
                return super.resolveException(request, response, handler, ex);
            }

            @Override
            public Throwable getError(WebRequest webRequest) {
System.out.println("getError is called");
                return super.getError(webRequest);
            }

            @Override
            public Map<String, Object> getErrorAttributes(WebRequest request, boolean includeStackTrace) {
System.out.println("getErrorAttributes is called");
                CustomError err = new CustomError();
                // Reuse default attributes to fill custom error ... removed for publication
                @SuppressWarnings("unchecked")
                Map<String, Object> map = OBJECT_MAPPER.convertValue(err, Map.class);
                return map;
            }
        };
    }
}

谢谢

0 个答案:

没有答案