Spring REST 错误处理:不能有我的自定义消息 [英] Spring REST error handling : Cannot have my custom message

查看:52
本文介绍了Spring REST 错误处理:不能有我的自定义消息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

<html><head><style type="text/css">*{margin:0px;padding:0px;background:#fff;}</style><title>;HTTP 错误</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></code></code>/p>

我的代码:Javascript:

create : function() {$scope.myObject.$save(功能(响应){在里面();$scope.popupCtrl.hideModal();$scope.popupCtrl.hideError();},功能(错误){//错误,我总是在那里得到 html 页面...$scope.popupCtrl.manageError(error.message);});}

我的控制器:

@RequestMapping(value = "myObject", method = RequestMethod.POST, products = "application/json")@ResponseBodypublic final String createNewCrawlConfiguration(@RequestBody final String receivedString){字符串 jsonString;尝试{jsonString = URLDecoder.decode(receivedString, "UTF-8");LOGGER.debug("正在准备要保存的配置.json : {}", jsonString);最终 JsonCCObject jsonObject = 新 JsonCrawlerObject(jsonString);//检查 json*//验证包含缺少属性的数组.如果 (!jsonObject.validate().isEmpty()){抛出新的 ConfigurationCreationException(HttpStatus.BAD_REQUEST,returnJsonError(new ArrayList<>(jsonObject.validate())));}//保存对象}catch (final UnsupportedEncodingException e){抛出新的 ConfigurationCreationException(HttpStatus.BAD_REQUEST,"不支持的编码:" + e.getMessage());}捕获(最终 JSONException e){抛出新的 ConfigurationCreationException(HttpStatus.BAD_REQUEST,"Json 异常:" + e.getMessage());}catch (final DuplicateKeyException e){抛出新的 ConfigurationCreationException(HttpStatus.BAD_REQUEST,"配置 portant le meme nom dejaexistante");}return buildReturnMessage("ok", "爬行配置正确添加");}public String buildReturnMessage(最终字符串状态,最终字符串消息){final String statusMessage = " {\"status\":\"" + status + "\", \"message\":\" " + message + " \"} ";LOGGER.debug(statusMessage);返回状态消息;}/*** 捕获 {@link ConfigurationCreationException} 并返回错误消息* @param configurationCreationException* @param 请求* @param 响应* @返回*/@ExceptionHandler(ConfigurationCreationException.class)@ResponseStatus(value = HttpStatus.BAD_REQUEST)@ResponseBodypublic String handleConfigurationCreationException(最终 ConfigurationCreationException configurationCreationException,最终的 WebRequest 请求,最终的 HttpServletResponse 响应){LOGGER.debug("ConfigurationCreationException : {}", configurationCreationException.getErrMessage());response.setContentType("application/json");response.setCharacterEncoding("UTF-8");返回 buildReturnMessage(configurationCreationException.getErrCode(),configurationCreationException.getErrMessage());}

你有什么想法吗?

谢谢!

<小时>

编辑

我的问题搞错了:

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

这里的问题仅在于检索客户端的自定义错误:/.

解决方案

我是这样解决的:

我将我的 Spring 版本从 3.2.2 更新到 4.0.3(更新的版本也可以).

然后,@ControllerAdvice 接受 basePackage 参数:

@ControllerAdvice(basePackages = "me.myself.hi")公共类 RestResponseEntityExceptionHandler 扩展了 ResponseEntityExceptionHandler{/** 关联的记录器.*/私有静态最终记录器 LOGGER = LoggerFactory.getLogger(RestResponseEntityExceptionHandler.class);@ExceptionHandler(value = { HttpRestException.class })受保护的 ResponseEntityhandleConflict(final RuntimeException ex, final WebRequest request){if (ex instanceof HttpRestException){最终 HttpRestException restEx = (HttpRestException) ex;return handleExceptionInternal(ex, restEx.getMessage(), new HttpHeaders(), restEx.getHttpStatus(), request);}return handleExceptionInternal(ex, "内部服务器错误",新的 HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR, request);}}

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

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

请记住,异常不能在控制器级别处理,而只能抛出,@ControllerAdvice 注释控制器将处理此异常并返回状态码 + 错误消息.

I read several articles/tutorials... about error handling on server side. I simply want to return an http error code with my custom message. And of course it does not work.

The result I'm always having in my javascript callbacks is this message :

<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>

My code : 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);
    });
}

My Controller :

@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());
}

Have you got any ideas ?

Thank you !


EDIT

I did a mistake on my question :

The html returned shows error 400. I haven't any media problem, it's the error I want to return. What I mean is that tomcat is not generating it, I do it myself with a throw new ConfigurationCreationException(HttpStatus.BAD_REQUEST,...).

The issue here is only about retrieving the custom error on the client side :/.

解决方案

Here is how I solved this :

I updated my Spring version from 3.2.2 to 4.0.3 (a more recent should work too).

Then, @ControllerAdvice accepts the basePackage parameters :

@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 specify the package assigned to the handler class. That means each controller defined in this package (or a sub one) will be concerned.

For me, me.myself.hi is a base package name shared by at least 10 projects. So even if a controller is in another project, as long as it is under a package starting with me.myself.hi, the HttpRestException will be catched there.

Remember that the exception must not be handled at the Controller level, but only thrown, the @ControllerAdvice annotated controller will handle this exception and return statuscode + error message.

这篇关于Spring REST 错误处理:不能有我的自定义消息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆