1.Spring MVC工作原理
①当用户在浏览器中点击一个链接或者提交一个表单时,那么就会产生一个请求(request)。当请求离开浏览器时,它会携带用户请求的信息(比如说请求的URL信息,用户名,密码什么的)。
②请求的第一站到达的是Spring的DispatcherServlet,它是一个前端控制器,工作是将用户的请求委托给其他的组件(这里是交给Spring MVC的控制器)去处理。这里DispatcherServlet要决定将请求传给哪一个控制器(Controller)去处理,那么这时就需要处理器映射(Handler Mapping)了。处理器映射会看请求的URL信息,然后决定将请求交给哪一个控制器去处理。比如说有两个控制器ControllerA和ControllerB,分别处理后缀名为.html和.jsp送来的请求,那么当请求者的后缀名为.html时,那么DispatcherServlet就将请求交给ControllerA进行处理。
③当选择了一个合适的控制器后,DispatcherServlet就会将请求交给这个控制器去处理。在这个控制器上,用户的请求将会将用户提交的一些信息交由控制器处理并等待。然而设计的比较好的控制器本身对信息做很少的处理或者根本不做处理,而是将业务逻辑交给一个或多个服务器对象(Model)去处理。
④当控制器对用户请求所携带的信息进行处理(或交给模型层处理)后,经常会产生一些其他的需要返回给浏览器进行显示的数据。这些原始数据直接显示出来显然是不友好的,那么就需要视图(View)来对这些数据进行显示了。控制器的最后一件事就是将模型数据打包,并且指定产生输出的视图的特定名称,然后它将模型、视图名称以及request请求一起发送给DispatcherServlet。所以控制器并没有与视图进行耦合,因为传递给DispatcherServlet的视图名称并不是某一个指定的特殊的文件名称(如后缀名一定是JSP或其他什么名称),它只要是一个可以产生输出和展示结果的逻辑名称就可以了。
⑤DispatcherServlet会向一个视图解析器(ViewResolver)进行请求,视图解析器可以将逻辑视图名称映射到一个特定的视图显示文件上面。
⑥现在DispatcherServlet知道哪一个视图文件可以显示结果了。该视图将会利用模板数据产生输出,这些输出通过response对象返回给客户端进行显示。
2.Spring MVC的一个简单实现(视图是通过Velocity模板进行显示)
①配置DispatcherServlet(必须在web应用的web.xml里面进行配置):
[html] view plaincopyprint?
1. <?xml version="1.0" encoding="UTF-8"?>
2. <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4. xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
5. http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
6. <servlet>
7. <servlet-name>dispatcherServlet</servlet-name>
8. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
9. <!-- 这里设置applicationContext.xml的位置,在类的根目录下,applicationContext.xml配置了Handler Mapping,Controller和ViewResolver等。-->
10. <init-param>
11. <param-name>contextConfigLocation</param-name>
12. <param-value>classpath:applicationContext.xml</param-value>
13. </init-param>
14. <load-on-startup>1</load-on-startup>
15. </servlet>
16. <!-- 这里设置为对所有请求者后缀名为.html的请求进行拦截 -->
17. <servlet-mapping>
18. <servlet-name>dispatcherServlet</servlet-name>
19. <url-pattern>*.html</url-pattern>
20. </servlet-mapping>
21. </web-app>
②配置applicationContext.xml:
[html] view plaincopyprint?
1. <?xml version="1.0" encoding="UTF-8"?>
2. <beans xmlns="http://www.springframework.org/schema/beans"
3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
4. xsi:schemaLocation="http://www.springframework.org/schema/beans
5. http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
6. http://www.springframework.org/schema/context
7. http://www.springframework.org/schema/context/spring-context-3.0.xsd">
8. <!-- 在com.spring.mvc包下寻找控制器组件 -->
9. <context:component-scan base-package="com.spring.mvc"></context:component-scan>
10. <!-- handlerMapping start -->
11. <bean id="handlerMapping"
12. class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"></bean>
13. <!-- handlerMapping end -->
14. <!-- handlerAdapter start -->
15. <bean id="handlerAdapter"
16. class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"></bean>
17. <!-- handlerAdapter end -->
18. <!-- 如果视图的后缀名是jsp,则视图默认视图解析器可以如下配置 -->
19. <!-- <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
20. <property name="viewClass" value="org.springframework.web.servlet.view.JstlView">
21. </property> <property name="suffix" value=".jsp"></property> </bean> -->
22. <!-- 配置处理velocity模板的默认视图解析器 -->
23. <bean id="velocityConfigurer"
24. class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
25. <property name="resourceLoaderPath" value="/"></property>
26. </bean>
27. <bean id="viewResolver"
28. class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">
29. <property name="suffix" value=".vm"></property>
30. </bean>
31. </beans>
③控制器HelloController.java:
[java] view plaincopyprint?
1. package com.spring.mvc;
2.
3. import javax.servlet.http.HttpServletRequest;
4.
5. import org.springframework.stereotype.Controller;
6. import org.springframework.ui.ModelMap;
7. import org.springframework.web.bind.annotation.RequestMapping;
8. import org.springframework.web.servlet.ModelAndView;
9. //使用注解@Controller声明该类是一个控制器
10. @Controller
11. public class HelloController
12. {
13. //使用注解@RequestMapping声明这个控制器处理index.html的请求
14. @RequestMapping( "index.html" )
15. public ModelAndView helloAnotherWorld( final HttpServletRequest request )
16. {
17. System.out.println( request.getRequestURI() ); // 输出/springMVC/index.html
18. final ModelMap model = new ModelMap();
19. //增加一个key-value键值对,相当于request.setAttribute("name","SpringMVC");
20. model.addAttribute( "name", "SpringMVC" );
21. //将model的数据交给文件名为helloSpringMVC,后缀名为vm(在applicationContext.xml里面设置)的文件显示
22. final ModelAndView mav = new ModelAndView( "helloSpringMVC", model );
23. return mav;
24. }
25. }
④视图helloSpring.vm:
[plain] view plaincopyprint?
1. #set($myName="Hello")
2. $myName
3. ${name}
⑤在浏览器地址栏里面输入:http://localhost:8080/springMVC/index.html,最后显示结果:Hello SpringMVC。
⑥最后看一下全部过程,在浏览器地址栏里面输入:http://localhost:8080/springMVC/index.html,拦截器发现请求的URL后缀名是html的,那么进行拦截,又通过Handle Mapping发现index.html与控制器HelloController所处理的文件一致,然后交给HelloController去处理,该控制器处理完请求后将生成的模板数据交给指定的文件helloSpring.vm去处理并显示(这里有Velocity视图解析器的作用),最后显示结果:Hello SpringMVC。而显示结果时地址栏里面的内容仍然是http://localhost:8080/springMVC/index.html,这样就隐藏了真正处理结果的页面以及使用的模板技术。
这样,一个简单的例子就实现了,这里用的是Spring3.0以及相关依赖包,这其中要注意包的导入,如果缺少了相关的包,那么会报编译或者运行错误。