我希望为我的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
将代表网站菜单的内容添加到模型中。
但这提出了两个问题:
Model
建议方法中获取@AfterReturning
个实例,以防建议方法中缺少该实例(如.index()
中所述)?Method
注释所有方法(如java反射Class
)和类(如java反射@RequestMenuMapping
)以构建完整的菜单索引?答案 0 :(得分:2)
我认为更好的解决方案是使用bean后处理器来扫描@RequestMenuMapping
和HandlerInterceptor
的所有控制器类,以将菜单项添加到每个模型映射中。
答案 1 :(得分:1)
Q1:
ModelAndView
对象在org.springframework.web.servlet.DispatcherServlet.doDispatch()
// 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.使用反射。
Class clazz = Class.forName(classStr);
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
if (method.isAnnotationPresent(RequestMapping.class)
&& method.isAnnotationPresent(RequestMenuMapping.class)) {
// do something
}
}
答案 2 :(得分:1)
拦截器演示:
@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
对象可以获得您想要的内容。