我有这样基于方面的日志记录:
@Pointcut("@annotation(Loggable)")
public void loggableAnnotation() {}
@Around("loggableAnnotation()")
public Object simpleProcess(ProceedingJoinPoint joinPoint) throws Throwable {
return this.processWithBody(joinPoint, null);
}
@Around("loggableAnnotation() && args(@org.springframework.web.bind.annotation.RequestBody body,..)")
public Object processWithBody(ProceedingJoinPoint joinPoint, Object body) throws Throwable {
// do things
}
当我使用RequestBody执行请求时,它工作正常,会触发adviceprocessWithBody()
。但是,当我执行没有@RequestBody的请求时(仅
@PathVariable和
@RequestParam)不会触发
simpleProcess()
,而是在processWithBody()
中,我接收路径变量值作为body
参数。
为什么会发生这种情况?我如何以不同的方式处理两种类型的请求(如果可能,在同一个通知中)?
你犯了三个基本的错误:
>
您的切入点语法是错误的,即使您将其转移到execution()
,例如执行(**(@org.springframework.web.bind.annotation.RequestBody*,…)
将匹配参数的有一个@RequestBody
注释,而不是参数本身
为了实现这一点,您需要将参数本身放入括号中,例如执行(**(@org.springframework.web.bind.annotation.RequestBody(*)),…)
。
您必须确保切入点是互斥的,否则多个建议将在同一个连接点上匹配。准确地说,您需要区分以下情况:
下面是纯Java AspectJ中的一个示例(没有Spring或Spring AOP),但Spring AOP中的方面语法应该相同:
注释驱动程序应用程序:
package de.scrum_master.app;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@Retention(RUNTIME)
@Target(METHOD)
public @interface Loggable {}
package de.scrum_master.app;
import org.springframework.web.bind.annotation.RequestBody;
public class Application {
public static void main(String[] args) {
Application application = new Application();
application.doNotLogMe("foo", 11);
application.doNotLogMeEither();
application.doNotLogMeEither("foo", 11);
application.logMe("foo", 11);
application.logMeToo("foo", 11);
application.logMeToo();
}
public void doNotLogMe(@RequestBody String body, int number) {}
public void doNotLogMeEither() {}
public void doNotLogMeEither(String body, int number) {}
@Loggable public void logMe(@RequestBody String body, int number) {}
@Loggable public void logMeToo(String body, int number) {}
@Loggable public void logMeToo() {}
}
方面:
如您所见,我正在使用区分上述三种情况的方法,并且还满足了您对一种常见辅助方法的需求,我称之为<代码>logIt(…) 。在那里,您可以放置所有想要使用的复杂日志记录,而不会在您的advice方法中有任何重复代码。
package de.scrum_master.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class MyAspect {
@Pointcut("@annotation(de.scrum_master.app.Loggable)")
public void loggableAnnotation() {}
@Around(
"loggableAnnotation() && " +
"execution(* *())"
)
public Object simpleProcessWithoutParameters(ProceedingJoinPoint joinPoint) throws Throwable {
return logIt(joinPoint, null);
}
@Around(
"loggableAnnotation() && " +
"execution(* *(!@org.springframework.web.bind.annotation.RequestBody (*), ..))"
)
public Object simpleProcessWithParameters(ProceedingJoinPoint joinPoint) throws Throwable {
return logIt(joinPoint, null);
}
@Around(
"loggableAnnotation() && " +
"execution(* *(@org.springframework.web.bind.annotation.RequestBody (*), ..)) && " +
"args(body, ..)"
)
public Object processWithBody(ProceedingJoinPoint joinPoint, Object body) throws Throwable {
return logIt(joinPoint, body);
}
private Object logIt(ProceedingJoinPoint joinPoint, Object body) throws Throwable {
System.out.println(joinPoint + " -> " + body);
return joinPoint.proceed();
}
}
控制台日志:
execution(void de.scrum_master.app.Application.logMe(String, int)) -> foo
execution(void de.scrum_master.app.Application.logMeToo(String, int)) -> null
execution(void de.scrum_master.app.Application.logMeToo()) -> null
附言:执行(**(@MyAnn*))
和执行(**(@MyAnn (*)))
)之间的区别很微妙,因此很棘手。不幸的是,这里没有正确记录它应该在的地方。准确地说,后一种情况根本没有记录,只是可能在一些AeyJ发行说明中,当然也在单元测试中。但是普通用户不会看那里。
我读过许多类似的问题,包括:JQuery、Spring MVC@RequestBody和JSON——使其能够将JSON请求与JQuery/Ajax与Spring一起工作 要求是服务器只会接受应用程序/json类型。我使用的是Spring MVC控制器。代码通过@响应体以JSON形式发送响应。我想通过我的Spring MVC控制器中的@Request estbody获取信息。我正在使用JSP将JSO
我有时区POJO如下: 我在Spring Controller中有如下updateTimeZone方法: 当我通过以下请求时: 然后,当映射到POJO时,它会自动将其他值转换为默认值,并变为: 因此,当我如下更新此POJO时 它自动覆盖TimeZone=null和小时差异=0.0, 那么有没有什么方法可以让我在@Request estbody中的TimeZoneDto只包含我在请求JSON中传递的
问题内容: 有人可以在Spring 3中解释@RequestBody和@ResponseBody注释吗?他们是干什么的?任何例子都很好。 问题答案: 在文档中有一个名为16.3.3.4的完整章节,其中将请求主体与@RequestBody批注进行映射。还有一个叫做16.3.3.5的映射,它使用@ResponseBody注释映射响应主体。我建议你查阅这些部分。也相关:@RequestBodyjavad
有人能解释一下Spring3中的和注释吗?它们是干什么用的?任何例子都很好。
我必须实现的逻辑是记录所有的请求与主体服务到数据库。 据我所知,在Controller中,我们可以使用和。我可以在重用它们吗?
我有: 和: 我不喜欢的是手动将从放入:。 对于正文为的POST请求,如何在中自动设置,以便您获得如下所示的? 基本上,我想要这样的东西: 有没有办法做到这一点? 谢谢你!:) 编辑:这是一个老问题,仍然没有答案,所以我想为这个问题添加新的视角。 我们遇到的另一个问题是验证,即基于某个字段和进行验证的特定定义的自定义约束。 如果我们从请求体中删除,那么我们如何从自定义约束中访问它呢?:)