如何使用自定义处理程序处理由方面抛出的异常

时间:2016-04-18 20:22:46

标签: java spring aop spring-aop

我正在与AOP和自定义错误处理程序进行战斗。 我有一个控制器" WorkingController" - 它按预期工作。

@Controller
public class WorkingController extends BaseController {
    ​
    @RequestMapping("/welcome")
    public ModelAndView helloWorld() {
        return new ModelAndView("welcome", "message", "<h3>********** Hello World, Success!</h3>");
    }
    ​
    @RequestMapping("/success")
    public void test(HttpServletResponse response) {
        writeResponse(response, "Success!", ContentType.TEXT_JSON);
    }
    ​
    @RequestMapping("/test")
    public void test2(HttpServletResponse response) throws IOException {
        throw new IOException("This exception should be handled by custom handler.");
    }
    ​
    @InterestingMethod
    @RequestMapping("/aspect")
    public void test3(@InterestingArg @RequestParam(value = "id", required = false) String id,
                      HttpServletResponse response) throws IOException, AccessDeniedException {
        throw new IOException("This exception should also be handled by custom handler.");
    }
}
​
class BaseController {

    @ExceptionHandler(Exception.class)
    public void handleException(Throwable ex, HttpServletRequest request, HttpServletResponse response) {
        System.out.println("Exception handled by BaseController, great work!: " + ex.getMessage());
        ServletUtil.writeResponse(response, JSONObject.fromObject("Error").toString(),
                ContentType.TEXT_JSON.toString(), false, "UTF-8");
    }
    ​
    void writeResponse(HttpServletResponse response, String data, ContentType contentType) {
        ServletUtil.writeResponse(response, data, contentType.toString(), false, "UTF-8");
    }
    ​
}

我的情况迫使我创建界面,标记我的控制器,Aspect会检查用户是否有权访问给定的端点 - 所以我有MarkedController接口和NotWorkingController。

@Controller
public class NotWorkingController extends BaseController implements MarkedController {

    public void test2(HttpServletResponse response) throws IOException {
        throw new IOException("NotWorkingController, This exception should be handled by custom handler.");
    }
    ​
    @InterestingMethod
    public void test3(@InterestingArg String id,
                      HttpServletResponse response) throws IOException, AccessDeniedException {
        throw new IOException("NotWorkingController, This exception should also be handled by custom handler.");
    }
}
​
@Controller
public interface MarkedController {
    ​
    @RequestMapping("/test2")
    void test2(HttpServletResponse response) throws IOException;

    @RequestMapping("/aspect2")
    void test3(@RequestParam(value = "id", required = false) String id,
               HttpServletResponse response) throws IOException, AccessDeniedException;
}

@Aspect
public class InterestingMethodAspect {
    @Pointcut("@annotation(interestingMethod)")
    public void interestingMethodPointcut(InterestingMethod interestingMethod) {
    }

    @Before("(interestingMethodPointcut(interestingMethod))")
    public void asd(JoinPoint joinPoint, InterestingMethod interestingMethod) throws AccessDeniedException {
        processArguments(joinPoint);
    }

    private void processArguments(JoinPoint joinPoint) throws AccessDeniedException {
        throw new AccessDeniedException("You don't have access to this endpoint.");
    }
}

这对我来说有点神奇,因为:

  1. 在NotWorkingController中,Aspect代码抛出的异常不由自定义异常处理程序(位于BaseController中)处理。
  2. 我被迫将所有@RequestMappings移动到界面 - 在我的情况下它有点烦人。怎么预防?
  3. 那么,我应该在哪里看,我应该检查什么? 提前感谢任何建议。

    BTW:完整的maven项目可用here

1 个答案:

答案 0 :(得分:0)

嗯,我有答案。

对于第一个问题(异常捕获): HandlerExceptionResolver完成了我所需要的一切。 我已在@ExceptionHandler中的handleException方法中删除了BaseController注释,HandlerExceptionResolver的自定义实现正在捕捉所有例外情况。)

第二个问题: 我不得不从基于JDK的代理切换到基于CGLIB的代理。