为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
将代表网站菜单的内容添加到模型中。
但这提出了两个问题:
- 我如何在
@AfterReturning
建议方法中获取Model
实例,以防它在.index()
方法中丢失(如.index()
)? - 我如何获得所有方法(如在javareflection
Method
)和使用@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 } }