Make A Big Image
要学习使用 spring mvc 有几个简单的要领, spring mvc 的架构很简单地想是透过一个共通的入口 DispatcherServlet 来接受所有的 request ,接着依 request 要求的页面透过 handler 转送给 Controller 处理;待 Controller 处理完毕后,再将结果丢让 View 呈页出来。大致上的示意图如下 (ps. 俺不会 uml 只是常看大家这样用 , 有错的话和我说一声啊。 ):
<shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"><img style="WIDTH: 583px; HEIGHT: 390px" height="400" alt="" width="732" src="https://p-blog.csdn.net/images/p_blog_csdn_net/xtpdcsse/001.JPG"><stroke joinstyle="miter"></stroke><formulas><f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f></formulas><path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"></path><lock v:ext="edit" aspectratio="t"></lock></shapetype><shape id="_x0000_i1025" style="WIDTH: 468pt; HEIGHT: 247.5pt" type="#_x0000_t75" alt=""><imagedata src="file:///C:/DOCUME~1/xt/LOCALS~1/Temp/msohtml1/01/clip_image001.png" o:href="http://static.flickr.com/52/138199405_8b54d56b71_o.png"></imagedata></shape>
身为 library user 的我们,只需要在每一个流程中贡献一点心力。就能让 spring mvc 跑了起来
DispatcherServlet
DispathcerServlet 的角色就好像是一个任意门,他位于 spring mvc 的 " 入口 " 想到那跟他说就对了。但是要使用任意门,您必需先安上他。要怎么按上呢 ? DispatcherServlet 本身其实是一个 Servlet ,所以我们要做的事就是在 web.xml 中布署他。就如同一般 Servlet 布署的方式一样,描述 servlet 的名字和类别,再给他一个 mapping 描述适用的网页。
要学习使用 spring mvc 有几个简单的要领, spring mvc 的架构很简单地想是透过一个共通的入口 DispatcherServlet 来接受所有的 request ,接着依 request 要求的页面透过 handler 转送给 Controller 处理;待 Controller 处理完毕后,再将结果丢让 View 呈页出来。大致上的示意图如下 (ps. 俺不会 uml 只是常看大家这样用 , 有错的话和我说一声啊。 ):
<shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"><img style="WIDTH: 583px; HEIGHT: 390px" height="400" alt="" width="732" src="https://p-blog.csdn.net/images/p_blog_csdn_net/xtpdcsse/001.JPG"><stroke joinstyle="miter"></stroke><formulas><f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f></formulas><path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"></path><lock v:ext="edit" aspectratio="t"></lock></shapetype><shape id="_x0000_i1025" style="WIDTH: 468pt; HEIGHT: 247.5pt" type="#_x0000_t75" alt=""><imagedata src="file:///C:/DOCUME~1/xt/LOCALS~1/Temp/msohtml1/01/clip_image001.png" o:href="http://static.flickr.com/52/138199405_8b54d56b71_o.png"></imagedata></shape>
身为 library user 的我们,只需要在每一个流程中贡献一点心力。就能让 spring mvc 跑了起来
DispatcherServlet
DispathcerServlet 的角色就好像是一个任意门,他位于 spring mvc 的 " 入口 " 想到那跟他说就对了。但是要使用任意门,您必需先安上他。要怎么按上呢 ? DispatcherServlet 本身其实是一个 Servlet ,所以我们要做的事就是在 web.xml 中布署他。就如同一般 Servlet 布署的方式一样,描述 servlet 的名字和类别,再给他一个 mapping 描述适用的网页。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<?xml version=
"1.0"
encoding=
"UTF-8"
?>
<!DOCTYPE web-app PUBLIC
'-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN'
'http://java.sun.com/dtd/web-app_2_3.dtd'
>
<web-app>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>
index.jsp
</welcome-file>
</welcome-file-list>
</web-app>
|
在这个例子里,我们给 DispatcherServlet 的小名为 dispatcher ,并且让 container 知道所有 .htm 结尾的 request 都丢给 dispatcher 。
handler
安上了我们的 " 任意门 " 之后,还有一件重要的事情 : 那就是要设定一下任意门可以移动的范围。默契 ( 预设 ) 上, DispatcherServlet 的 handler 会设定在 dispatcher-servlet.xml 文件中 ( 您猜到规规则了吗 没错就是 DispatcherServlet 的小名再加上 -servlet.xml) 。所以,我们为了要让任意门知道我们欲往何方需要再努力一点点。在 spring mvc 中,常用的 handler 为 org.springframework.web.servlet.handler.SimpleUrlHandlerMapping ,他的功能很简单地维护一个 map 。 Key 是 request 的网页, Value 则是处理这个网页的 controller
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<?xml version=
"1.0"
encoding=
"UTF-8"
?>
<!DOCTYPE beans PUBLIC
"-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd"
>
<!--
- Application context definition
for
"dispatcher"
DispatcherServlet.
-->
<beans>
<bean id=
"urlMapping"
class=
"org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"
>
<property name=
"mappings"
>
<props>
<prop key=
"/helloSpringMVC.htm"
></prop>
</props>
</property>
</bean>
</beans>
|
惯例上,我们把 handler 的 bean 称为 "urlMapping" 。而 SimpleUrlHandlerMapping 提供 2 个 setter ,一个是指定单一 map 的;一个是指定很多 map rule 的。现在我们使用的是后者 ( 这些 xml 的设定,请参考 IoC 基础文件 ) 。到目前为止,我们只填上了 request page
Controller
填完了 request page 却没有填 Controller ,这样任意门的设定只做了一半耶。当你在门前大喊我要去 "/helloSpringMVC.htm" ,门大概会回你说 : "Controller 都不 Controller 了,要怎么任意们呢 >"<" 。为了让咱们的任意门能继续摇摆,我们是该写给 Controller 给他了。这里就有二件事要做了,一件是填好 handler 内的 mapping rule ,一件是生出一个 Controller 给他,总不能填了却又晃点它是呗 :p
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<?xml version=
"1.0"
encoding=
"UTF-8"
?>
<!DOCTYPE beans PUBLIC
"-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd"
>
<!--
- Application context definition
for
"dispatcher"
DispatcherServlet.
-->
<beans>
<bean id=
"helloController"
class=
"HelloController"
/>
<bean id=
"urlMapping"
class=
"org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"
>
<property name=
"mappings"
>
<props>
<prop key=
"/hello.htm"
>helloController</prop>
</props>
</property>
</bean>
</beans>
|
我们填上了一个菜市场名的 Controller: helloController 。虽然俗了一点,不过倒是挺好记的。眼尖的观众应该发现除了 map 之外,还多了一个 bean 。那就是我们的 Controller 在这里注入了 ( 野猪力量 ! 注入 ~~~~ * 冷 *) 如一般的 IoC 写法一下,平凡到您不会说他特别。但特别之处在于, 有什么资格能称他是一个 Controller?
在 SpringMVC 中,有几个常用的 Controllerhttp://www.springframework.org/docs/reference/mvc.html#mvc-controller
必要时,我们可以继承他们,或是简单的实作 Controller 接口。
1 2 3 4 5 6 7 8 9 10 11 12 |
import
javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse;
import
org.springframework.web.servlet.ModelAndView;
import
org.springframework.web.servlet.mvc.Controller;
public
class
HelloController
implements
Controller
{
public
ModelAndView handleRequest(HttpServletRequest arg0, HttpServletResponse arg1)
throws
Exception
{
return
new
ModelAndView(
""
);
}
}
|
这次,我们先示范实作 Controller 的方式吧 他只要求我们实任 handleRequest 方法。这个方法会回传 ModelAndView 类别, ModelAndView 类别,就是用在下一个阶段用来产生 View 用的。
View
经过一番实作,终于把我们的 Controller 给 " 完成了 !!!"
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
import
javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse;
import
org.springframework.web.servlet.ModelAndView;
import
org.springframework.web.servlet.mvc.Controller;
public
class
HelloController
implements
Controller
{
public
ModelAndView handleRequest(HttpServletRequest arg0, HttpServletResponse arg1)
throws
Exception
{
/*
*
相信我
,
这一段是放非常简单或非常之复杂的商业逻辑
*
经过了非常简单或非常复杂的
"
运算
"
之后
,
*
千辛万苦
,
我们终于修作正果
. (
泣
)
* */
return
new
ModelAndView(
"/WEB-INF/jsp/hello.jsp"
);
}
}
|
好的 ! 本小节的重点在, ModelAndView 。您可以先看看我们的 Controller 中,最后 return 了 "/WEB-INF/jsp/hello.jsp" 。我们把 view 放在 /WEB-INF/jsp/ 目录中,这样做是有理由的。因为使用者不应该在 view 还没完成时有机会取得 view 的 " 样版 " ,所以放在该目录是一种合理的作法 ( 这次是玩真的啦 ! 你一定要放一个真实的档案在 /WEB-INF/jsp/ 中,可不像 handler mapping 看到影子就开枪了,即使没有 helloSpringMVC.htm 也能跑。 )
所以,小弟我提供一个老梗的 hello.jsp 范本 :p
1 2 3 4 5 |
<html>
<body>
<h1>Hello! View</h1>
</body>
</html>
|
虽然,这样下去是能让我们的 view 出来见见人,我们的任意门确实能由 "/helloSpringMVC.htm" 跑到 "/WEB-INF/jsp/hello.jsp" 。但是好像麻烦了点,那天高兴起来想把 hello.jsp 换一下位子,那不就要去改 Controller 了 ! 真是囧 rz 。不过,好在 SpringMVC 牌的任意门还有密技可以 call 一下,那就是 ViewResolver ( 谜之声,这一定是谜武将,在循序图中没出现啊 !!!) 。
我们简单示范一下 ViewResolver 的用法 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<?xml version=
"1.0"
encoding=
"UTF-8"
?>
<!DOCTYPE beans PUBLIC
"-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd"
>
<!--
- Application context definition
for
"dispatcher"
DispatcherServlet.
-->
<beans>
<bean id=
"helloController"
class=
"HelloController"
/>
<bean id=
"urlMapping"
class=
"org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"
>
<property name=
"mappings"
>
<props>
<prop key=
"/hello.htm"
>helloController</prop>
</props>
</property>
</bean>
<bean id=
"viewResolver"
class=
"org.springframework.web.servlet.view.UrlBasedViewResolver"
>
<property name=
"viewClass"
><value>org.springframework.web.servlet.view.JstlView</value></property>
<property name=
"prefix"
><value>/WEB-INF/jsp/</value></property>
<property name=
"suffix"
><value>.jsp</value></property>
</bean>
</beans>
|
作法很简单,把 org.springframework.web.servlet.view.UrlBasedViewResolver bean 调出来 ! 注入 !!! 。这里要注入的主要有 3 个参数,为了解决刚刚那个名字太长的问题,我们可以设定 prefix 和 suffix ,自动解析 veiwer ,把他包装为 prefix 为 /WEB-INF/jsp/ ,与扩展名为 .jsp 的档案。另外,还要选用一个 view class ,给我们的 View 。这里用的是 JstlView ,因为俺还蛮常用 Jstl 的所以,嘿嘿嘿。
1 2 3 4 5 6 7 8 9 10 11 12 |
import
javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse;
import
org.springframework.web.servlet.ModelAndView;
import
org.springframework.web.servlet.mvc.Controller;
public
class
HelloController
implements
Controller
{
public
ModelAndView handleRequest(HttpServletRequest arg0, HttpServletResponse arg1)
throws
Exception
{
return
new
ModelAndView(
"
hello
"
);
}
}
|
[finished]
我们的任意门实作终于完成了。这也就是 spring mvc 的基本用法。当然,弟抽离了许多可以深入的点,因为我觉得入门的重点在掌握使用上的流程,先对大致上的流程有了印象,再来细部的调整自己真的需要深入学习的东西才不会让学习没方向的感觉。希望这篇文章能帮助您入门 Spring MVC 。