问题描述
我正在Web环境中使用Spring Framework
4.3.3.
I am working with Spring Framework
4.3.3 in a web environment.
我有一个@Controller
用于通过Web Browser
的Web
请求,该请求使用其他@Controller
的依赖关系但用于Rest
的目的.后者提到使用@Service
等...
I have a @Controller
used for Web
requests through a Web Browser
that uses how dependency other @Controller
but for Rest
purposes. It latter mentioned uses a @Service
etc...
关于这种使用'Rest'的'Web'的方法,如何在进行内容协商.直到这里进行开发/测试和生产工作正常.这是一种有价值的方法.
This approach about a 'Web' using a 'Rest' how a dependency is explained in Content Negotiation using Spring MVC for the Combining Data and Presentation Formats
section. Until here for development/testing and production works fine. It is a valuable approach.
注意 Rest
类用@Controller
注释,因为我使用ResponseEntity<?>
和@ResponseBody
.
Note The Rest
class is annotated with @Controller
because I work with ResponseEntity<?>
and @ResponseBody
.
问题出在AOP
关于我的基础架构,
@Configuration
@EnableAspectJAutoProxy
public class AopConfig {
}
关于@Controller
,我有以下两个类:
About the @Controller
s I have these two classes:
-
PersonaDeleteOneController
具有:-
deleteOne(@PathVariable String id, Model model)
为@GetMapping
-
deleteOne(@PathVariable String id, RedirectAttributes redirectAttributes)
为@DeleteMapping
PersonaDeleteOneController
with:deleteOne(@PathVariable String id, Model model)
for@GetMapping
deleteOne(@PathVariable String id, RedirectAttributes redirectAttributes)
for@DeleteMapping
-
deleteOne(@PathVariable String id)
为@DeleteMapping
这两个类在同一个名为
-
com.manuel.jordan.controller.persona
我有以下
@Pointcut
:@Pointcut(value= "execution(* com.manuel.jordan.controller.*.*Controller.deleteOne(String, ..)) && args(id) && target(object)") public void deleteOnePointcut(String id, Object object){}
该
@Pointcut
用于以下建议:@Before(value="ControllerPointcut.deleteOnePointcut(id, object)") public void beforeAdviceDeleteOne(String id, Object object){ logger.info("beforeAdviceDeleteOne - @Controller: {} - Method: deleteOne - id: {}", object.getClass().getSimpleName(), id); }
当我执行
Rest
测试时,我可以通过AOP + logging
进行确认,并打印出以下图案:When I execute the
Rest
tests I can confirm throughAOP + logging
that prints the following pattern:-
@Controller
( Rest )->@Service
->@Repository
@Controller
(Rest) ->@Service
->@Repository
直到这里一切正常
当我执行
Web
测试时,我可以通过AOP + logging
进行确认,并打印出以下图案:When I execute the
Web
tests I can confirm throughAOP + logging
that prints the following pattern:-
@Controller
( Rest )->@Service
->@Repository
@Controller
(Rest) ->@Service
->@Repository
我需要或期望的是以下内容:
What I need or expect is the following:
-
@Controller
( Web )->@Controller
( Rest )->@Service
->@Repository
@Controller
(Web) ->@Controller
(Rest) ->@Service
->@Repository
出什么问题或遗漏了什么?
deleteOne
签名的参数并不明确.What is wrong or missing?. The
deleteOne
signatures are not ambiguous about their parameters.生产情况相同.
Alpha
这里的控制器:
@Controller @RequestMapping(value="/personas") public class PersonaDeleteOneController { private final PersonaRestController personaRestController; @Autowired public PersonaDeleteOneController(PersonaRestController personaRestController){ this.personaRestController = personaRestController; } @GetMapping(value="/delete/{id}", produces=MediaType.TEXT_HTML_VALUE) public String deleteOne(@PathVariable String id, Model model){ model.addAttribute(personaRestController.findOneById(id)); model.addAttribute("root", "/personas/delete"); return "persona/deleteOne"; } @DeleteMapping(value="/delete/{id}", produces=MediaType.TEXT_HTML_VALUE) public String deleteOne(@PathVariable String id, RedirectAttributes redirectAttributes){ personaRestController.deleteOne(id); redirectAttributes.addFlashAttribute("message", "process.successful"); return "redirect:/message"; } }
还有
@Controller @RequestMapping(value="/personas") public class PersonaRestController { private final PersonaService personaService; @Autowired public PersonaRestController(PersonaService personaService){ this.personaService = personaService; } @DeleteMapping(value="/{id}") public ResponseEntity<Void> deleteOne(@PathVariable String id){ personaService.deleteOne(id); return ResponseEntity.noContent().build(); } ....
如何看到我不使用
this.
来执行方法调用.How you can see I don't use
this.
to execute the method invocations.推荐答案
似乎问题出在您
pointcut
定义中.您可能会注意到,建议方法仅对具有一个参数的方法执行,这是由于您在切入点声明中指定了args(id)
.如果删除args(id)
,它必须能够按预期工作,但是在这种情况下,必须使用某些解决方法来公开参数值.Seems that the problem is in you
pointcut
definition. You may notice that your advice method is performed only for methods with one parameter, so this is due to the fact that you have specifiedargs(id)
in the pointcut declaration. It must work as you expect if you removeargs(id)
, but in this case some workaround must be used to expose parameter value.我认为这是AspectJ的一种奇怪行为,因为类似
execution(* *.*(String, ..)) && args(arg) && target(t))
的结构具有清晰的语义,可以捕获具有String
第一个参数的所有方法并将其公开给args
.至少对于AspectJ开发人员而言,它可能是错误或功能.I think that this is strange behavior form AspectJ because constructions like
execution(* *.*(String, ..)) && args(arg) && target(t))
has clear semantic sense to capture all the methods withString
first parameter and expose it toargs
. It can be a bug or feature, at least, to AspectJ developers.要获得所需的内容,可以对内部建议方法使用
joinPoint.getArgs()
的变通方法,如下所示:To get what you want, you can use a workaround with
joinPoint.getArgs()
inside advice method like this:@Pointcut(value= "execution(* com.manuel.jordan.controller.*.*Controller.deleteOne(..)) && target(object)") public void deleteOnePointcut(Object object){} @Before(value="ControllerPointcut.deleteOnePointcut(object)") public void beforeAdviceDeleteOne(JoinPoint jp, Object object){ Object id = jp.getArgs()[0]; logger.info("beforeAdviceDeleteOne - @Controller: {} - Method: deleteOne - id: {}", object.getClass().getSimpleName(), id); }
这篇关于Spring MVC和AOP:@Pointcuts仅适用于Rest控制器,不适用于常见的Web控制器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!
-