我们有一个在Spring MVC中开发的大型代码库。以下代码遍及整个地方。
public @ResponseBody BaseResponse<String> getSomething() {
BaseResponse<String> response = new BaseResponse<String>();
try {
//something
} catch (Exception e) {
BaseError be = ExceptionHandler.errorResponse(e);
response.setError(be);
}
return response;
}
我很好奇是否可以使用方面对其进行重构或简化?
ie:可以在方面内调用ExceptionHandler但是如何在响应中设置错误?
感谢。
答案 0 :(得分:1)
我使用普通的Java + native AspectJ重新创建了你的情况,因为我不是Spring用户。但是这样的方面及其切入点在Spring AOP中应该是相同的,只有方面也需要是@Component
。
几个虚拟课程:
package de.scrum_master.app;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ResponseBody {}
package de.scrum_master.app;
public class BaseError {
private Exception e;
public BaseError(Exception e) {
this.e= e;
}
public String getMessage() {
return e.getMessage();
}
}
package de.scrum_master.app;
public class ExceptionHandler {
public static BaseError errorResponse(Exception e) {
return new BaseError(e);
}
}
package de.scrum_master.app;
public class BaseResponse<T> {
private String body;
private String error = "OK";
public void setBody(String body) {
this.body = body;
}
public void setError(BaseError be) {
error = be.getMessage();
}
@Override
public String toString() {
return "BaseResponse [body=" + body + ", error=" + error + "]";
}
}
驱动程序应用程序:
有两个目标方法返回BaseResponse<String>
,基本上与示例方法相同,随机抛出异常,但异常处理被剥离。我想这就是你想要实现的目标。
还有一种方法不是该方面的目标(作为负面测试案例)。
package de.scrum_master.app;
import java.util.Random;
public class Application {
private static final Random RANDOM = new Random();
public static void main(String[] args) {
Application application = new Application();
for (int i = 0; i < 5; i++) {
System.out.println(application.doSomething());
System.out.println(application.getSomething());
System.out.println(application.getSomethingElse());
}
}
public String doSomething() {
return "Doing something";
}
public @ResponseBody BaseResponse<String> getSomething() {
BaseResponse<String> response = new BaseResponse<String>();
if (RANDOM.nextBoolean())
throw new RuntimeException("cannot get something");
response.setBody("getting something");
return response;
}
public @ResponseBody BaseResponse<String> getSomethingElse() {
BaseResponse<String> response = new BaseResponse<String>();
if (RANDOM.nextBoolean())
throw new RuntimeException("cannot get something else");
response.setBody("getting something else");
return response;
}
}
错误处理方面:
package de.scrum_master.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import de.scrum_master.app.BaseError;
import de.scrum_master.app.BaseResponse;
import de.scrum_master.app.ExceptionHandler;
@Aspect
public class ErrorHandler {
@Around("execution(de.scrum_master.app.BaseResponse<String> *(..))")
public Object handleError(ProceedingJoinPoint thisJoinPoint) throws Throwable {
//System.out.println(thisJoinPoint);
try {
return thisJoinPoint.proceed();
} catch (Exception e) {
BaseError be = ExceptionHandler.errorResponse(e);
BaseResponse<String> response = new BaseResponse<String>();
response.setBody("uh-oh!");
response.setError(be);
return response;
}
}
}
控制台日志:
在这里,您可以很好地了解每个BaseResponse
是如何由cour应用程序代码或错误处理方面创建和填充的:
Doing something
BaseResponse [body=getting something, error=OK]
BaseResponse [body=uh-oh!, error=cannot get something else]
Doing something
BaseResponse [body=uh-oh!, error=cannot get something]
BaseResponse [body=getting something else, error=OK]
Doing something
BaseResponse [body=getting something, error=OK]
BaseResponse [body=getting something else, error=OK]
Doing something
BaseResponse [body=getting something, error=OK]
BaseResponse [body=getting something else, error=OK]
Doing something
BaseResponse [body=getting something, error=OK]
BaseResponse [body=uh-oh!, error=cannot get something else]