为Spring MVC / AOP应用程序实现动态菜单

我希望为我的Spring MVC应用程序实现动态可更改的菜单(在添加带注释的方法或控制器时更新)。

我想要的是引入新的注释( @RequestMenuMapping ),它将转到@Controller bean及其方法(就像@RequestMapping一样)。

Heres是我想要的, User类,生成菜单之类的

 Users Index | List | Signup | Login 

使用以下代码:

 @Controller @RequestMapping("user") @RequestMenuMapping("Users") public class User { @RequestMapping("") @RequestMenuMapping("Index") public String index(/* no model here - just show almost static page (yet with JSP checks for authority)*/) { return "user/index.tile"; } @RequestMapping("list") @RequestMenuMapping("List") public String list(Model model) { model.addAttribute("userList",/* get userlist from DAO/Service */); return "user/list.tile"; } @RequestMapping("signup") @RequestMenuMapping("Signup") public String signup(Model model) { model.addAttribute("user",/* create new UserModel instance to be populated by user via html form */); return "user/signup.tile"; } @RequestMapping("login") @RequestMenuMapping("Login") public String login(Model model) { model.addAttribute("userCreds",/* create new UserCreds instance to be populated via html form with login and pssword*/); return "user/login.tile"; } } 

我认为Spring AOP可以帮助我使用@RequestMenuMapping注释@AfterReturning方法,并通过@AfterReturning将代表网站菜单的内容添加到模型中。

但这提出了两个问题:

  1. 我如何在@AfterReturning建议方法中获取Model实例,以防它在.index()方法中丢失(如.index() )?
  2. 我如何获得所有方法(如在javareflectionMethod )和使用@RequestMenuMapping注释的类(如在javareflectionClass )以构建完整的菜单索引?

InterceptorDemo:

 @Aspect @Component public class InterceptorDemo { @Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)") public void requestMapping() { } @Pointcut("@annotation(you.package.RequestMenuMapping)") public void requestMenuMapping() { } @AfterReturning("requestMapping() && equestMenuMapping()") public void checkServer(JoinPoint joinPoint,Object returnObj) throws Throwable { Object[] args = joinPoint.getArgs(); Model m = (Model)args[0]; // use joinPoint get class or methd... } } 

如果你想用你自己拦截Contoller,你可以得到另一个切入点, ProceedingJoinPoint对象可以得到你想要的。

我认为一个更好的灵魂将是一个bean后处理器来扫描所有控制器类的@RequestMenuMapping和一个HandlerInterceptor来将菜单项添加到每个模型映射。

Q1:在org.springframework.web.servlet.DispatcherServlet.doDispatch()创建ModelAndView对象

 // Actually invoke the handler. mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); // Do we need view name translation? if (mv != null && !mv.hasView()) { mv.setViewName(getDefaultViewName(request)); } 

因此,您可以在撤消或覆盖该方法后拦截handle方法。

Q2:据我所知,有两种方法可以获得注释方法。

1.使用AOP:您可以声明这样的切入点:

 @Pointcut("@annotation(you.package.RequestMenuMapping)") public void requestMenuMappingPountcut() { } 

2.使用reflection。

 Class clazz = Class.forName(classStr); Method[] methods = clazz.getDeclaredMethods(); for (Method method : methods) { if (method.isAnnotationPresent(RequestMapping.class) && method.isAnnotationPresent(RequestMenuMapping.class)) { // do something } }