SpringMVC简单介绍
SpringMVC是Spring框架的一部分
优点:
- 基于MVC架构,分工明确,解耦合。
- 上手快,使用简单,轻量级,jar包小,不依赖特定的类和接口
- 作 为 Spring 框 架 一 部 分 , 能 够 使 用 Spring 的 IoC 和 Aop,方 便 整 合。Strtus,MyBatis,Hiberate,JPA 等其他 框架。
- SpringMVC 强化注解的使用,在控制器,Service ,Dao 都可以使用注解 。方便灵活
SpringMVC小案例
- 新建maven web项目
- 配置依赖pom.xml
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.16.RELEASE</version>
</dependency>
- 注册中央调度器DispatcherServlet
- )DispatcherServlet它是一个Servlet, 父类继承了HttpServlet
- )DispatcherServlet的作用
- )是接收请求,显示处理结果给用户。
- )把接收到的请求分派给处理器(控制器)对象。
- )DispatcherServlet也叫做前端控制器(front controller)
web.xml
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
在Tomcat启动时,根据load-on-startup的值创建dispatcherservlet对象,这是一个Servlet,创建时执行init()方法,,这个方法执行时会创建WebApplicationContext,创建容器时会读取spring需要的配置文件,这个配置文件的默认存在路径是WEB-INF,默认名称是当前servlet的 <servlet-name> -servlet.xml
url-pattern:将请求传递给中央调度器。常用的方式:1. **.do **.action **.mvc等,使用 **.jsp容易分不清请求与页面,所以不用。2. “/"
4. 创建处理器@Controller
@Controller默认是单例模式,在处理器类上添加@Controller注册为处理器类,它不是servlet, 起到servlet的作用。
方法上面加入@RequestMapping(value=“请求的uri地址”)
@Controller
public class MyController {
@RequestMapping(value = "/my.do")
public ModelAndView doSome() {
ModelAndView mv = new ModelAndView();
//添加到model部分,数据放到request.setAttrubute(),放到request作用域中
mv.addObject("msg", "第一个springmvc项目");
mv.addObject("fun", "doSome");
//指定视图,框架对视图执行的是forWord操作:req.getRequestDisaptcher("/show.jsp").forwoard(req,resp);
mv.setViewName("show");
return mv;
}
}
- spring配置文件applicationContext.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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 声明组件扫描器-->
<context:component-scan base-package="com.ljf.controller" />
<!--创建视图View对象, 指定视图的路径,和扩展名-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--前缀:指定视图文件的路径-->
<property name="prefix" value="/WEB-INF/view/" />
<!--后缀:指定视图文件的扩展名-->
<property name="suffix" value=".jsp" />
</bean>
</beans>
- 定义目标页面
webapp/index.jsp
用来发送请求my.do
<a href="my.do" >my.do</a>
webapp/WEB-INF/view/show.jsp
用于接收传回来的值
<!-- el表达式 -->
msg数据:${msg}
<hr>
fun数据:${fun}
SpringMVC执行流程
-
DispatcherServlet的初始化做了什么
在父类的init()initServletBean();
initServletBean(){
创建springmvc的容器的对象, 读取springmvc的配置文件
this.webApplicationContext = initWebApplicationContext();把springmvc的容器对象放入到ServletContext中
String attrName = getServletContextAttributeName();
getServletContext().setAttribute(attrName, wac);
} -
请求的处理
1)用户发起some.do
2)DispatcherServlet接收some.do, 把请求交给了处理器映射器
处理器映射器:springmvc中的对象, 需要实现HandlerMapping的接口。
在框架中映射器有很多。
映射器作用:根据请求some.do找到处理他的处理器对象(MyController)
然后把MyController对象放到“处理器执行链”的类中保存
3)DispatcherServlet把“处理器执行链”的控制器对象交给了处理器适配器
处理器适配器:springmvc的对象,需要实现HandlerAdapter接口(可以有多个)
适配器作用:执行控制器对象的方法(MyController中的doSome())
执行流程分析:
(1)浏览器提交请求到中央调度器
(2)中央调度器直接将请求转给处理器映射器。
(3)处理器映射器会根据请求,找到处理该请求的处理器,并将其封装为处理器执行链后返回给中央调度器。
(4)中央调度器根据处理器执行链中的处理器,找到能够执行该处理器的处理器适配器。
(5)处理器适配器调用执行处理器。
(6)处理器将处理结果及要跳转的视图封装到一个对象 ModelAndView 中,并将其返回给处理器适配器。
(7)处理器适配器直接将结果返回给中央调度器。
(8)中央调度器调用视图解析器,将 ModelAndView 中的视图名称封装为视图对象。
(9)视图解析器将封装了的视图对象返回给中央调度器
(10)中央调度器调用视图对象,让其自己进行渲染,即进行数据填充,形成响应对象。
(11)中央调度器响应浏览器。
SpringMVC注解
@Controller 注册创建控制器对象
@RequestMapping 表示接收请求
- 属性:value :接收的请求
method:请求的方式 - 可以用在方法名上面,表示这个请求需要执行的方法;用在类名上面,表示这个类是一个请求模块,其内部还有其他子请求
处理器方法的参数
- 可以在@RequestMapping修饰的方法添加形参:HttpServletRequest HttpServletResponse HttpSession 这三种类型的参数
- 可以形参可以与请求中携带的参数名一致,但是类型也必须一致。框架会自动进行赋值
- 形参与请求参数名不一致时,可以通过@RequestParam进行指定
@RequestParam(“请求参数名”) 形参类型 形参名 - 当传入的多个参数是某个实体类的属性时,且请求参数名与这个实体类的属性名一致,那么形参可以是这个实体类的类型(当然类型也要相同),实体类必须声明set方法。
传入name,age 。实体类Student属性:name,age
public void doSome(Student student){ … }
在接收请求时,doSome方法还没实行,先创建Student对象,将name、age通过set方法赋值Student的对象。 - 当上面3、4同时出现时
public void doSome(Student student,String name){ … }
name会传给student,也会传给形参name
请求参数中文乱码问题
对于前面所接收的请求参数,若含有中文,则会出现中文乱码问题
解决方案:过滤器
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
<init-param>
<param-name>forceRequestEncoding</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>forceResponseEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
处理器方法的返回值
- ModelAndView
- ModelAndView 表示请求处理结果的数据和视图
- Model:表示数据的,Model实际是Map结构
mv.addObject(“msg”, “第一个springmvc项目”);
mv.addObject(“fun”, “doSome”); - View:表示视图的,也就是jsp
mv.setViewName(“other”);
- String类型
return “逻辑视图名”
有视图解析器,可以将逻辑视图名配置成完整路径 - void
一般用来传递json数据 - Object
处理器方法返回 Object 对象。这个 Object 可以是 Integer,String,自定义对象,Map,List 等。但返回的对象不是作为逻辑视图出现的,而是作为直接在页面显示的数据出现的。
返回对象,一般使用JSON格式的数据,需要使用@ResponseBody 注解。
- 需要添加依赖
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
-
声明注解驱动
<mvc:annotation-driven />
将 Object 数据转化为 JSON 数据,需要由消息转换器 HttpMessageConverter 完成。而转换器的开启,需要由mvc:annotation-driven/来完成。
当 Spring 容器进行初始化过程中,在mvc:annotation-driven/处创建注解驱动时,默认创建了七个 HttpMessageConverter 对象。也就是说,我们注册mvc:annotation-driven/,就是为了让容器为我们创建 HttpMessageConverter 对象。
HttpMessageConverter 接口四个方法 :
boolean canRead(Class<?> clazz,MediaType mediaType)
: 指定转换器可以读取的对象类型,即转换器是否可将请求信息转换为 clazz 类型的对象,同时指定支持 MIME 类型(text/html,applaiction/json 等)
boolean canWrite(Class<?> clazz,MediaType mediaType)
:指定转换器是否可将 clazz 类型的对象写到响应流中,响应流支持的媒体类型在MediaType 中定义。LIst getSupportMediaTypes():该转换器支持的媒体类型。
T read(Class<? extends T> clazz,HttpInputMessage inputMessage)
:将请求信息流转换为 T 类型的对象。
void write(T t,MediaType contnetType,HttpOutputMessgae outputMessage)
:将 T 类型的对象写到响应流中,同时指定相应的媒体类型为 contentType -
返回自定义类型对象
返回自定义类型对象时,不能以对象的形式直接返回给客户端浏览器,而是将对象转换为 JSON 格式的数据发送给浏览器的。需要jackson的相关依赖,同时需要在处理方法上面使用@ResponseBody修饰。这表示返回的自定义类型对象是json格式的 -
返回List集合
将返回的list集合转换成json格式进行返回,需要jackson的相关依赖,同时需要在处理方法上面使用@ResponseBody修饰。 -
返回String类型
如果方法上不使用@ResponseBody修饰,则返回值表示返回一个页面。
使用@ResponseBody修饰,则表示返回值是一个字符串类型的数据。