SpringMVC学习日志

SpringMVC简介

Spring MVC是当前最优秀的MVC框架,自从Spring 2.5版本发布后,由于支持注解配置,易用性有了大幅度的提高。Spring 3.0更加完善,实现了对Struts 2的超越。现在越来越多的开发团队选择了Spring MVC。 Spring3 MVC的优点:

1、Spring3 MVC使用简单,学习成本低。学习难度小于Struts2,Struts2用不上的多余功能太多。呵呵,当然这不是决定因素。

2、Spring3 MVC很容易就可以写出性能优秀的程序,Struts2要处处小心才可以写出性能优秀的程序(指MVC部分)

3、Spring3 MVC的灵活是你无法想像的,Spring框架的扩展性有口皆碑,Spring3 MVC当然也不会落后,不会因使用了MVC框架而感到有任何的限制。

SpringMVC的maven配置:

 1<dependencyManagement>
 2	<dependencies>
 3	  <dependency>
 4	    <groupId>org.springframework</groupId>
 5	    <artifactId>spring-framework-bom</artifactId>
 6	    <version>4.3.9.RELEASE</version>
 7	    <type>pom</type>
 8	    <scope>import</scope>
 9	  </dependency>
10	</dependencies>
11</dependencyManagement>
12
13</dependencies>
14	<dependency>
15	  <groupId>org.springframework</groupId>
16	  <artifactId>spring-webmvc</artifactId>
17	</dependency>
18</dependencies>

配置web.xml

 1<!-- 设置根上下文配置文件,与Spring Core容器有关 -->
 2<context-param>
 3    <param-name>contextConfigLocation</param-name>
 4    <param-value>classpath:application-context.xml</param-value>
 5</context-param>
 6
 7<!-- 注册ContextLoaderListener-->
 8<listener>
 9    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
10</listener>
11
12<!-- 前端控制器:导演,注册DispatcherServlet-->
13<servlet>
14    <servlet-name>servlet</servlet-name>
15    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
16    <init-param>
17        <!-- 初始化参数 -->
18        <param-name>contextConfigLocation</param-name>
19        <param-value>classpath:application-servlet.xml</param-value>
20    </init-param>
21</servlet>
22
23<!-- 将注册的DispatcherServlet映射到'/' -->
24<servlet-mapping>
25    <servlet-name>servlet</servlet-name>
26    <url-pattern>/</url-pattern>
27</servlet-mapping>

配置视图解析器:

 1<!--配置JSP视图解析器-->
 2<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
 3    <property name="prefix" value="/WEB-INF/views/"/>
 4    <property name="suffix" value=".jsp"/>
 5</bean>
 6
 7
 8<!-- 扫描包 control -->
 9<context:component-scan base-package="com.xpu.springmvc.control"/>
10<!-- 启用注解SpringMVC -->
11<mvc:annotation-driven/>

一个示例Controller:

 1@Controller
 2@RequestMapping
 3public class IndexController {
 4    @RequestMapping(value = {"","/index"}, method = {RequestMethod.GET})
 5    public ModelAndView hello(){
 6        ModelAndView modelAndView = new ModelAndView();
 7        modelAndView.setViewName("welcome");//WEB-INFO/views/welcome.jsp
 8        return modelAndView;
 9    }
10}

SpringMVC涉及的元素

mark 模型-视图-控制器(MVC模式)是一种非常经典的软件架构模式,在UI框架和UI设计思路中扮演着非常重要的角色。从设计模式的角度来看,MVC模式是一种复合模式,它将多个设计模式在一种解决方案中结合起来,用来解决许多设计问题。MVC模式把用户界面交互分拆到不同的三种角色中,使应用程序被分成三个核心部件: Model(模型)、View(视图)、Control(控制器) ,它们各自处理自己的任务:

(1)模型:模型持有所有的数据、状态和程序逻辑;模型独立于视图和控制器。 (2)视图:用来呈现模型。视图通常直接从模型中取得它需要显示的状态与数据。对于相同的信息可以有多个不同的显示形式或视图。 (3)控制器:位于视图和模型中间,负责接受用户的输入,将输入进行解析并反馈给模型,通常一个视图具有一个控制器。 mark MVC模式将它们分离以提高系统的灵活性和复用性,不使用MVC模式,用户界面设计往往将这些对象混在一起。 MVC模式实现了模型和视图的分离,这带来了几个好处: (1)一个模型提供不同的多个视图表现形式,也能够为一个模型创建新的视图而无须重写模型。一旦模型的数据发生变化,模型将通知有关的视图,每个视图相应地刷新自己。 (2)模型可复用。因为模型是独立于视图的,所以可以把一个模型独立地移植到新的平台工作。 (3)提高开发效率。在开发界面显示部分时,你仅仅需要考虑的是如何布局一个好的用户界面;开发模型时,你仅仅要考虑的是业务逻辑和数据维护。这样能使开发者专注于某一方面的开发,提高开发效率。

Servlet请求响应

Servlet对应的就是MVC框架模式中的控制器。Servlet负责在处理用户请求和响应,其中数据的处理,页面响应都是在Servlet里面完成的。如下图是Servlet请求响应示意图: mark

SpringMVC请求响应

mark 上面这张图是SpringMVC请求处理的比较高层次的流程图(隐含了更多细节),从图上看它与Servlet处理请求的最大不同在于,它将视图渲染,请求处理,模型创建分离了。即遵循了MVC框架模式的基本思想。 mark 上图是将高层次的流程图细化到SpringMVC框架的具体实现上了,通过上图我们可以看出,SpringMVC的请求响应经过的7个阶段。其中2-6阶段分别对应着SpringMVC框架中的几个概念,分别是:前端控制器,处理映射器,控制器(处理器),视图解析器,视图。图中绿色部分是用户需要实现的内容

核心类的请求流程

mark 第一步:(发起)发起请求到前端控制器(DispatcherServlet) 第二步:(查找)前端控制器请求HandlerMapping查找 Handler(可以根据xml配置、注解进行查找) 第三步:(返回)处理器映射器HandlerMapping向前端控制器返回Handler,HandlerMapping会把请求映射为HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象,多个HandlerInterceptor拦截器对象),通过这种策略模式,很容易添加新的映射策略 第四步:(调用)前端控制器调用处理器适配器去执行Handler 第五步:(执行)处理器适配器HandlerAdapter将会根据适配的结果去执行Handler 第六步:(返回)Handler执行完成给适配器返回ModelAndView 第七步:(接收)处理器适配器向前端控制器返回ModelAndView (ModelAndView是SpringMVC框架的一个底层对象,包括 Model和view) 第八步:(解析)前端控制器请求视图解析器去进行视图解析 (根据逻辑视图名解析成真正的视图(jsp)),通过这种策略很容易更换其他视图技术,只需要更改视图解析器即可 第九步:(返回)视图解析器向前端控制器返回View 第十步:(渲染)前端控制器进行视图渲染 (视图渲染将模型数据(在ModelAndView对象中)填充到request域) 第十一步:(响应)前端控制器向用户响应结果

SpringMVC核心组件(后续补充的)

DispatcherServlet 控制器入口 负责分发请求 (前置控制器) HandlerMapping 负责根据请求 找到对应的控制器(将请求映射到Handler) Handler 后端控制器 HandlerInterceptor 处理器拦截器 HandlerExecution 处理器执行链 HandlerAdapter 处理器适配器 ViewResolver 视图处理器 通过处理找到对应的页面 ModelAndView 封装数据信息和视图信息的 Controller 真正处理请求的控制器

mark

SpringMVC的xml配置方式

springmvc.xml配置如下

 1<!-- 配置HandlerMapping-->
 2    <bean id="handlerMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
 3
 4        <!-- 配置Mapping -->
 5        <property name="mappings">
 6            <props>
 7                <prop key="/test">testHandler</prop>
 8            </props>
 9        </property>
10    </bean>
11
12    <!-- 配置Handler -->
13    <bean id="testHandler" class="com.xpu.maven.MyHandler">
14    </bean>
15
16    <!-- 配置视图解析器 -->
17    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
18        <!-- 前缀-->
19        <property name="prefix" value="/"></property>
20        <!-- 配置后缀-->
21        <property name="suffix" value=".jsp"></property>
22    </bean>

web.xml配置

 1<web-app>
 2  <display-name>Archetype Created Web Application</display-name>
 3
 4  <filter>
 5    <filter-name>encodingFilter</filter-name>
 6    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
 7    <init-param>
 8      <!--要使用的字符集,一般我们使用UTF-8(保险起见UTF-8最好)-->
 9      <param-name>encoding</param-name>
10      <param-value>UTF-8</param-value>
11    </init-param>
12    <init-param>
13      <!--是否强制设置request的编码为encoding,默认false,不建议更改-->
14      <param-name>forceRequestEncoding</param-name>
15      <param-value>false</param-value>
16    </init-param>
17    <init-param>
18      <!--是否强制设置response的编码为encoding,建议设置为true,下面有关于这个参数的解释-->
19      <param-name>forceResponseEncoding</param-name>
20      <param-value>true</param-value>
21    </init-param>
22  </filter>
23  <filter-mapping>
24    <filter-name>encodingFilter</filter-name>
25    <url-pattern>/*</url-pattern>
26  </filter-mapping>
27
28  <servlet>
29    <servlet-name>springmvc</servlet-name>
30    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
31    <!-- 配置文件的路径 -->
32    <init-param>
33      <param-name>contextConfigLocation</param-name>
34      <param-value>classpath:springmvc.xml</param-value>
35    </init-param>
36  </servlet>
37  <!-- 这个配置servlet-mapping主要是为了防止SpringMVC阻止了css文件请求 -->
38  <servlet-mapping>
39    <servlet-name>default</servlet-name>
40    <url-pattern>*.css</url-pattern>
41  </servlet-mapping>
42
43  <servlet-mapping>
44    <servlet-name>springmvc</servlet-name>
45    <url-pattern>/</url-pattern>
46  </servlet-mapping>
47</web-app>

MyHandler.java

 1public class MyHandler implements Controller {
 2    @Override
 3    public ModelAndView handleRequest(HttpServletRequest httpServletRequest,
 4        HttpServletResponse httpServletResponse) throws Exception {
 5        //装载模型数据
 6        ModelAndView modelAndView = new ModelAndView();
 7        modelAndView.addObject("name", "Tim");
 8        modelAndView.setViewName("show");
 9        return modelAndView;
10    }

pom.xml

 1<properties>
 2    <encoding>UTF-8</encoding>
 3    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 4    <maven.compiler.source>1.8</maven.compiler.source>
 5    <maven.compiler.target>1.8</maven.compiler.target>
 6  </properties>
 7
 8  <dependencies>
 9    <dependency>
10      <groupId>junit</groupId>
11      <artifactId>junit</artifactId>
12      <version>4.11</version>
13      <scope>test</scope>
14    </dependency>
15
16
17    <dependency>
18      <groupId>javax.servlet</groupId>
19      <artifactId>servlet-api</artifactId>
20      <version>2.5</version>
21    </dependency>
22    <!-- JSTL -->
23    <dependency>
24      <groupId>javax.servlet</groupId>
25      <artifactId>jstl</artifactId>
26      <version>1.2</version>
27    </dependency>
28    <!-- JSTL实现包 -->
29    <dependency>
30      <groupId>org.apache.taglibs</groupId>
31      <artifactId>taglibs-standard-impl</artifactId>
32      <version>1.2.5</version>
33    </dependency>
34    <dependency>
35
36      <groupId>org.springframework</groupId>
37      <artifactId>spring-webmvc</artifactId>
38      <version>5.1.5.RELEASE</version>
39
40    </dependency>
41
42     <!-- 接收JSON数据shi时才使用 -->
43     <dependency>
44          <groupId>com.fasterxml.jackson.core</groupId>
45          <artifactId>jackson-databind</artifactId>
46          <version>2.9.8</version>
47     </dependency>
48  </dependencies>

SpringMVC的数据绑定

设计一个课程类Course和一些其他的JavaBean:

 1//课程类
 2public class Course {
 3    private int id;
 4    private String name;
 5    private double price;
 6}
 7//讲师类
 8public class Author {
 9    private int id;
10    private String name;
11}
12//课程类的集合类
13public class CourseList {
14    List<Course> list;
15}
16//课程类的集合类
17public class CourseMap {
18    private Map<String, Course> courseMap;
19}
20
21//课程类的集合类
22public class CourseSet {
23    private Set<Course> courseSet = new HashSet<>();
24
25    public Set<Course> getCourseSet() {
26        return courseSet;
27    }
28
29    public void setCourseSet(Set<Course> courseSet) {
30        this.courseSet = courseSet;
31    }
32    
33    //主要是为了完成绑定
34    public CourseSet(){
35        courseSet.add(new Course());
36        courseSet.add(new Course());
37    }
38}
 1/**
 2     * 基本类型
 3     */
 4    @RequestMapping(value = "/baseType")
 5    @ResponseBody
 6    public String baseType(@RequestParam(value = "id", required = false) int id){
 7        return "baseType id:"+id;
 8    }
 9
10    /**
11     * 包装类类型
12     */
13    @RequestMapping(value = "/packageType")
14    @ResponseBody
15    public String packageType(@RequestParam(value = "id") Integer id){
16        return "packageType id:"+id;
17    }
18    
19    /**
20     * 数组类型
21     */
22    @RequestMapping(value = "/arrayType")
23    @ResponseBody
24    public String arrayType(String[] name){
25        StringBuffer sb = new StringBuffer();
26        for(String item: name){
27            sb.append(item);
28        }
29        return sb.toString();
30    }
31
32    /**
33     * 对象类型
34     */
35    @RequestMapping("/pojoType")
36    public ModelAndView pojoType(Course course){
37        ModelAndView view = new ModelAndView();
38        courseDao.add(course);
39        view.setViewName("index");
40        view.addObject("courses", courseDao.getAll());
41
42        return view;
43    }
44
45    /**
46     * 对象list集合 
47     */
48    @RequestMapping("/listType")
49    public ModelAndView listType(CourseList courseList){
50        for(Course course : courseList.getList()){
51            courseDao.add(course);
52        }
53        ModelAndView view = new ModelAndView();
54        view.setViewName("index");
55        view.addObject("courses", courseDao.getAll());
56        return view;
57    }
58
59    /**
60     * 对象map集合
61     */
62    @RequestMapping("/mapType")
63    public ModelAndView mapType(CourseMap courseMap){
64        //遍历的是Key
65        for(String key: courseMap.getCourseMap().keySet()){
66            Course course = courseMap.getCourseMap().get(key);
67            courseDao.add(course);
68        }
69        ModelAndView view = new ModelAndView();
70        view.setViewName("index");
71        view.addObject("courses", courseDao.getAll());
72        return view;
73    }
74
75    /**
76     * 对象set集合
77     */
78    @RequestMapping("/setType")
79    public ModelAndView setType(CourseSet courseSet){
80        //遍历的是Key
81        for(Course course: courseSet.getCourseSet()){
82            courseDao.add(course);
83        }
84        ModelAndView view = new ModelAndView();
85        view.setViewName("index");
86        view.addObject("courses", courseDao.getAll());
87        return view;
88    }
89
90    /**
91     * JSON数据类型
92     */
93    @RequestMapping(value = "jsonType")
94    @ResponseBody
95    public Course jsonType(@RequestBody Course course){
96        course.setPrice(course.getPrice()+100);
97        return course;
98    }

想要支持JSON数据格式: springmvc.xml配置:

1 <mvc:annotation-driven>
2        <mvc:message-converters>
3            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
4            </bean>
5        </mvc:message-converters>
6    </mvc:annotation-driven>

pom.xml

1<!-- 接收JSON数据时才使用 -->
2<dependency>
3     <groupId>com.fasterxml.jackson.core</groupId>
4     <artifactId>jackson-databind</artifactId>
5     <version>2.9.8</version>
6</dependency>

需要注意的地方就是在接收为Set对象集合的时候需要先: mark 在接收JSON数据的时候别忘了导入jar包,并且在springmvc.xml文件中配置! 级联属性的设定写法: mark 还有在JSP中配置需要的配置项,方便EL表达式的使用!

1<%@ page contentType="text/html;charset=UTF-8" language="java" %>
2<%@ page isELIgnored="false" %>
3<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>