有时候我们需要 两种或者两种以上的视图解析方式,比如jsp,html,json,jstl,ftl等等,显然默认的 springmvc 只配置一种视图解析方式是满足不了我们的,但是放心,springmvc提供了配置多视图解析的方式:
本文使用的是velocity,实现需要引入jar包
pom文件中添加
<!-- velocity测试包 -->
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2</version>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
<version>1.7</version>
</dependency>
源码:
/*** Eclipse Class Decompiler plugin,copyright (c) 2012 Chao Chen (cnfree2000@hotmail.com) ***/
packageorg.springframework.web.servlet.view;
import java.util.Locale;
importorg.springframework.beans.factory.InitializingBean;
public abstract classAbstractUrlBasedView extends AbstractView implements
InitializingBean {
private String url;
protected AbstractUrlBasedView() {
}
protected AbstractUrlBasedView(String url) {
this.url = url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUrl() {
return this.url;
}
public void afterPropertiesSet() throws Exception {
if ((isUrlRequired()) &&(getUrl() == null))
throw newIllegalArgumentException("Property 'url' is required");
}
protected boolean isUrlRequired() {
return true;
}
public boolean checkResource(Locale locale) throws Exception{
return true;
}
public String toString() {
StringBuilder sb = new StringBuilder(super.toString());
sb.append("; URL[").append(getUrl()).append("]");
return sb.toString();
}
}
第一步
新建Java类,继承InternalResourceView类,重写checkResource方法
package com.ssm.springmvcpro;
import java.io.File;
import java.util.Locale;
importorg.springframework.stereotype.Component;
importorg.springframework.web.servlet.view.InternalResourceView;
@Component
public class VMProperties extendsInternalResourceView{
publicboolean checkResource(Locale locale){
Filefile = new File(this.getServletContext().getRealPath("/") +getUrl());
returnfile.exists();
}
/**
* 报java.lang.IllegalArgumentException:Property 'url' is required错误的时候重写该方法,原类返回true,重写后返回false
*/
publicboolean isUrlRequired(){
returnfalse;
}
}
其中isUrlRequired方法是启动项目报java.lang.IllegalArgumentException: Property 'url' is required的时候需要重写的方法(参考https://stackoverflow.com/questions/9933429/creating-a-custom-view-resolver-in-spring-mvc-property-url-is-required)
第二步
在springmvc.xml文件中指定解析器的 viewClass为刚刚写的java类
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">
<!-- 拦截器 -->
<mvc:interceptors>
<bean class="com.ssm.interceptor.MyInterceptor"></bean>
<mvc:interceptor>
<!--拦截的是controller类requestmapping的地址,不能拦截jsp页面 -->
<mvc:mapping path="/test/t2"/>
<bean class="com.ssm.interceptor.WelcomeInterceptor">
</bean>
</mvc:interceptor>
</mvc:interceptors>
<mvc:annotation-driven />
<context:component-scan base-package="com.ssm">
</context:component-scan>
<!-- 内容协商管理器 -->
<!--1、首先检查路径扩展名(如my.pdf);2、其次检查Parameter(如my?format=pdf);3、检查Accept Header -->
<bean id="contentNegotiationManager"
class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<!-- 扩展名至mimeType的映射,即 /user.json => application/json -->
<property name="favorPathExtension" value="true" />
<!-- 用于开启 /userinfo/123?format=json 的支持 -->
<property name="favorParameter" value="true" />
<property name="parameterName" value="format" />
<!-- 是否忽略Accept Header -->
<property name="ignoreAcceptHeader" value="false" />
<property name="mediaTypes"> <!--扩展名到MIME的映射;favorPathExtension, favorParameter是true时起作用 -->
<value>
json=application/json
xml=application/xml
html=text/html
</value>
</property>
<!-- 默认的content type -->
<property name="defaultContentType" value="text/html" />
</bean>
<!-- 当在web.xml 中 DispatcherServlet使用 <url-pattern>/</url-pattern> 映射时,能映射静态资源 -->
<mvc:default-servlet-handler />
<!-- 视图渲染 jsp/freemaker/velocity -->
<bean id="jspResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="order" value="1"></property>
<!-- 制定页面存放的路径 -->
<property name="prefix" value="/WEB-INF/pages/"></property>
<!-- 文件jsp的后缀-->
<property name="suffix" value=".jsp"></property>
</bean>
<!-- 配置视图的显示 -->
<bean id="VMResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="order" value="0"></property>
<property name="viewClass" value ="com.ssm.springmvcpro.VMProperties"></property>
<property name="cache" value="false" />
<property name="prefix" value="/WEB-INF/vm/" /><!-- 视图文件的前缀,即存放的路径 -->
<property name="suffix" value=".vm" /><!-- 视图文件的后缀名 -->
<property name="contentType" value="text/html;charset=UTF-8" />
</bean>
</beans>
文件的位置需要根据你的项目修改
我的位置为
vm1.xml的内容随便写一点什么
<html>
<body>
<h2>Welcome $name to Javayou.com!
today is $date.</h2>
</body>
</html>
第三部
开始测试
我这是在ssm项目中,所以直接在controller中写
package com.ssm.controller;
import java.io.StringWriter;
importjava.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import javax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
import org.apache.velocity.Template;
importorg.apache.velocity.VelocityContext;
importorg.apache.velocity.app.Velocity;
importorg.apache.velocity.app.VelocityEngine;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.stereotype.Controller;
importorg.springframework.web.bind.annotation.RequestMapping;
importorg.springframework.web.bind.annotation.ResponseBody;
import com.ssm.entity.Book;
import com.ssm.service.BookService;
@Controller
@RequestMapping("/test")
public class GetBookController {
@Autowired
BookServicebookService;
@RequestMapping("/t1")
@ResponseBody
publicString getAllBook(){
List<Book>list = bookService.getAllBooks();
returnlist.get(0).toString();
}
@RequestMapping("/t2")
publicString reindex(){
return"welcome";
}
@RequestMapping("/t3")
publicObject reindexToVm(HttpServletRequest request, HttpServletResponse response)throws UnsupportedEncodingException{
//初始化参数
Propertiesproperties=new Properties();
//设置velocity资源加载方式为class
properties.setProperty("resource.loader","file");
//设置velocity资源加载方式为file时的处理类
properties.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH,
this.getClass().getResource("/").toString().replaceAll("^file:/","").replaceAll("classes","vm"));
properties.setProperty(Velocity.ENCODING_DEFAULT,"UTF-8");
properties.setProperty(Velocity.OUTPUT_ENCODING,"UTF-8");
//实例化一个VelocityEngine对象
VelocityEnginevelocityEngine=new VelocityEngine(properties);
//实例化一个VelocityContext
VelocityContextcontext=new VelocityContext();
//向VelocityContext中放入键值
context.put("name","黄伟");
context.put("date",new Date().toString());
//实例化一个StringWriter
StringWriterwriter=new StringWriter();
Templatetemplate =velocityEngine.getTemplate("vm1.vm");
template.merge(context,writer);
System.out.println(writer);
return"vm1";
}
}
t1是测试spring+mybatis的方法,暂时不看
这里 properties.setProperty的时候注意要把replaceall方法中的vm修改为自己对应的文件夹名字
到这里所有配置就已经完成了,接下来测试访问一下。
http://localhost:8080/SSM/test/t2
http://localhost:8080/SSM/test/t3
额。。。为什么不显示之前配置的名字和日期呢?
偶母鸡