浏览 4877 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2007-04-23
在项目开发过程中,面对一个需要对一个域对象进行查询明细,查询列表和查询该域对象的关联对象的案例,这里不包括对域对象进行更新的工作,这样如果采用实现Controller接口的话,每个实现类执行handleRequest返回ModelAndView来达到目的,很自然的将会产生3个实现类,这样项目的类文件数量增多,而且在以后维护工作中,虽然在一个用例中,仍然不得不从配置文件下手,一个一个根据映射找出对应的相应的Controller,这添加了维护的难度,所以这里我们很自然的采用了MultiActionController做实现。代码基本类似如下: public class BookMultiController extends MultiActionController{ //(1) public ModelAndView getBook(HttpServletRequest request, HttpServletResponse response) { ModelAndView mv = new ModelAndView("book/book_detail"); Book book = bookManager.getBook(request.getParameter("bookId")); mv.addObject("book", book); return mv; } //(2) public ModelAndView getBookList(HttpServletRequest request, HttpServletResponse response) { ModelAndView mv = new ModelAndView("book/book_list"); Book book = new Book(); BeanUtils.populate(book, request.getParameterMap()); List list = bookManager.getBooks(book); mv.addObject("bookList", list); return mv; } //(3) public ModelAndView getAuthorByBook(HttpServletRequest request, HttpServletResponse response) { ModelAndView mv = new ModelAndView("author/author_detail"); Author author = authorManager.getAuthorByBookId(request.getParameter("bookId")); mv.addObject("author", author); return mv; } } 在Url配置映射方面,我们使用了org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver,所以上述代码 的访问是: book.do?method=getBook&bookId=123; book.do?method=getBookList&bookName=JavaDesign&price=100; book.do?method=getAuthorByBook&bookId=123; 这样实现下来似乎很不错了。但是在开发过程中,这样情况还会出现很多,当我们碰到一个综合查询的时候,往往会有一颗树,点击树的每一个节点,通过传递一些参数,我们需要看到想要的结果显示在正确的页面。如果采用实现Controller的方法,那么每一个节点的点击将具体的对应到一个相应,通过处理返回ModelAndView。如果考虑这颗树的节点很多,那么是否应该随着节点的不断增加,controller也不断的增加,配置文件的不断增加呢?如果不这样,是否还是考虑使用MultiActionController呢?在这里我们的选择还是使用MultiActionController来实现,不过带来的后果就是有多少个节点,就意味着MultiActionController有多少个对应的方法执行来返回ModelAndView。在这里已经假设节点有很多的情况,那么就意味着这个Controller随着执行方法的增加,代码也会会很冗长。如果有30个节点的话,上面的方法将会有30个,代码一多,这时仔细看看,其实他们都很薄,也都很相似。这里薄和相似是他们 都没有像SimpleFormController那样需要绑定对象,对对象进行验证,保存和更新的动作,他们都是从用户请求那里拿到参数,然后返回给用户希望得到的东西,这就足够了。所以我们在这个基础上加了一些东西,让这些事情做起来更容易一些,在MultiActionController注入了一个IRequestHandler,由它来完成上述的需求,这样30个方法的查询,实现起来至多也就是2个。拿一开始的用例来举例,代码: public ModelAndView query(HttpServletRequest request, HttpServletResponse response) { requestHandler.dynamicInvocate(request); Solution solution = requestHandler.getSolution(); return new ModelAndView(solution.getPage(),solution.getModelName(),solution.getModel()); } public ModelAndView queryBook(HttpServletRequest request, HttpServletResponse response) { Book book = new Book(); BeanUtils.populate(book, request.getParameterMap()); Map<String,Object> map = new HashMap<String,Object>(); map.put("book", book); requestHandler.dynamicInvocate(request, map); Solution solution = requestHandler.getSolution(); return new ModelAndView(solution.getPage(),solution.getModelName(),solution.getModel()); } 对应的访问变成: query.do?method=query&purpose=getBook&bookId=123; query.do?method=queryBook&purpose=getBookList&bookName=JavaDesign&price=100; query.do?method=query&purpose=getAuthorByBook&bookId=123; 这里IRequestHandler有两个版本的dynamicInvocate,第一个最为简单,就是从请求控制域获取参数然后执行调用,并最终返回一个Solution对象,这里面封装了模型和视图。而第二个版本,则可以实现更多的参数传递的调用。如一开始的代码清单(2)中,是没有办法直接从请求中获取Book对象的,这样构建一个Map传递给调用,也能成功的得到模型和视图。完成了这些,回过头来再次考虑刚才那个拥有30个节点的树,如果足够幸运,所有的查询都是从request,或者session中获取的参数,那么只有一个MultiActionController类文件,并且只有一个方法。值得一提的是这个requestHandler我们是使用方法注入的,也就是他始终是以原型的形式出现,不会造成一些负面的影响,在我们系统测试运行期间,他运作的很好,效果还算满意。 大家对这样的设计有何看法,欢迎大家讨论。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2007-04-23
看了半天没太明白,
requestHandler算是业务层吗? 这么做是把controller里的多个方法提取成requestHandler里的一个方法吗?? 这样的好处是减少了配置文件的代码量吗? |
|
返回顶楼 | |
发表时间:2007-04-23
应该说requestHandler是直接处理业务请求的,他和handleRequest完成的工作一样,就是获取模型和准备视图,其他的业务逻辑代码还是在serivce
层完成,只不过requestHandler需要从我们自行定义的一个xml开始工作。 刚才可能没有说清楚,我上传一个类图。这里我们主要使用xml,当然也可以是其他载体。上面的三个代码实际上是被写到了xml文件中,而requestHandler 通过反射和WebApplicationContextUtils来完成工作。对应上述的三个方法,xml写成: <item name="getBook"> <operation action="bookManager" method="getBook"> <parameter match="request">bookId</parameter> </operation> <solution page="book/book_detail" modelName="book" /> </item> <item name="getBookList"> <operation action="bookManager" method="getBooks"> <parameter>bookName</parameter> <parameter>price</parameter> <parameter match="custom" type="com.test.model.Book">book</parameter> </operation> <solution page="book/book_list" modelName="bookList" /> </item> <item name="getAuthorByBook"> <operation action="authorManager" method="getAuthorByBookId"> <parameter match="request" type="java.lang.String" >bookId</parameter> </operation> <solution page="author/author_detail" modelName="author" /> </item> 在类图中,XmlParser在容器启动的时候,首先将xml解析成一组<String,Item>静态的映射,然后等待请求的到来。在这一组映射中的每一个Item,都由 Operation和Solution合成,Solution封装了model,view。而Operation封装了执行业务逻辑方法的manager,参数,方法。RequestHelper则根据xml中定 义的东东从request,session或者自定义的map中获取方法执行的参数,并WebApplicationContextUtils获取项目上下文,然后通过getBean获取manager, 那么这样一切准备就绪,requestHandler就可以开始工作了。这样相对一开始给出的那段(1),(2),(3)的代码清单,就变成了这样三段xml片断,以后的增 量不再写实际代码,而是写一段xml代码片断替代,维护工作就是从这一个xml开始,这样我们觉得还是值得的。 |
|
返回顶楼 | |