首先说明 一下需求,有若干个 jsp 页面,想使用同一个 jsp 做 parent 然后, 每个 view 只放入 parent 的某个节点下面,比如 content。
很简单的一个需求但是至少花了我三天的时间。由于是使用的 google,所以就想把通过不断的自我提问以及根据网上人们的答案一步步缩小问题范围,修正精炼需求的过程记录下来。顺便看一下 google 是如何一步步引导自己走向新的不熟悉的领域。再看一下自己是如何一步步步入歧途,以及如何迷途知返的。
知道需求我们就开始去寻找解决方案吧。因为我用的是 spring mvc,所以先看看官方有没有解决方案吧。
1, google “spring mvc view adapter”,
第一个结果就是 22. Web MVC framework - Spring spring mvc的官方文档,看了当没看,不够既然是官方文档那也是要看一下的,
2, 更改搜索关键词 “spring mvc”
看了 Getting Started · Serving Web Content with Spring MVC
又看到了第一步的搜索结果,还是点进去,还是一样,还是看下吧,
说是让看下 Chapter 23, View technologies 看下吧又不少块肉。
3,google “sprint mvc set up global template”
4,google “sprint mvc set up common parent template”
java - Spring MVC parent template model component - Stack Overflow 没啥用
5,没头绪还是看下官方文档吧。我去,没目录,这么多内容不方便寻找目标,下个 “html5 ouliner”,顺便下个 pdf http://docs.spring.io/spring/docs/current/spring-framework-reference/pdf/spring-framework-reference.pdf
6,google “spring mvc combine two template”
7,继续 google “spring mvc merge two template”
终于有点好结果了 java - Spring how to merge an external html page with generated …, 有人回答用到了 filter 好消息
8,乘胜追击 google “spring merge two template”
然而没有更多信息了。
9,继续看下 google “spring view digram” 自动帮我更正成了 “spring view diagram”
这张图片不错,表明了 spring mvc 的处理流程。
10,google “spring merge view template”
11,google “spring view template proxy”
没有好的结果
12,google “spring view template delegate”
哟不错出现了两个好的结果
“java - Process output after template engine in Spring MVC - Stack …”
“java - How to manually render Spring MVC view to html? - Stack …“
嗯,有不用 filter 的解决方案了,自定义 viewClass,那就搜下 spring boot 是咋自定义 viewClass,看看官方文档http://docs.spring.io/spring-boot/docs/1.1.4.RELEASE/reference/htmlsingle/#common-application-properties 没有。。。那就 google 吧
13,google “spring boot viewclass property”
java - How to configure spring boot mvc app for JSP? - Stack Overflow
不错的结果
12345678 public InternalResourceViewResolver setupViewResolver() {InternalResourceViewResolver resolver = new InternalResourceViewResolver();resolver.setPrefix ("/ui/jsp/");resolver.setSuffix (".jsp");resolver.setViewClass (JstlView.class);return resolver;}顺便还搞清楚了
1234 <dependency><groupId>javax.servlet</groupId><artifactId>jstl</artifactId></dependency>Embedded Tomcat core package has no JSP rendering support.
14,google “spring view life cycle”
spring mvc - SpringMVC lifecycle– the overall view - Stack Overflow 里面又提到官方文档 Spring Framework Reference 看一眼吧
Spring MVC Request Lifecycle Diagram - Spring Forum 提到了一张图片 https://www.flickr.com/photo_zoom.gne?id=89101625&size=l 明明这个结果就是通过搜索结果进去的,现在的结果里咋就看不到了呢
剩下来的就是写代码了。
情况并不是想象的那么好
JstlView 的自定义并不是想象的那么好弄。
15,先研究下 ViewAndModel, google “ModelAndView”
16,峰回路转在研究 ViewAndModel 的时候回看 google
“jstlview” 的结果 [View]2 详解JSP和JSTL视图(InternalResourceView,JstlView … 看到了 void setDefaultParentView(String defaultParentView)
这个方法,不管了先试试看。
17,parent 在 ResourceBundleViewResolver 里面到底是什么鬼,好像只是继承关系,并不满足要求。
google “spring ResourceBundleViewResolver parent” 倒是提到了一本书Expert Spring MVC and Web Flow - 第 211 页 - Google 图书结果 (pdf) 抽空看一下
google “spring “setDefaultParentView””
看起来好像只是设置了默认 view
18, google “modelandview to html”
第一个结果 java - Get html content from spring ModelAndView - Stack Overflow 是想要的结果但是是给的伪代码,这个年代不给出明确的代码还真难再 spring 里面走。继续看看其他结果吧
诶,这个结果不是12步里面的结果吗? “java - How to manually render Spring MVC view to html? - Stack …“ 手动转换 child jsp 到 html 再当成 ModelMap 属性传给 global;世界真是转圈圈。
19,顺便 google “ModelAndView”
What is Model in ModelAndView from Spring MVC? - Stack Overflow 了解了怎么传值给jsp
20,午休的时候不死心 google “spring view common wrapper”
wrap template with a parent layout using thymeleaf - Stack Overflow 好结果,不过用到了模版引擎。在第一个回答里面的comments 里面有个链接,额好像是个人服务器,已经关了,还好有 google 快照,关键的地方有个 fragments。
21,尝试 google “spring jsp fragments”
ajax - Render partial JSP fragments in Spring MVC? - Stack Overflow 哈就是跟我现在要做的一样。
Spring MVC: from JSP and Tiles to Thymeleaf 第二个结果好像非 Thymeleaf 不用了,等等
<jsp:include page="../footer.jspx"/>
试试看呢,为啥一开始没是这种方法呢。。 。<%@ include file = "./lrcpage.jsp" >
一开始用的这种方法,报语法错误:joy:。
22,应该是在 19 步的时候 gooogle “spring “setDefaultParentView””
SpringMVC源码分析(8)剖析ViewResolver - 简单- 51CTO技术博客 得到一个有用的信息
InternalResourceViewResolver会把返回的视图名称都解析为InternalResourceView对象,InternalResourceView会把Controller处理器方法返回的模型属性都存放到对应的request属性中,然后通过RequestDispatcher在服务器端把请求forword重定向到目标URL。
现在的情况就是在返回视图名称的时候替换成 “global” 然后把原视图名称放到 “ModelMap” 的 “template” 属性里面。
23,回头看一下 9 里面的 spring 处理流程图。再研究下源码。
24,试想一下我们是不是可以自己写 handler 或 hanler adapter 来处理返回的视图名称。或者 aop 呢
25,google “spring 拦截controller 返回的视图名称”
26,google “spring aop return”
java - How to change the return value by spring aop - Stack Overflow
有人建议用 @Around 看一下他提供的链接吧
我的代码是:
|
|
多次试验的结果是上面代码返回的 global 可以在 DispatcherServlet debug 看到,但是 报 File [/WEB-INF/jsp/.jsp] not found
google 也没结果。奇怪了为啥 view 的名字不见了。
27,google “spring aspect on controller”
java - Spring AOP pointcut for all methods in a controller - Stack Overflow 提到了 @ControllerAdvice
28,google “spring aspect on controller change return view name”
java - AspectJ - around advice for controller request methods not … 提到 HandlerInterceptor
29,google “@ControllerAdvice sample” 验证了并不是我想要的结果
Spring MVC Exception Handling using @ControllerAdvice annotation 只是用来处理 Exception
回到 <26>,为啥 view 的名字在RequestDispatcher
forward 的时候丢掉了呢。26>
30,在 <28> 的结果里同时提到 Spring 3 MVC @Controller with AOP interceptors?28>
Note
When using controller interfaces (e.g. for AOP proxying), make sure to consistently put all your mapping annotations - such as @RequestMapping and @SessionAttributes - on the controller interface rather than on the implementation class.猜想可能就是写法的问题。结合上面提到的,需要自定义一个 annotation 并且放到
@RequestMapping
的上面。一试果然正常了。亲哥,你是我的亲哥啊。等等……上面好像没有提到位置的问题啊。并且没有 top bottom 关键字啊。唉!不管了。反正成功了。
总结
从一开始得到一个能用的结果。
到
|
|
最终到我们熟悉的写法
|
|
为了找到一个最优美的解决方案,经过不懈的努力,终于如愿以偿。