17

@ExceptionHandler を使用して春に例外を処理しています。コントローラーによってスローされた例外は、@ExceptionHandler で注釈が付けられたメソッドを使用してキャッチされ、それに応じてアクションが実行されます。すべてのコントローラーに @exceptionHandler を記述しないようにするために、 @ControllerAdvice アノテーションを使用しています。

すべてが期待どおりに正常に動作します。

これで、DelegatingFilterProxy と ContextLoaderListener を使用して実装されたフィルター (はい、特定の要件を処理するためのインターセプターではありません) ができました。

上記のフィルターから同じ例外をスローすると、コントローラーのケースで行われた方法でキャッチされません。ユーザーに直接投げられます。

ここで何が問題なのですか?

4

8 に答える 8

0

私のように、Spring 3.1 (わずか 0.1 バージョン遅れ@ControllerAdvice) で立ち往生している場合は、私が思いついたこのソリューションを試すことができます。


では、例外リゾルバーについて聞いたことがありますよね? そうでない場合は、ここを読んでください:

@Component
public class RestExceptionResolver extends ExceptionHandlerExceptionResolver {

    @Autowired
    //If you have multiple handlers make this a list of handlers
    private RestExceptionHandler restExceptionHandler;
    /**
     * This resolver needs to be injected because it is the easiest (maybe only) way of getting the configured MessageConverters
     */
    @Resource
    private ExceptionHandlerExceptionResolver defaultResolver;

    @PostConstruct
    public void afterPropertiesSet() {
        setMessageConverters(defaultResolver.getMessageConverters());
        setOrder(2); // The annotation @Order(2) does not work for this type of component
        super.afterPropertiesSet();
    }

    @Override
    protected ServletInvocableHandlerMethod getExceptionHandlerMethod(HandlerMethod handlerMethod, Exception exception) {
        ExceptionHandlerMethodResolver methodResolver = new ExceptionHandlerMethodResolver(restExceptionHandler.getClass());
        Method method = methodResolver.resolveMethod(exception);
        if (method != null) {
            return new ServletInvocableHandlerMethod(restExceptionHandler, method);
        }
        return null;
    }

    public void setRestExceptionHandler(RestExceptionHandler restExceptionHandler) {
        this.restExceptionHandler = restExceptionHandler;
    }

    public void setDefaultResolver(ExceptionHandlerExceptionResolver defaultResolver) {
        this.defaultResolver = defaultResolver;
    }
}

次に、ハンドラーの例は次のようになります

@Component
public class RestExceptionHandler {

    @ExceptionHandler(ResourceNotFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    @ResponseBody
    public Map<String, Object> handleException(ResourceNotFoundException e, HttpServletResponse response) {
        Map<String, Object> error = new HashMap<>();
        error.put("error", e.getMessage());
        error.put("resource", e.getResource());
        return error;
    }
 }

もちろん、ビーンの登録を忘れることはありません


次に、必要なフィルターの前に呼び出されるフィルターを作成します (オプションですべてのフィルター)

次に、そのフィルターで

try{
   chain.doFilter(request, response);
catch(Exception e){
   exceptionResolver(request, response, exceptionHandler, e);
   //Make the processing stop here... 
   return; //just in case
}
于 2016-11-07T11:04:24.360 に答える
0

以下のコード スニペットを確認してください。

final HttpServletResponseWrapper wrapper = new 
HttpServletResponseWrapper((HttpServletResponse) res);    
wrapper.sendError(HttpServletResponse.SC_UNAUTHORIZED, "<your error msg>");    
res = wrapper.getResponse();

これをフィルター内で使用している場合は、return ステートメントを追加します。そうしないchain.doFilter(req,res)と、これがオーバーライドされます。

于 2016-03-21T18:32:37.407 に答える