文章目录
一、使用注解搭建 spring-mvc 框架
(1)在 spring 包的基础上导入 spring-webmvc jar包
(2)在 web.xml 中加载核心控制器
springmvc 的核心控制器是一个 Servlet,在 webmvc 组件的 org.springframework.web.servlet 包下名为 DispatcherServlet,该 Servlet 用于接收所有请求并进行分发不同的业务控制器以及后续的响应工作。
<!-- 核心控制器 -->
<servlet>
<servlet-name>mvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>mvc</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
(3)配置 spring-mvc 的配置文件:
在没有特别说明的情况下 spring-mvc 会默认去读取位于WEB-INF文件夹下,名为核心控制器 Servlet 的 servlet-name+servlet.xml 的文件作为它的配置文件,例如根据上面第二步的配置核心控制器 DispatcherServlet 的 servlet-name 为 springmvc,那么WEB-INF文件夹下就应该新建一个名为 springmvc-servlet.xml 的配置文件。
如果想要自定义配置文件名称,可以在src目录下新建任意名称的xml文件,然后通过servlet的初始化参数将配置文件的名称告知给 springmvc。
<!-- 核心控制器 -->
<servlet>
<servlet-name>mvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 如果是创建在src目录下的mvc-servlet.xml,则需要在web.xml中配置下面的信息
告知springmvc这个配置文件的名字,便于初始化过程中加载配置文件mvc-servlet.xml -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:mvc-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
(4)新建业务控制器处理请求
- spring-mvc 的业务控制器可以是实现了 Controller 接口的类,也可以是普通类,之所以 springmvc 能够支持多种不同类型的业务控制器,基于 springmvc 的处理器适配器(HandlerAdapter)。在使用注解搭建 springmvc 框架时,业务控制器用普通类来定义就可以了,不需要实现任何接口或者继承任何类。
- 在业务控制器类上,需要添加@Controller注解,添加该注解的目的是为了使用 spring 的IOC创建控制层的对象。
- 在业务控制器中新建方法,将方法的返回值定义为String类型,方法名没有限制,同时在方法上添加一个注解@RequestMapping(“请求地址”),该注解的目的是将业务控制器中的方法与请求地址进行映射,当服务器收到该请求时,将会交给这个方法来执行。在方法中返回一个网页的地址,作为响应的视图。
@Controller
public class ProductsController {
@RequestMapping("select")
public String select() {
System.out.println("执行到Controller层,处理请求");
return "success.jsp";
}
}
(5)在 springmvc 的配置文件中,添加扫包信息和注解驱动器
<!-- 配置Spring扫描包的地址 -->
<context:component-scan base-package="com.springmvc.demo1"></context:component-scan>
<!-- 开启注解驱动 -->
<mvc:annotation-driven></mvc:annotation-driven>
<mvc:annotation-driven/>
:
在 spring3.0 以前该标签的作用是注册DefaultAnnotationHandlerMapping
和AnnotationMethodHandlerAdapter
两个 bean,springmvc 默认情况下只支持以配置文件的方式进行配置,是没有加载专门用于通过扫描注解生成处理器的DefaultAnnotationHandlerMapping
(注解处理映射器)和执行注解处理器的AnnotationMethodHandlerAdapter
(注解处理适配器),所以必须手动配置这两个 bean 才能通过注解的方式处理请求。
(6)通过浏览器测试
RequestMapping
注解也可以放到业务控制器的类上,作为当前类中所有请求的命名空间来使用,类似于 struts2 中的 namespace。
二、Spring-mvc 的执行过程及其重要组件
1、重要组件:
(1)DispatcherServlet
:核心控制器
用户请求到达核心控制器,它就相当于MVC模式中的C,DispatcherServlet 是整个流程控制的中心,由它调用其它组件处理用户的请求, DispatcherServlet 的存在降低了组件之间的耦合性。
(2)HandlerMapping
:处理器映射器
HandlderMapping.getHandler(request);
HandlerMapping 负责根据用户请求找到 Handler 即处理器(业务控制器),springmvc 提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。
(3)Handler
:处理器
Handler 是继 DispatcherServlet 核心控制器之后的业务控制器,在 DispatcherServlet 的控制下 Handler 对具体的用户请求进行处理。
(4)HandlAdapter
:处理器适配器
由于 Spring-mvc支持多种类型的处理器,为了执行不同种类的处理器,Spring-mvc 通过 HandlerAdapter 对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。
(5)View Resolver
:视图解析器
View Resolver 负责将处理结果生成 View 视图,View Resolver 首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成 View 视图对象,最后对 View 进行渲染将处理结果通过页面展示给用户。
2、Spring-mvc 执行流程图:
(1)用户发送请求
(2)请求进入核心控制器DispatcherServlet
(3)通过处理器映射器(HandlerMapping)获取处理器对象(Handler)(包含了业务控制器方法的代理对象)
(4)通过相匹配的处理器适配器调用处理器
(5)处理器执行,并得到返回值(String、ModelAndView、需要转为json的数据)
(6)通过视图解析器对返回值进行解析,返回不同的视图
(7)核心控制器响应信息
三、Spring-mvc 参数获取
1、Spring-mvc 参数获取
处理器适配器在执行 Handler 之前会直接把http请求的 key/value 数据绑定到 Handler 方法形参上。
(1)默认支持的参数类型
处理器形参中添加如下类型的参数处理适配器会默认识别并进行赋值。
HttpServletRequest
:通过 request 对象获取请求信息
HttpServletResponse
:通过 response 处理响应信息
HttpSession
:通过 session 对象得到 session 中存放的对象
@RequestMapping("test")
public String test(HttpServletRequest request, HttpServletResponse response, HttpSession session) {
return "success.jsp";
}
(2)基本数据类型
http请求中包含的数据,并自动进行数据类型转换
@RequestMapping("test")
public String test(int id) {
return "success.jsp";
}
默认情况下,http 请求中的参数名称必须和方法形参名称一致才能进行参数绑定,但是可以使用 @RequestParam 注解进行手动的参数绑定,例如:http 中的参数名称为 user_id,形参中的参数名称为id,就需要在形参前添加@RequestParam(name="user_id")
进行绑定。
@RequestMapping("test")
public String test(@RequestParam(name="user_id")int id) {
return "success.jsp";
}
(3)实体类型
将http请求中包含的数据封装为实体类型
为了便于后续执行过程中参数的传递,通常我们会将多个参数封装称为一个实体类型的对象,在形参列表中定义一个实体类型的形参,在发送http请求时直接使用实体类的属性名称作为参数即可。
① 实体类
public class Users {
private Integer userId;
private String userName;
private String userPassword;
//省略get、set方法
}
② concontroller 层
@RequestMapping("test")
public String test(Users users) {
System.out.println(users.getUserName());
return "success.jsp";
}
页面传递参数时,将参数名称指定为 userName 和 userPassword 即可,注意不要和 struts2 混淆写成 users.userName和 users.userPassword,这样是接收不到参数的。
假如对象之间有嵌套的关系,例如 User 中定义了一个 UserInfo 对象,那么如果要给 UserInfo 对象中的id赋值,在传参时使用 UserInfo对象名称.属性名=值
的方式将参数保存到 UserInfo 对象中
(4)日期类型
如果参数中有字符串类型需要转为日期类型,那么需要执行日期类型的转换格式不然会抛出异常。
@RequestMapping("test")
public String test(@DateTimeFormat(pattern="yyyy-MM-dd")Date time) {
System.out.println(time);
return "success.jsp";
}
如果日期类型数据需要绑定在在实体类对象中,那么需要在实体类的日期属性上添加该注解
public class Users {
private Integer userId;
private String userName;
private String userPassword;
@DateTimeFormat(pattern="yyyy-MM-dd")
private Date time;
//省略get、set方法
}
(5)字符串数组类型
将 http 请求中包含的字符串数组数据封装为数组,http 请求中包含了数组数据,例如用多选框传递的参数 arr=“张三”,arr=“李四”,那么在形参中需要定义名为 arr 的字符串数组来绑定参数。
@RequestMapping("test")
public String test(String[] arr) {
System.out.println(arr[0]);
return "success.jsp";
}
2、SpringMVC 乱码处理
SpringMVC 在处理 post 请求传递的参数时,是没有进行乱码处理的,我们需要在项目中引入一个过滤器来处理 post 请求中的乱码。
<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>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>