废话有点多。。大家谅解下啊,如果着急的话可以直接下拉到底部,上面是我的解决历程。。
这个问题一般是遇不到的,只怪我们项目是在奇葩。事情是这样的,我们先开发的项目要集成进去一个老项目,新项目用的是html,但是老项目用的是Jsp,而且老项目功能完善,只是前端有点问题。
问题有了,那总得解决是吧。现在有很多种办法:1、把Jsp改成Html;2、用request.getDispacter()去跳转;3、研究一下spring的视图解析器。
第一种:实在是比较麻烦,我这种懒的人不到万不得已是不会采用这种方式的。
第二种:比第一种还要麻烦,既要改后端,还要改前端,因为这样跳转,得用jsp的内置对象去获取传递参数了,果断舍去。
第三种:说到第三种,我们就不得不先说一下spring视图解析器的源码了。
protected View resolveViewName(String viewName, @Nullable Map<String, Object> model,
Locale locale, HttpServletRequest request) throws Exception {
if (this.viewResolvers != null) {
for (ViewResolver viewResolver : this.viewResolvers) {
View view = viewResolver.resolveViewName(viewName, locale);
if (view != null) {
return view;
}
}
}
return null;
}
在DispacterServlet中找到这个方法,可以看见spring是循环所有的视图解析器,然后返回解析结果不为空的视图。
因此,如果我们想要即返回jsp,又返回html,就必须要加一个Jsp的视图解析器。
经过网上的资料查找和作为程序员的经验以及源码(具体源码在哪我忘了),我们可以发现,一个视图解析器必须得包含前缀,后缀等东西,所以得出的代码如下:
@Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/");
viewResolver.setSuffix(".jsp");
viewResolver.setOrder(0);
viewResolver.setContentType("text/html;charset=UTF-8");
return viewResolver;
}
加上去之后呢启动项目,我们发现项目所有都当成jsp去跳转了。分析了一下,发现可能,是因为order的原因,因为前面DispacterServlet中的代码也说了,只要view不为空就会返回回去。然后我就再配了一个html视图解析器,没用默认的,并且我把优先级也修改了一下,代码如下。
@Bean
public InternalResourceViewResolver htmlViewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/");
viewResolver.setSuffix(".html");
viewResolver.setOrder(0);
viewResolver.setContentType("text/html;charset=UTF-8");
return viewResolver;
}
@Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/");
viewResolver.setSuffix(".jsp");
viewResolver.setOrder(1);
viewResolver.setContentType("text/html;charset=UTF-8");
return viewResolver;
}
可是这样所有的都解析成html去了,我不得不再次跟了一下源码,发现即使没有页面,view依旧不为空,这样不就肯定都当成Html处理了么,我们现在需要一个能去检测是否有这个页面的东西。经过一番折腾之后,我们需要创建一个这样的类:
public class HandleResourceViewExists extends InternalResourceView {
@Override
public boolean checkResource(Locale locale) {
File file = new File(this.getServletContext().getRealPath("/") + getUrl());
return file.exists(); //判断页面是否存在
}
}
其实就是一个检查器,然后我们把我们的检查器设置到我们自定义解析器上面,最终的代码如下:
@Bean
public InternalResourceViewResolver htmlViewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/");
viewResolver.setViewClass(HandleResourceViewExists.class); //设置检查器
viewResolver.setSuffix(".html");
viewResolver.setOrder(0);
viewResolver.setContentType("text/html;charset=UTF-8");
return viewResolver;
}
@Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(HandleResourceViewExists.class); //设置检查器
viewResolver.setPrefix("/WEB-INF/");
viewResolver.setSuffix(".jsp");
viewResolver.setOrder(0);
viewResolver.setContentType("text/html;charset=UTF-8");
return viewResolver;
}