4

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

我想要的是引入新的注释(@RequestMenuMapping),它将用于@Controllerbean 及其方法(就像@RequestMapping作品一样)。

这是我想要的,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添加一些代表网站菜单的东西来建模。

但这提出了两个问题:

  1. 如果建议方法中缺少实例(如中) ,我如何Model在建议方法中获取实例?@AfterReturning.index()
  2. 我如何获取所有方法(如在 java 反射中Method)和类(如在 java 反射中Class@RequestMenuMapping以构建完整的菜单索引?
4

3 回答 3

2

我认为更好的解决方案是使用 bean 后处理器来扫描所有控制器类,@RequestMenuMapping然后HandlerInterceptor将菜单项添加到每个模型映射中。

于 2012-12-22T15:21:52.567 回答
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
    }
}
于 2012-12-22T13:30:04.410 回答
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对象可以得到你想要的。

于 2012-12-22T14:04:55.810 回答