spring mvc first example

[size=large]Spring mvc
第一个 Spring MVC 程式
这边的第一个 Spring Web MVC 程式将使用 Tomcat 5.5 来示范,这次为了资源管理上的方便,直 接使用 spring.jar,以及其相依的 commons-logging.jar,请将这两个 jar 放到 WEB-INF/lib 下。
在 Web MVC 架构中,使用者并不直接连接至所需的资源,而必须先连接至前端控制器(Front controller),由前端控制器判断使用者的请求要分派(Dispatch)给哪一个控制物件(Controller) 来处理请求,藉此执到控制使 用者可请求的资源之目的。
在 Spring 的 Web MVC 框架中,担任前端控制器角色的是 org.springframework.web.servlet.DispatcherServlet, DispatcherServlet 负责将客户的请 求分派给对应于请求的控制物件,所以使用 Spring Web MVC 的第一步,就是在 web.xml 中定义 DispatcherServlet:
•      web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
	→ http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd " version="2.4">
	<session-config>
		<session-timeout>
			30
		</session-timeout>
	</session-config>
	<servlet>
		<servlet-name>dispatcherServlet</servlet-name>
		<servlet-class>
			org.springframework.web.servlet.DispatcherServlet
		</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/mvc-config.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>dispatcherServlet</servlet-name>
		<url-pattern>*.do</url-pattern>
	</servlet-mapping>
</web-app>

在 web.xml 中定义了一个 DispatcherServlet 的实例 dispatcherServlet,从设定中可以看到, 所有连接至 *.do 结尾的请求都会由它来处理,"contextConfigLocation"初始参数用来设定
Bean 定义档的位置与名称,如果不设置 "contextConfigLocation"初始参数,则 DispatcherServlet 预设会使用 Servlet 的名称为前置,读取 “Servlet 名称- servlet.xml” 作为其 Bean 定义档,在上面的设定中则会读取 mvc-config.xml 中的定义。
您也可以定义多个 Bean 定义档的来源,像是:
...
<servlet>
	<servlet-name>hello</servlet-name>
	<servlet-class>
		org.springframework.web.servlet.DispatcherServlet
	</servlet-class>
	<init-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/mvc-config.xml,
		→?/WEB-INF/other-service.xml</param-value>
	</init-param>
	<load-on-startup>1</load-on-startup>
</servlet>

...
DispatcherServlet 负责转发请求至控制物件(Controller),在 Spring Web MVC 框架中,控 制物件是实作 org.springframework.web.servlet.mvc.Controller 介面的类别之实例, Controller 介面有一个必须实作的 handleRequest()方法,其定义如下所示:
package org.springframework.web.servlet.mvc;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
public interface Controller {
	ModelAndView handleRequest(HttpServletRequest request, 
						HttpServletResponse response) throws Exception;
}

当 Controller 收到 DispatcherServlet 转发而来的请求,会执行 handleRequest()方法来处理 请求,处理完毕后返回一 个 org.springframework.web.servlet.ModelAndView 的实例, ModelAndView 包括了要呈现在 View 层(例如 JSP 网页)的相关 Model 资料,以及其它有关 View 层的相关讯息。
在您第一个 Spring Web MVC 中,使用者的请求将由一个 HelloController 类别之实例来处理, 其实作如下所示:
•    
 HelloController.java 
package onlyfun.caterpillar;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.mvc.Controller;
import org.springframework.web.servlet.ModelAndView;
public class HelloController implements Controller {
	private String viewPage;
	public ModelAndView handleRequest(HttpServletRequest req, HttpServletResponse res)
				throws Exception
	{
		String user = req.getParameter("user");
		return new ModelAndView(viewPage, "user", user);
	}
	public void setViewPage(String viewPage) {
		this.viewPage = viewPage;
	}
}


在这个 Controller 中,取得了来自使用者的 user 请求参数,并设定在 ModelAndView 的实例中,在这个例子中,建构 ModelAndView 的第一个引数为要呈现的目标网页(或资源)路径,第二个 引数是设定用来取得 Model 物件的键(Key),而第三个引数为要给 View 层呈现资料用的 Model 物件。
在 Web MVC 架构下,控制物件的作用为收集使用者的请求,进行与 Web 层相关的动作,您不应当 在控制物件中执行商务逻辑,也不应当让 Servlet 相关的 API 侵入至商务层,这会让商务层的 物件与 Servlet API 产生耦合,例如让 HttpServletRequest 物件直接设定至商务层物件之中。
使用 Spring Web MVC 的好处是,Spring 的 Controller 在其 IoC 容器管理下,可以如同一般的 Bean 来加以管理,并利用其依赖注入来完成相关物件的注入, 以这边的例子来说,具体而言, 您可以在 XML 档案中设定 Controller 请求处理完毕之后,所要呈现资料的网页路径,来看一下 Bean 定义档的内容, 依 web.xml 中的设定,请在 WEB-INF 目录下建立 mvc-config.xml 档案:
•      mvc-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC
"-//SPRING/DTD BEAN/EN""http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
	<bean id="viewResolver" class="org.springframework.web.servlet.
		→ view.InternalResourceViewResolver">
		<property name="prefix">
			<value>/WEB-INF/jsp/</value>
		</property>
		<property name="suffix">
			<value>.jsp</value>
		</property>
	</bean>
	<bean name="/hello.do" class="onlyfun.caterpillar.HelloController">
		<property name="viewPage">
			<value>hello</value>
		</property>
	</bean>
</beans>

实际上 DispatcherServlet 必须根据一个 HandlerMapping 物件来决定请求由哪一个 Controller 来处理, DispatcherServlet 预设使用 org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,也就是根据 Bean 在定义时的"name"属性及使用者请求的 URL 来决定使用哪一个 Controller 实例,例如在这个例 子中,请求/hello.do 时, DispatcherServlet 根据"hello"(即不包括.do)名称决定要使用 "name"为"hello"的 Bean 实例,所以就是将请求交 由 HelloController 的实例来处理。
当 Controller 返回 ModelAndView 后,DispatcherServlet 会交由 ViewResolver 物件来作 View 层的相关解 析,因而您需要设置一个 ViewResolver 实例,在这个范例中将以 JSP 作为 View 层 技术,所以使用 org.springframework.web.servlet.view.InternalResourceViewResolver, InternalResourceViewResolver 需要设置一个"viewClass",预设是 org.springframework.web.servlet.view.InternalResourceView,这个类别支援 Servlet 技 术 的相关资源(像是 JSP、Servlet)。
InternalResourceViewResolver 的"prefix"、"suffix"属性会与 ModelAndView 返回的路径资讯 结合, 例如若路径资讯返回为"hello"字串,则与以上的例子设定结合,实际的路径就是 /WEB-INF/jsp/hello.jsp。
最后可以简单的在/WEB-INF/jsp/中写一个测试的 hello.jsp:
•      hello.jsp
<%@page contentType="text/html"%>
<%@page?pageEncoding="UTF-8"%>
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
		<title>First Spring MVC</title>
	</head>
	<body>
		<h1>Hello, ${user}!!</h1>
	</body>
</html>

在 ModelAndView 中设 置的 Model 物件,经由 InternalResourceViewResolver 及 InternalResourceView 的解析,将设定为 JSP 技术中可存取的属性(Attribute),因而可以使 用 JSP 技术中的 Expression Language 来取得资料,依以上所撰写的程式,如果您在请求 hello.do 时附带了 user 参数,则最后的 JSP 会出现您所给的 user 讯息。
[/size]

猜你喜欢

转载自fantaoyalin.iteye.com/blog/1507658