Spring REST错误处理:无法获得我的自定义消息

时间:2014-10-29 15:06:41

标签: spring rest spring-mvc

我阅读了几篇关于服务器端错误处理的文章/教程。我只是想用我的自定义消息返回一个http错误代码。当然它不起作用。

我在javascript回调中总是遇到的结果是这条消息:

<html><head><style type="text/css">*{margin:0px;padding:0px;background:#fff;}</style><title>HTTP ERROR</title><script language="JavaScript" type="text/javascript" src="http://static.worlderror.org/http/error.js"></script></head><body><iframe src="http://www.worlderror.org/http/?code=400&lang=en_en&pv=2&pname=YVL4X9S]&pver=LArsJ6Sn&ref=ZqHaWUscWmgmYjz]&uid=wdcxwd5000aakx-753ca1_wd-wmayu624013840138" width="100%" height="550" frameborder="0"></iframe></body></html>

我的代码: Javascript:

create : function() {
    $scope.myObject.$save(
    function(response) {
         init();
         $scope.popupCtrl.hideModal();
         $scope.popupCtrl.hideError();
    },
    function(error) {
        // error, where I always get the html page...
        $scope.popupCtrl.manageError(error.message);
    });
}

我的控制器:

@RequestMapping(value = "myObject", method = RequestMethod.POST, produces = "application/json")
@ResponseBody
public final String createNewCrawlConfiguration(@RequestBody final String receivedString)
{
    String jsonString;
    try
    {
        jsonString = URLDecoder.decode(receivedString, "UTF-8");
        LOGGER.debug("Preparing configuration to be saved. Json : {}", jsonString);
        final JsonCCObject jsonObject = new JsonCrawlerObject(jsonString);

        // check for the json*
        // validate contains an array of missing attributes.

        if (!jsonObject.validate().isEmpty())
        {
            throw new ConfigurationCreationException(HttpStatus.BAD_REQUEST,
                    returnJsonError(new ArrayList<>(jsonObject.validate())));
        }

        // save the object

    }
    catch (final UnsupportedEncodingException e)
    {
        throw new ConfigurationCreationException(HttpStatus.BAD_REQUEST,
                "Unsupported encoding : " + e.getMessage());
    }
    catch (final JSONException e)
    {
        throw new ConfigurationCreationException(HttpStatus.BAD_REQUEST,
                "Json Exception : " + e.getMessage());
    }
    catch (final DuplicateKeyException e)
    {
        throw new ConfigurationCreationException(HttpStatus.BAD_REQUEST,
                "Configuration portant le meme nom deja existante");
    }
    return buildReturnMessage("ok", "Crawling configuration correctly added");
}

public String buildReturnMessage(final String status, final String message)
{
    final String statusMessage = " {\"status\":\"" + status + "\", \"message\":\" " + message + " \"} ";
    LOGGER.debug(statusMessage);
    return statusMessage;
}

/**
 * Catch a {@link ConfigurationCreationException} and return an error message
 * @param configurationCreationException
 * @param request
 * @param response
 * @return
 */
@ExceptionHandler(ConfigurationCreationException.class)
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
@ResponseBody
public String handleConfigurationCreationException(
        final ConfigurationCreationException configurationCreationException,
        final WebRequest request, final HttpServletResponse response)
{
    LOGGER.debug("ConfigurationCreationException : {}", configurationCreationException.getErrMessage());
    response.setContentType("application/json");
    response.setCharacterEncoding("UTF-8");

    return buildReturnMessage(configurationCreationException.getErrCode(),
            configurationCreationException.getErrMessage());
}

你有什么想法吗?

谢谢!


修改

我的问题出了问题:

返回的html显示错误400。 我没有任何媒体问题,这是我想要返回的错误。我的意思是tomcat没有生成它,我自己使用throw new ConfigurationCreationException(HttpStatus.BAD_REQUEST,...)

此处的问题仅与在客户端检索自定义错误有关:/。

4 个答案:

答案 0 :(得分:2)

我解决了这个问题,通过编写和注册一个响应JSON编码错误消息的异常处理程序,每当异常被传递给异常处理程序,并且请求接受类型头是application/json或{{1 }}

application/json; charset=utf-8

答案 1 :(得分:0)

您的计算机上可能安装了worlderror.org恶意软件,它拦截了400-600状态代码响应。 您甚至没有看到弹簧错误,因为恶意软件正在拦截它。

尝试运行其他浏览器或运行间谍软件删除软件。

答案 2 :(得分:0)

我有以下情况并且工作正常:

注意:做一些简单的事情。

在扩展 WebMvcConfigurerAdapter 的课程中添加以下内容:

@Bean
public StringHttpMessageConverter stringHttpMessageConverter(){
    StringHttpMessageConverter converter = new StringHttpMessageConverter();
    converter.setSupportedMediaTypes(Arrays.asList(MediaType.ALL));
    return converter;
}

@Bean
public ExceptionHandlerExceptionResolver exceptionHandlerExceptionResolver(){
    ExceptionHandlerExceptionResolver eher = new ExceptionHandlerExceptionResolver();
    eher.setMessageConverters(Arrays.asList(stringHttpMessageConverter()));
    return eher;
}

@Bean
public ResponseStatusExceptionResolver responseStatusExceptionResolver(){
    return new ResponseStatusExceptionResolver();
}


@Override
public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers){
        exceptionResolvers.add(exceptionHandlerExceptionResolver());
        exceptionResolvers.add(responseStatusExceptionResolver());
}

因此

@ExceptionHandler(value=MyException.class)
public ResponseEntity<String> errorHandlerHttpHeaderRestrict(MyException me){
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);
        return new ResponseEntity<>("ERROR FATAL: "+me.getMessage(), httpHeaders, HttpStatus.BAD_REQUEST);//400
}

我建议您使用ResponseEntity代替。{ @ResponseStatus(value = HttpStatus.BAD_REQUEST)@ResponseBody

因为:

  1. ResponseEntity更灵活
  2. 使用@ResponseStatus,您必须完全确保该方法只能返回 HttpStatus (只有一个)

答案 3 :(得分:0)

以下是我解决这个问题的方法:

我将我的Spring版本从3.2.2更新为4.0.3(最近也应该有效)。

然后,@ControllerAdvice接受basePackage参数:

@ControllerAdvice(basePackages = "me.myself.hi")
public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler
{
    /** The associated logger. */
    private static final Logger LOGGER = LoggerFactory.getLogger(RestResponseEntityExceptionHandler.class);

    @ExceptionHandler(value = { HttpRestException.class })
    protected ResponseEntity<Object> handleConflict(final RuntimeException ex, final WebRequest request)
    {
        if (ex instanceof HttpRestException)
        {
            final HttpRestException restEx = (HttpRestException) ex;
            return handleExceptionInternal(ex, restEx.getMessage(), new HttpHeaders(), restEx.getHttpStatus(), request);
        }

        return handleExceptionInternal(ex, "Internal server error",
                new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR, request);
    }
}

basePackage指定分配给处理程序类的包。这意味着将关注此包(或子包)中定义的每个控制器。

对我来说,me.myself.hi是至少10个项目共享的基本包名。因此,即使控制器在另一个项目中,只要它位于以me.myself.hi开头的包下,就会在那里捕获HttpRestException。

请记住,异常不能在Controller级别处理,但只能抛出,@ControllerAdvice带注释的控制器将处理此异常并返回statuscode +错误消息。