SpringMVC是一个基于DispatcherServlet的MVC框架,每一个请求最先访问的都是DispatcherServlet,DispatcherServlet负责转发每一个Request请求给相应的Handler,Handler处理以后再返回相应的视图(View)和模型(Model),返回的视图和模型都可以不指定,即可以只返回Model或只返回View或都不返回。
DispatcherServlet是继承自HttpServlet的,既然SpringMVC是基于DispatcherServlet的,那么我们先来配置一下DispatcherServlet,好让它能够管理我们希望它管理的内容。HttpServlet是在web.xml文件中声明的。
[html] view plain copy print ?
- <servlet>
- <servlet-name>securityWeb</servlet-name>
- <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
- <init-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>classpath*:conf/applicationContext-mvc.xml</param-value>
- </init-param>
- <load-on-startup>2</load-on-startup>
- </servlet>
- <servlet-mapping>
- <servlet-name>securityWeb</servlet-name>
- <url-pattern>*.do</url-pattern>
- </servlet-mapping>
<servlet>
<servlet-name>securityWeb</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:conf/applicationContext-mvc.xml</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>securityWeb</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
上面声明了一个名为securityWeb的DispatcherServlet,该Servlet将处理所有以“.do”结尾的请求。在初始化DispatcherServlet的时候,SpringMVC默认会到/WEB-INF目录下寻找一个叫[servlet-name]-servlet.xml的配置文件,来初始化里面的bean对象,该文件中对应的bean对象会覆盖spring配置文件中声明的同名的bean对象。如上面的就会在/WEB-INF目录下寻找一个叫securityWeb-servlet.xml的文件;当然也可以在Servlet中声明配置文件的位置。如上面代码已经写出路径。
DispatcherServlet会利用一些特殊的bean来处理Request请求和生成相应的视图返回。
关于视图的返回,Controller只负责传回来一个值,然后到底返回的是什么视图,是由视图解析器控制的,在jsp中常用的视图解析器是InternalResourceViewResovler,它会要求一个前缀和一个后缀
[html] view plain copy print ?
- <?xml version="1.0" encoding="UTF-8"?>
- <!--
- - DispatcherServlet application context for DeclareOnline's web tier.
- spring mvc 的 DispatcherServlet 对应的配置文件
- -->
- <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-2.5.xsd
- http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd" default-autowire="byName">
- <!--
- - The controllers are autodetected POJOs labeled with the @Controller annotation.
- Spring mvc将在该路径下寻找Controller(有Controller注释的类)
- -->
- <context:component-scan base-package="com.zhjy.dps.*"/>
- <!-- 使用依赖控制器类名字的惯例,将URI映射到控制器 -->
- <bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping" />
- <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
- <!-- 启动Spring MVC的注解功能,完成请求和注解POJO的映射 -->
- <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
- <!-- 定义Spring MVC 的模板文件 -->
- <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
- <!-- 支持JSTL -->
- <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
- <!-- 模板的路径 -->
- <property name="prefix" value="/" />
- <!-- 模板文件后缀 -->
- <property name="suffix" value=".jsp" />
- </bean>
- </beans>
<?xml version="1.0" encoding="UTF-8"?>
<!--
- DispatcherServlet application context for DeclareOnline's web tier.
spring mvc 的 DispatcherServlet 对应的配置文件
-->
<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-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd" default-autowire="byName">
<!--
- The controllers are autodetected POJOs labeled with the @Controller annotation.
Spring mvc将在该路径下寻找Controller(有Controller注释的类)
-->
<context:component-scan base-package="com.zhjy.dps.*"/>
<!-- 使用依赖控制器类名字的惯例,将URI映射到控制器 -->
<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping" />
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
<!-- 启动Spring MVC的注解功能,完成请求和注解POJO的映射 -->
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
<!-- 定义Spring MVC 的模板文件 -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 支持JSTL -->
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<!-- 模板的路径 -->
<property name="prefix" value="/" />
<!-- 模板文件后缀 -->
<property name="suffix" value=".jsp" />
</bean>
</beans>
在上述视图解析器中,如果Controller返回的是securityWeb/index,那么通过视图解析器解析之后的视图就是/WEB-INF/securityWeb/index.jsp。
要使用注解的SpringMVC需要在SpringMVC的配置文件中进行声明,具体方式为先引入mvc命名空间,然后利用<mvc:annotation-driven />进行声明。
主要是说说Controller.
一个类使用了@Controller进行标记的都是Controller
[java] view plain copy print ?
- @Controller
- public class PlanController {
- }
@Controller
public class PlanController {
}
有了Controller之后,那么到底是怎样请求一个Controller具体的方法的呢,那是通过@RequestMapping来标记的,@RequestMapping可以标记在类上面,也可以标记在方法上,当方法上和类上都标记了@RequestMapping的时候,那么对应的方法对应的Url就是类上的加方法上的,如下面的index方法,其对应的URL应为类上的/blog加上index方法上的/index,所以应为/blog/index,所以当请求/blog/index.do的时候就会访问BlogController的index方法。
[java] view plain copy print ?
- @Controller
- public class PlanController {
- @RequestMapping("service/index")
- public String index(Map<String, Object> map) {
- return "secruityWeb/index";
- }
- }
@Controller
public class PlanController {
@RequestMapping("service/index")
public String index(Map<String, Object> map) {
return "secruityWeb/index";
}
}
在RequestMapping中还可以指定一个属性method,其主要对应的值有RequestMethod.GET和RequestMethod.POST,利用该属性可以严格的控制某一方法只能被标记的请求路径对应的请求方法才能访问,如指定method的值为GET,则表示只有通过GET方式才能访问该方法,默认是都可以访问。
在SpringMVC中常用的注解还有@PathVariable,@RequestParam,@PathVariable标记在方法的参数上,利用它标记的参数可以利用请求路径传值,看下面一个例子
[java] view plain copy print ?
- @RequestMapping(value="/comment/{blogId}", method=RequestMethod.POST)
- public void comment(Comment comment,@PathVariable int blogId, HttpSession session, HttpServletResponse response) throws IOException {
- }
@RequestMapping(value="/comment/{blogId}", method=RequestMethod.POST)
public void comment(Comment comment,@PathVariable int blogId, HttpSession session, HttpServletResponse response) throws IOException {
}
在该例子中,blogId是被@PathVariable标记为请求路径变量的,如果请求的是/blog/comment/1.do的时候就表示blogId的值为1. 同样@RequestParam也是用来给参数传值的,但是它是从头request的参数里面取值,相当于request.getParameter("参数名")方法。
在Controller的方法中,如果需要WEB元素HttpServletRequest,HttpServletResponse和HttpSession,只需要在给方法一个对应的参数,那么在访问的时候SpringMVC就会自动给其传值,但是需要注意的是在传入Session的时候如果是第一次访问系统的时候就调用session会报错,因为这个时候session还没有生成。
接下来讨论一下方法的返回值,主要有一下情况:
- 返回一个ModelAndView,其中Model是一个Map,里面存放的是一对对的键值对,其可以直接在页面上使用,View是一个字符串,表示的是某一个View的名称
- 返回一个View,也就是一个字符串,这个时候如果需要给页面传值,可以给方法一个Map参数,该Map就相当于一个Model,往该Model里面存入键值对就可以在页面上进行访问了
- 返回一个Model也就是一个Map,这个时候将解析默认的生成的view name。
- 什么也不返回,这个时候可以利用HttpServletResponse进行返回,也可以直接使用printStream进行返回
下面是一个实例:
[java] view plain copy print ?
- @RequestMapping("/work/plan/findProjectByState")
- public String findProjectByState(YearPlanMgrQueryForm form,String planState, HttpServletRequest request, HttpServletResponse response) {
- HttpSession session = request.getSession();
- String industryId = (String) session.getAttribute("industryID");
- String planName = request.getParameter("planName");
- String personSituation = request.getParameter("planState");
- try {
- if(planState != null && !"".equals(planState)){
- form.setPlanState(planState);
- }
- int pageNo = 1;
- int fetch = 8;
- String pageNumber = request.getParameter("pageNumber");
- String pageSize = request.getParameter("pageSize");
- // 得到页码
- if (pageNumber == null) {
- pageNo = PageUtil.getPageNum(request, PageUtil.DEFAULT_PAGENUM);
- } else {
- pageNo = Integer.parseInt(pageNumber);
- }
- // 得到每页记录数
- if (pageSize == null) {
- fetch = PageUtil.getPageSize(request, 8);
- } else {
- fetch = Integer.parseInt(pageSize);
- }
- // 获取列表
- System.out.println(personSituation);
- Page<Map<String, Object>> page = projectPlanService.findProjectByState(planName, industryId, personSituation, pageNo, fetch);
- request.setAttribute("personSituation", personSituation);
- request.setAttribute("page", page);
- request.setAttribute("pageSize", fetch);
- } catch (Exception e) {
- throw new PlatformException(e);
- }
- return "/module/industry/planlist";
- }