SpringMVC学习总结
来源:互联网 发布:linux上jsp页面跳转 编辑:程序博客网 时间:2024/05/19 17:51
SpringMVC学习总结
1 . MVC架构
MVC是一种架构模型,本身没有什么功能,只是让我们的项目结构更加合理,流程控制更加清晰,一般包含三个组件:
一、流程图
二、流程总结
- Model(模型):数据模型,用于提供要展示的数据。一般包含数据和行为(也就是业务),在JavaWEB中,数据和业务往往是分离开的
- View(视图):负责对模型数据进行展示,例如我们看到的网页。概念比较广泛,可以是:html、JSP、excel、Word、PDF、json、XML等
- Controller(控制器):接收用户请求,委托给模型做处理,处理完毕返回数据,再交给视图做渲染,相当于调度员工作
2 . SpringMVC架构
一、流程图
二、流程总结
DisPatcherServlet:前端控制器
HandlerMapping:处理器映射
Handler:处理器
HandlerInterceptor:处理器拦截器
HandlerAdapter:处理器适配器
ModelAndView:模型和视图
Model:模型数据
View:视图名称,不是真正的视图对象
ViewResolver:视图解析器
- 用户发送请求到DisPatcherServlet
- DispatcherServlet通过HandlerMapping 寻找用户要请求的 Handler
- HandlerMapping返回执行链,包含两部分内容:Handler和HandlerInterceptor
- DisPatcherServlet通过HandlerAdapter对Handler进行适配包装
- 调用包装后的Handler中的方法处理业务
- 处理业务完成,返回ModelAndView对象,包含两部分内容:Model和View
- DispatcherServlet获取处理得到的ModelAndView对象
- DispatcherServlet将视图名称交给ViewResolver查找视图
- ViewResolver返回真正的视图对象给DispatcherServlet
- DispatcherServlet把Model交给视图对象进行渲染
- 返回渲染后的视图
- 将最终的视图返回给用户,产生响应
3 . SpringMVC入门案例
第一步:在war工程的pom.xml文件中导入依赖
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>cn.itcast.springmvc</groupId> <artifactId>springmvc-day03</artifactId> <packaging>war</packaging> <!-- 1. 导入父模块 --> <parent> <groupId>cn.itcast.parent</groupId> <artifactId>itcast-parent</artifactId> <version>1.0.0-SNAPSHOT</version> </parent> <!-- 2. 导入相关依赖 --> <dependencies> <!-- 2.1 SpringMVC --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> </dependency> <!-- 2.2 JSP相关 --> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jsp-api</artifactId> </dependency> <!-- 2.3 日志 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </dependency> </dependencies> <!-- 3. 配置插件 --> <build> <plugins> <!-- 3.1 配置Tomcat插件 --> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <configuration> <!-- 端口信息 --> <port>8080</port> <!-- 项目路径 --> <path>/</path> </configuration> </plugin> </plugins> </build></project>
第二步:在WEB-INF目录下编写项目配置文件web.xml
<?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="MyWebApp" version="2.5"> <!-- 配置欢迎页面 --> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <!-- 描述servlet的名称信息 --> <display-name>springMVC</display-name> <servlet> <!-- 在web.xml(web程序的入口) 配置了DispatcherServlet, 并且指定所有以.do结尾的请求全部交给DispatcherServlet来处理--> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <!-- 配置/*会拦截所有请求,包括静态页面 --> <url-pattern>*.do</url-pattern> </servlet-mapping></web-app>
第三步:在WEB-INF目录下创建springmvc-servlet.xml
springmvc-servlet.xml是SpringMVC项目的核心配置文件
<?xml version="1.0" encoding="UTF-8"?><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" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 配置HandlerMapping --> <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/> <!-- 配置HandlerAdapter --> <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" /> <!-- 配置Handler,一般以Controller后缀,指向自定义的那个Controller--> <bean name="/hello.do" class="cn.itcast.controller.HelloController"/> <!-- 视图解析器,这里是用内部资源视图解析器,其实就是指向项目中的jsp文件 Example: prefix="/WEB-INF/jsp/", suffix=".jsp", viewname="test" -> "/WEB-INF/jsp/test.jsp" --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/"/> <property name="suffix" value=".jsp"/> </bean></beans>
第四步:编写Handler
Handler,具体的处理器,在SpringMVC中,一般是叫做Controller(控制器),我们可以自定义类,实现Controller接口,就称为控制器,代码如下所示:
package cn.itcast.controller;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{ @Override public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { ModelAndView mv = new ModelAndView("hello"); mv.addObject("msg","这是我的第一个springmvc程序"); return mv; }}
第五步:定义视图
创建一个hello.jsp文件,符合上面的视图规则,所以要放到WEB-INF/views/下,代码如下
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title></head><body> <h1>${msg}</h1></body></html>
第六步:测试
将该工程的父模块工程使用 maven install 命令,打成jar包到仓库中,然后使用tomcat7:run命令执行该模块工程
测试结果OK!
第七步:优化配置
- 我们尝试省略HandlerMapping和HandlerAdapter的配置
重启Tomcat重试:发现依然没有问题
原因:在spring-webmvc-4.1.3.RELEASE.jar –> org.springframework.web.servlet –> DispatcherServlet.properties文件中定义了很多默认配置,因此,一般我们只需要配置 Handler和视图解析器就够了
4 . SpringMVC注解案例
入门案例中,我们自定义控制器类的方式并不好,存在以下问题:
- 类必须实现Controller接口,不友好
- 每个类中只能有一个默认处理方法,只能处理一个用户请求
- 每个类需要在配置文件中进行配置,很麻烦
解决方案:在Spring2.5以后,就引入了注解方式的控制器定义方式,并且在Spring3.0以后引入了更多非常强大的注解帮我们进行参数注入
第一步:创建注解控制器
package cn.itcast.controller;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.servlet.ModelAndView;// 通过@Controller注解表名当前类是一个控制器类@Controllerpublic class AnnotationController { // 通过@RequestMapping注解定义当前方法的映射路径,在浏览器中通过这个路径访问这个方法 @RequestMapping("/show1") public ModelAndView show1(){ ModelAndView mv = new ModelAndView("hello"); mv.addObject("msg","这是使用注解的第一个SpringMVC程序!"); return mv; }}
第二步:在springmvc-servlet.xml配置包扫描
要想使用SpringMVC的注解控制器,只需要在springmvc-servlet.xml文件中增加一个配置包扫描,代码如下所示:
<!-- 使用SpringMVC注解:直接配置包扫描,不需要Controller的Bean了 --><context:component-scan base-package="cn.itcast.controller"/>
第三步:测试
测试结果OK!
第四步:默认的配置问题及推荐方案
我们使用SpringMVC默认配置没有问题,完全可以使用。但是呢,有一些小问题存在:
- 默认的HandlerMapping过时了,推荐我们使用RequestMappingHandlerMapping
- 默认的HandlerAdapter过时了,推荐使用RequestMappingHandlerAdapter
所以,这里要玩注解方式,就不能使用默认配置,必须手动设置这两个推荐的HandlerMapping和HandlerAdapter
在springmvc-servlet.xml文件中增加两个bean节点,代码如下所示:
<!-- 配置注解方式的HandlerMapping和HandlerAdapter --><bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/><bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
第五步:注解驱动及原理
经过上面第四步的修改,我们的配置又变的很麻烦了。为了解决这个问题,其实在SpringMVC中,给我们提供了一种解决方案:只需要配置一个标签即可
在springmvc-servlet.xml文件中取消第四步配置的两个bean节点,增加一个开启注解驱动的节点,代码如下所示:
<!-- 开启注解驱动,就不要配置HandlerMapping和HandlerAdapter了 --><mvc:annotation-driven />
原因:在spring-webmvc-4.1.3.RELEASE.jar –> org.springframework.web.servlet.config –> AnnotationDrivenBeanDefinitionParser.class这个类中已经注册了2个HandlerMapping和3个HandlerAdapter
因此,当我们配置了注解驱动开关,那么注解驱动的类被加载后,会自动加载这几个HandlerMapping和HandlerAdapter,所以我们不需要配置了。
注解驱动相当于是原来默认配置的升级版!
因此,玩注解驱动的最终配置方式就是:
- 开启注解驱动
- 开启扫描包
- 配置内部资源解析器
最终的springmvc-servlet.xml文件代码如下所示:
<?xml version="1.0" encoding="UTF-8"?><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" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 开启注解包扫描 --> <context:component-scan base-package="cn.itcast.controller"/> <!-- 开启注解驱动 --> <mvc:annotation-driven /> <!-- 配置视图解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/"/> <property name="suffix" value=".jsp"/> </bean></beans>
注意:上面的最终配置只针对注解方式有效
5 . RequestMapping请求映射方式
第一种:标准映射
规则:
- @RequestMapping可以设置在类上,也可以设置在方法上
- 请求的映射规则是:类上的RequestMapping + 方法上的RequestMapping
- 如果没有写 / ,SpringMVC会自动补全
- 类上的RequestMapping可以省略,这时直接用方法的RequestMapping访问
- 路径不可重复
第二种:Ant风格映射
Ant风格,其实就是通配符映射,有以下三种方式:
- ? 匹配任何单”字符”
- 匹配0或者任意数量的”字符”
- ** 匹配0或者更多的”目录”
第三种:占位符映射
@RequestMapping(value=”/users/{userId}”) :
其中{userId}占位符,请求的 URL 可以是 “/users/123456”或“/users/abcd”
通过@PathVariable 可以提取 URI 模板模式中的{userId}中的userId变量
演示代码如下:
// 演示占位符路径映射@RequestMapping("/show4/{userId}")public ModelAndView show4(@PathVariable("userId") Integer userId) { ModelAndView mv = new ModelAndView("hello"); mv.addObject("msg", "占位符:" + userId); return mv;}
第四种:请求方式限定
我们可以通过@RequestMapping注解中的 method属性来限定客户端的请求方式,method属性可以接收的是一个枚举数组
限定post请求方式代码演示如下:
// 演示请求方式的限定@RequestMapping(value = "/only/post", method={RequestMethod.POST})public ModelAndView show5() { ModelAndView mv = new ModelAndView("hello"); mv.addObject("msg", "请求方式限定,只允许post请求方式访问"); return mv;}
第四种:请求参数限定
我们还可以通过@RequestMapping注解的params属性来对请求的参数进行限定
需求如下:
- 限定必须携带参数userid
- 限定不能携带参数name
- 限定必须携带参数age但是不能等于18
- 限定必须携带参数nickname但是必须是lisi
代码演示如下:
// 演示请求参数的限定@RequestMapping(value = "/query", params = { "userid", "!name", "age!=18", "nickname=lisi" })public ModelAndView show6(Integer userid, String name, Integer age, String nickname) { ModelAndView mv = new ModelAndView("hello"); mv.addObject("msg", "请求参数限定,您输入的userId:" + userid + "--name:" + name + "--age:" + age + "--nickname" + nickname); return mv;}
6 . 视图解析
一、什么是视图解析?
视图就是展示给用户看的结果。可以是很多形式,例如:html、JSP、excel表单、Word文档、PDF文档、JSON数据、freemarker模板视图等等。
我们目前比较常用的就是JSP视图了。
二、传统JSP和JSTL视图
我们所使用的InternalResourceViewResolver解析器,默认支持JSP视图,而JSP中最常用的莫过于JSTL标签库了
1.导入JSTL标签库依赖如下:
<dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId></dependency>
2.编写用户的控制器代码如下:
package cn.itcast.controller;import java.util.ArrayList;import java.util.List;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.servlet.ModelAndView;import cn.itcast.mybatis.pojo.User;@Controller@RequestMapping("user")public class UserController { @RequestMapping("list") public ModelAndView getUserList(){ // 创建模型和视图对象 ModelAndView mv = new ModelAndView("user"); // 创建一个集合对象 List<User> users = new ArrayList<User>(); for (Long i = 1L; i <= 10L; i++) { User user = new User(); user.setId(i); user.setuserName("lisi" + i); user.setName("lisi" + (11 - i)); user.setAge(18); users.add(user); } mv.addObject("users",users); return mv; }}
3.编写用户视图代码如下:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title><style type="text/css"> table {border-collapse: collapse;} table, th, td {border: 1px solid green;padding: 10px}</style></head><body> <table> <tr> <th>ID</th> <th>UserName</th> <th>Name</th> <th>Age</th> </tr> <c:forEach items="${users }" var="user"> <tr> <td>${user.id }</td> <td>${user.userName }</td> <td>${user.name }</td> <td>${user.age }</td> </tr> </c:forEach> </table></body></html>
4.测试
测试结果OK!
三、JSON视图
在实际开发中,我们经常需要以JSON的格式进行数据的传输,所以在SpringMVC中提供了一种非常便捷的方式来返回一个JSON视图
第一步:引入依赖
SpringMVC的JSON功能,底层依赖的是Jackson这个JSON工具,引入依赖代码如下所示:
<!-- Jackson Json处理工具包 --><dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId></dependency>
第二步:定义需要访问的Controller
代码如下所示:
// 演示:返回JSON视图@RequestMapping("/ajaxlist")// 这里没有返回ModelAndView,而是通过ResponseBody注解声明,返回的是JSON视图// SpringMVC会自动的把返回值,本例中的是List<User>转为JSON格式返回@ResponseBodypublic List<User> getAjaxUserList(){ // 创建一个集合对象 List<User> users = new ArrayList<User>(); for (Long i = 1L; i <= 10L; i++) { User user = new User(); user.setId(i); user.setuserName("lisi" + i); user.setName("lisi" + (11 - i)); user.setAge(18); users.add(user); } return users;}
第三步:测试
测试结果OK!
第四步:分析原理
- 当SpringMVC读取到方法上的@ResponseBody注解时,就知道该方法不再使用默认的视图解析器解析视图,而是直接把结果写到响应体中,这样就需要对结果进行转换
- SpringMVC会从框架中查找有没有定义MessageConvertor(消息转换器),通过消息转换器转换结果,返回对应视图
- 在SpringMVC的注解驱动类中,会进行默认的消息转换器注册,因为我们引入了jacksonJson包,所以会注册JSON的消息转换器
注解驱动类中的代码:在AnnotationDrivenBeanDefinitionParser.class中关键点代码如下所示:
if (jackson2Present) { RootBeanDefinition jacksonConverterDef = createConverterDefinition(MappingJackson2HttpMessageConverter.class, source); GenericBeanDefinition jacksonFactoryDef = createObjectMapperFactoryDefinition(source); jacksonConverterDef.getConstructorArgumentValues().addIndexedArgumentValue(0, jacksonFactoryDef); messageConverters.add(jacksonConverterDef); }
4 因为只有JSON消息转换器可以对Java对象序列化,因此这里默认用了JSON转换
第五步:问题:如果有多个消息转换的依赖被引入,那么就会注册多个消息转换器:例如JSON、XML等等,此时会用哪个转换器?
答案:此时会根据请求头中的accept来判断返回什么类型数据
四、直接返回视图名称
有时候,我们并不需要返回数据模型,而仅仅是访问某个JSP页面。如果是传统做法,你要创建一个ModelAndView对象,并且返回。很麻烦。
所以,SpringMVC允许直接返回一个String数据,作为视图名称。不需要数据模型,演示代码如下:
// 演示:直接返回视图名称,不需要数据模型@RequestMapping("/index")public String index(){ // 如果只是访问一个页面,就不需要创建ModelAndView对象,直接返回一个字符串 // 这个字符串就会作为视图的名称,从而去访问对应的页面 return "index";}
编写index.jsp页面
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title></head><body> <h1>欢迎光临首页</h1></body></html>
也可以把视图与模型分离。在参数中注入Model对象:
// 把视图与模型分离。在参数中注入Model对象@RequestMapping("/index2")// 直接返回视图,而不需要model中的数据public String index2(Model model){ model.addAttribute("msg","我试试Model好不好用"); return "hello";}
五、重定向和转发
在SpringMVC中,如果要实现重定向或转发,也非常简单,只需要在返回的字符串前以下面的格式做前缀即可:
redirect:/hello.do 重定向到hello.do
forward:/hello.do 转发到hello.do
注意:后面必须跟上URL路径而非视图名
演示代码如下所示:
// 演示重定向@RequestMapping("/demo1")// 直接返回视图,而不需要model中的数据public String demo1(){ // 返回值以redirect开头,但是后面必须跟上URL路径而非视图名 return "redirect:/user/index.do";}// 演示转发@RequestMapping("/demo2")// 直接返回视图,而不需要model中的数据public String demo2(){ // 返回值以redirect开头,但是后面必须跟上URL路径而非视图名 return "forward:/user/index.do";}
注意:返回ModelAndView,或者没有写redirect和forward时,默认都属于转发
六、不返回视图
有的时候,我们接收一个请求,处理后并不打算给页面返回任何数据,只是返回成功的状态码即可,演示代码如下:
// 演示不返回视图@RequestMapping("/demo3")@ResponseStatus(HttpStatus.OK)// 如果写void,表示不返回模型和视图,那么就需要加ResponseStatus,返回一个响应的状态码public void demo3() { System.out.println("你好,我收到了你的请求,但是什么也不想做");}
7 . 请求参数绑定和获取
struts2获取参数的弊端:
获取页面参数,是javaee必不可少的一个环节,在struts中,是通过action定义属性,或者modle的方式进行数据绑定和获取,需要提供setter和getter方法,略显麻烦
SpringMVC获取参数的优点:
在SpringMVC中,却可以非常方便的获取请求参数,只需要在对应方法的参数列表中定义出来,即可获取,所见即所得!
- SpringMVC学习总结(一)
- SpringMVC学习总结(二)
- SpringMVC学习总结(三)
- SpringMVC学习总结(四)
- SpringMVC学习总结(五)
- springmvc interceptori学习总结
- Springmvc学习总结
- SpringMvc之前学习总结
- Web-SpringMVC学习总结
- SpringMVC学习相关总结
- springMVC-学习总结-框架
- springmvc-学习总结-注解
- springmvc-学习总结-校验
- SpringMVC框架学习总结
- springMVC学习总结
- SpringMVC学习总结
- SpringMVC学习笔记总结
- SpringMVC学习,总结
- BZOJ1096: [ZJOI2007]仓库建设
- 什么是spring,它有什么特点?
- Hystrix的原理与使用
- ROS 安装与配置
- 方法重载
- SpringMVC学习总结
- 编写Shell脚本的最佳实践
- 面试题集合---数据结构
- Java LinkedList和 ArrayList
- laravel使用faker填充数据
- javaWeb笔记之Servlet
- 书单
- C#连接mysql数据及简单操作
- 【转】【记录】Java五个最常用的集合类之间的区别和联系