也谈 SpringMVC多视图配置

本文详细介绍了如何在SpringMVC框架中集成Velocity模板引擎,包括Web.xml和spring-mvc.xml的配置步骤,以及如何编写Controller代码和Velocity模板。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近在springmvc上集成velocity,磕磕绊绊,总算是有所收获,在此记录一下。

   Velocity是一种易用的模板语言。Velocity将Java代码从Web 页面中分离出来,使用Web站点从长远看更容易维护,并且提供了一种可行的JavaServer Pages替代解决方案。除了JSP,Velocity可能是用于Web应用的最流行的模板语言之一。很多web系统也都采用Velocity作为视图层技术,Spring对Velocity作为视图模板语言提供了很好的支持。 

 

怎么配置,来,一步步走:

 

1、首先,在Web.xml进行配置,DispatcherServlet配置的映射为所有请求类型,这样以后如果要集成其他如Freemaker等只需要加入其配置就可以了。

  

 

	<servlet>
		<servlet-name>springmvc</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:spring-mvc.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>springmvc</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>

 

 

2、配置spring-mvc.xml

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	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/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">

	<!-- 自动扫描且只扫描@Controller -->
	<context:component-scan base-package="com.per.action"
		use-default-filters="false">
		<context:include-filter type="annotation"
			expression="org.springframework.stereotype.Controller" />
	</context:component-scan>

	<mvc:annotation-driven />

	<mvc:default-servlet-handler />

		<!-- 定义JSP视图解析器-->
	<bean id="jspViewResolver" 
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/views/" />
		<property name="suffix" value=".jsp" />
		<property name="contentType" value="text/html;charset=UTF-8" />
	</bean>
 
 
	 <!-- velocity视图解析器 -->

	 <!-- velocity环境配置 -->
    <bean id="velocityConfig" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
        <!-- velocity配置文件路径 -->
        <property name="configLocation" value="classpath:velocity.properties"/>
        <!-- velocity模板路径 -->
        <property name="resourceLoaderPath" value="/WEB-INF/velocity/"/>
    </bean>
    
     <bean id="velocityViewResolver" class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">
        <property name="cache" value="false"/>
        <property name="prefix" value=""/>
        <property name="suffix" value=".vm"/>
        <property name="contentType" value="text/html;charset=UTF-8" />
        <!-- 多ViewResovler配置 --> 
        <property name="order" value="1" />
    </bean>
	

</beans>

 注意,“order”属性是必须加的,为什么呢,可以查看我前一篇内容

 

SpringMVC ViewResolver查找序列

 

velocity.properties配置文件,位置要与spring-mvc.xml中配置的一样。

#encoding
input.encoding=UTF-8
output.encoding=UTF-8
contentType=text/html;charset=UTF-8

#autoreload when vm changed
file.resource.loader.cache=false
file.resource.loader.modificationCheckInterval=1
velocimacro.library.autoreload=true

runtime.log=velocity.log
#runtime.log.logsystem.class=org.springframework.ui.velocity.CommonsLoggingLogSystem
runtime.log.logsystem.class=org.apache.velocity.runtime.log.NullLogSystem
#runtime.log.logsystem.class=org.springframework.ui.velocity.NullLogSystem
runtime.log.error.stacktrace=false
runtime.log.warn.stacktrace=false
runtime.log.info.stacktrace=false
runtime.log.invalid.reference=false

 

当然这里面的jspViewResover和velocityViewResover是可以单独运行的,合并也是可以运行的,不过我集成时,运行一个JSP,页面是正常的,但日志总是会提示“[Error]Resource Not Found :xxxx.vm”,查了资料都说这个可以ignore,可是怎么设置呢,这个很头疼,试着去掉velocity.jar包中日志配置也不行,可日志不能老让报error啊,求解

当然还有方法,就是打开ResourceBundleViewResover这个配置,设置view.properties,在里面加入视图的路径配置,这样就不会报异常了,也是可以正常运行的。可是新的问题来了,一个是页面会有乱码,到我写这篇文字的时候也没能解决,高人指点下啊;另外一个是你的controller的每个view路径都要在view.properties中配置,这也比较麻烦,毕竟一个项目那么多view呢

 

修改后,加入ResourceBundleViewResover配置:

 

	<!-- ResourceBundleViewResolver用于多个视图集成,是通过解析资源文件来解析请求输出文件的。 <property name="basename" 
		value="views"></property>,即表示在/WEB-INF/classes路径下有一个 views.properties文件  -->
	<bean class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
		<property name="basename" value="views"/>
		<property name="order" value="0" />
	</bean>

	<!-- 定义JSP视图解析器-->
	<bean id="jspViewResolver" 
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/views/" />
		<property name="suffix" value=".jsp" />
		<property name="contentType" value="text/html;charset=UTF-8" />
	</bean>
 
 
	 <!-- velocity视图解析器 -->


	 <!-- velocity环境配置 -->
    <bean id="velocityConfig" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
        <!-- velocity配置文件路径 -->
        <property name="configLocation" value="classpath:velocity.properties"/>
        <!-- velocity模板路径 -->
        <property name="resourceLoaderPath" value="/WEB-INF/velocity/"/>
    </bean>
    
    <bean id="velocityViewResolver" class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">
        <property name="cache" value="false"/>
        <property name="prefix" value=""/>
        <property name="suffix" value=".vm"/>
        <property name="contentType" value="text/html;charset=UTF-8" />
       	 <!--  多ViewResovler配置
        <property name="order" value="1" /> -->
    </bean>

 

view.properties配置文件

#welcome为modelAndView.setViewName("welcome");中的welcome   .(class)固定写法
welcome.(class)=org.springframework.web.servlet.view.velocity.VelocityView
#welcome.url 路径 welcome.vm模板名称
welcome.url=welcome.vm

#IndexController路径
velocity_main.(class)=org.springframework.web.servlet.view.velocity.VelocityView
velocity_main.url=velocity_main.vm

  

 

无奈,看来,只有自己写个ViewResover来处理多视图了,google了一下,还真有人也是这么做的,看来不只是我一个人这么想啊,手懒了些,直接抄了http://blog.youkuaiyun.com/rommel1/article/details/7673325的代码,好了,来看看配置吧:

 

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:p="http://www.springframework.org/schema/p"
 xmlns:context="http://www.springframework.org/schema/context"
 xsi:schemaLocation="
 http://www.springframework.org/schema/beans
 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
 http://www.springframework.org/schema/context
 http://www.springframework.org/schema/context/spring-context-3.0.xsd ">
    <context:component-scan
     base-package="com.spring.action"/>
    <!--
    org.springframework.web.servlet.view.ResourceBundleViewResolver
    用于多个视图集成时,ResourceBundleViewResolver是通过解析资源文件来解析请求输出文件的。
    <property name="basename" value="views"></property>,即表示在/WEB-INF/classes路径下有一个
    views.properties文件,本例中views.properties的内容为
    welcome.(class)=org.springframework.web.servlet.view.velocity.VelocityView
    welcome.url=welcome.vm
    freemarker.(class)=org.springframework.web.servlet.view.freemarker.FreeMarkerView
    freemarker.url=freemarker.ftl
    -->
    <bean class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
        <property name="basename" value="views">
        </property>
        <!--
        <property name="order" value="0"></property>
        -->
    </bean>
    <!-- FreeMarker环境配置 -->
    <bean id="freemarkerConfig"
    
     class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
        <!-- freemarker模板位置 -->
        <property name="templateLoaderPath" value="/WEB-INF/freemarker/"/>
    </bean>
	<!-- velocity环境配置 -->
	<bean id="velocityConfig" 

	 class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
		<!-- velocity配置文件路径 -->
		<property name="configLocation" value="/WEB-INF/velocity.properties"/>
		<!-- velocity模板路径 -->
		<property name="resourceLoaderPath" value="/WEB-INF/velocity/"/>
	</bean>
    <bean id="viewResolver"
     class="com.spring.action.MultiViewResover">
        <property name="resolvers">
            <map>
                <entry key="jsp">
                    <bean
                     class="org.springframework.web.servlet.view.InternalResourceViewResolver">
                        <property name="viewClass"
                         value="org.springframework.web.servlet.view.JstlView"/>
                        <property name="prefix" value="/WEB-INF/jsp/"/>
                        <property name="suffix" value=".jsp"/>
                    </bean>
                </entry>
                <entry key="ftl">
                    <bean
                     class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
                        <property name="cache" value="true"/>
        				<property name="prefix" value="/"/>
        				<property name="suffix" value=".ftl"/>  
                    </bean>
                </entry>
                <entry key="vm">
                    <bean
                     class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">
                        <property name="cache" value="true"/>
						<property name="prefix" value="/"/>
						<property name="suffix" value=".vm"/>
                    </bean>
                </entry>
            </map>
        </property>
    </bean>
    
</beans>

 

MultiViewResover代码,这里我默认的是使用jsp视图解析,如果你没有默认的可以去掉

 

public class MultiViewResover implements ViewResolver {

	private Map<String, ViewResolver> resolvers;

	@Override
	public View resolveViewName(String viewName, Locale locale) throws Exception {
		int n = viewName.lastIndexOf("."); // 获取
											// viewName(modelAndView中的名字)看其有没有下划线
		String suffix = "";

		// 没有默认使用“jsp“方式 解析,有的话截取下划线后面的字符串 这里一般是jsp,ftl,vm与配置文件中的<entry
		// key="ftl">的key匹配
		if (n == (-1)) {
			suffix = "jsp";
		}
		else {
			suffix = viewName.substring(n + 1);
			// 取下划线前面的部分 那时真正的资源名.比如我们要使用hello.jsp 那viewName就应该是hello_jsp
			viewName = viewName.substring(0, n);
		}

		// 根据下划线后面的字符串去获取托管的视图解析类对象
		ViewResolver resolver = resolvers.get(suffix);

		if (resolver != null) {
			return resolver.resolveViewName(viewName, locale);
		}
		else {
			return null;
		}
	}

	public Map<String, ViewResolver> getResolvers() {
		return resolvers;
	}

	public void setResolvers(Map<String, ViewResolver> resolvers) {
		this.resolvers = resolvers;
	}
}

 

好了,第二步这个配置总算完成了,真累 啊,继续看下面。

 

3、编写controller代码,注意,你的view名字中,要加上".vm",".jsp",".ftl"这些后缀哦,要不默认都使用jsp的解析器了

 

@Controller
public class IndexController{

	@RequestMapping(value="/index")
	public ModelAndView handleRequest(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		ModelAndView mav = new ModelAndView("velocity_main.vm");
		
		Person p1 = new Person();
		p1.setId(1);
		p1.setName("胡楠");
		p1.setPassword("123456");
		p1.setAge(24);
		p1.setBirthday(new Date());
		
		List<Person> list = new ArrayList<Person>();
		for(int i=0;i<10;i++){
			Person p = new Person();
			p.setId(1000+i);
			p.setName("胡楠"+i);
			p.setPassword("123456"+i);
			p.setAge(24+i);
			p.setBirthday(new Date());
			list.add(p);
		}
		//集合
		mav.addObject("persons", list);
		//对象
		mav.addObject("person",p1);
		//request范围数据
		request.setAttribute("requestData", "hunan");
		//session范围数据
		request.getSession().setAttribute("sessionData", "123456");
		return mav;
	}

	
	@RequestMapping(value="/welcome")
	public ModelAndView helloVm(){
		ModelAndView modelAndView=new ModelAndView();
		modelAndView.setViewName("welcome.vm");
		modelAndView.addObject("message", "Hello,Velocity");
		return modelAndView;
	}
}

 4、编写velocity模板代码,以下是velocity_main.vm代码

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
显示对象的属性<br>
$person.id<br>
$person.name<br>
$person.password<br>
$person.age<br>
if语句<br>
#if($person.id <2)
id大于2
#else
id小于2
#end
#if($person.password=="123456")
密码等于123456
#end
<hr>
foreach语句<br>
#foreach($p in $persons)
	$p.id<br>
   $p.name<br>
   $!p.email<br>
   $dateTool.format("yyyy-MM-dd HH:mm:ss", $p.birthday)<br>
#end
<hr>
request范围数据<br>
$requestData<br>
session范围数据<br>
$sessionData<br>
</body>
</html>

 呼~~写完了终于,把tomcat发动起来,看一下效果吧。

 

 

 

<think>嗯,用户之前问过关于Python中通过序列化和反序列化实现深拷贝的问题,现在又转向了SpringMVC的工作流程。看起来用户可能在学编程,特别是后端开发相关的技术。用户可能有一定的Python基础,现在在学习Java的框架,比如SpringMVC。我需要先确认用户的需求,他们可能想了解SpringMVC的基本流程,以便更好地进行开发或者面试准备。 首先,我需要回忆一下SpringMVC的工作流程。大致步骤是:用户发送请求到前端控制器DispatcherServlet,然后DispatcherServlet查询处理器映射HandlerMapping,找到对应的Controller,Controller处理请求后返回ModelAndView,然后解析视图,渲染数据,最后返回响应。但需要详细一点,每个步骤具体发生了什么。 用户可能希望得到一个简明扼要的解释,不需要太深入,但关键点要覆盖到。可能需要比较结构化的回答,比如分步骤说明,或者用流程图的方式。但因为是文字回答,用列表的方式更合适。 还要注意用户之前的问题是关于深拷贝的,现在转到了SpringMVC,可能用户在学习不同的技术点,所以回答要清晰明了,避免使用过于专业的术语,但需要准确。可能需要举例说明每个步骤的作用,比如DispatcherServlet作为中央控制器,处理所有请求,然后HandlerMapping找到对应的Controller,这样用户更容易理解。 另外,用户可能对某些组件不太熟悉,比如HandlerAdapter,需要解释它的作用,为什么需要它。比如,Controller可能有不同的实现方式,HandlerAdapter负责适配不同的处理器,执行实际的方法,并返回ModelAndView。 视图解析器ViewResolver的作用是将逻辑视图名转换为实际的视图,比如JSP或者Thymeleaf模板。渲染过程是将模型数据填充到视图中,生成最终的响应内容。 在总结的时候,需要强调SpringMVC的核心是DispatcherServlet,以及各组件如何协同工作,处理请求的流程。同时,可能提到一些相关的注解,比如@Controller,@RequestMapping,帮助用户联系实际开发中的使用。 还需要注意用户可能的后续问题,比如某个步骤的细节,或者如何配置,但当前问题只需要简单介绍,不需要深入配置细节。确保回答结构清晰,步骤明确,便于用户理解和记忆。</think>好的!SpringMVC 是一个基于 Java 的 Web 框架,其核心思想是 **“请求驱动”**,通过分层设计将 HTTP 请求的处理流程模块化。以下是其简化的工作流程: --- ### 📌 核心流程图 ``` 用户请求 → DispatcherServlet → HandlerMapping → Controller → ModelAndView → ViewResolver → 视图渲染 → 响应 ``` --- ### 📝 详细步骤说明 1. **用户发起请求** - 浏览器发送 HTTP 请求到 Web 服务器(如 Tomcat)。 2. **DispatcherServlet 拦截请求** - **前端控制器**(DispatcherServlet)是 SpringMVC 的核心入口,负责统一接收所有请求。 - 它本质上是一个 Servlet,在 `web.xml` 中配置为拦截所有请求(如 `/*` 或自定义路径)。 3. **HandlerMapping 查找处理器** - DispatcherServlet 调用 **HandlerMapping**(处理器映射器),根据请求的 URL、参数等,找到对应的 **Controller** 及其方法。 - 常用映射方式:`@RequestMapping` 注解、`RouterFunction`(WebFlux)等。 4. **HandlerAdapter 执行处理器** - **HandlerAdapter**(处理器适配器)负责调用具体的 Controller 方法,处理请求逻辑。 - 这一步会解析参数(如 `@RequestParam`、`@RequestBody`),执行方法并返回结果。 5. **Controller 处理业务** - Controller 中的方法执行业务逻辑(如调用 Service 层),最终返回一个 **ModelAndView** 对象(包含模型数据和视图名)或直接返回数据(如 REST API 的 `@ResponseBody`)。 6. **ViewResolver 解析视图** - 如果返回的是视图名称(如 JSP、Thymeleaf),**ViewResolver**(视图解析器)会将逻辑视图名(如 `"userList"`)转换为具体的视图对象(如 `/WEB-INF/views/userList.jsp`)。 7. **视图渲染并响应** - 视图技术(如 JSP、FreeMarker)将 Model 中的数据与模板结合,生成最终的 HTML 内容。 - DispatcherServlet 将渲染结果通过 HTTP 响应返回给用户。 --- ### 🌰 示例场景(用户访问 `/user?id=1`) 1. DispatcherServlet 收到请求。 2. HandlerMapping 根据 URL `/user` 找到 `UserController` 的 `getUserById` 方法。 3. HandlerAdapter 解析参数 `id=1`,调用该方法。 4. Controller 查询数据库,返回 `ModelAndView("userDetail", userData)`。 5. ViewResolver 将 `"userDetail"` 映射到 `/WEB-INF/views/userDetail.jsp`。 6. JSP 页面渲染用户数据,生成 HTML 返回浏览器。 --- ### 🔑 核心组件总结 | 组件 | 作用 | |------|------| | **DispatcherServlet** | 中央调度器,统一处理请求和响应 | | **HandlerMapping** | 映射请求到对应的处理器(Controller 方法) | | **HandlerAdapter** | 执行处理器方法,适配不同处理逻辑 | | **ViewResolver** | 将逻辑视图名转换为实际视图 | | **Controller** | 处理具体业务,返回数据或视图 | --- ### 💡 特点与优势 - **松耦合**:各组件职责分离,易于扩展(如替换视图技术)。 - **注解驱动**:通过 `@Controller`、`@RequestMapping` 等简化配置。 - **灵活适配**:支持 REST API(`@RestController`)和传统页面渲染。 如果需要更深入的细节(如拦截器、异常处理),可以进一步探讨! 🚀
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值