一.springmvc 工作原理
springmvc常用的组件为
SpingMVC的常用组件:
1)DispatcherServlet
是一种前端控制器,由框架提供。
作用:统一处理请求和响应。除此之外还是整个流程控制的中心,由 DispatcherServlet 来调用其他组件,处理用户的请求
2)HandlerMapping
处理器映射器,由框架提供。
作用:根据请求的 url、method 等信息来查找具体的 Handler(一般来讲是Controller)
3)Handler(一般来讲是Controller)
处理器,注意,这个需由工程师自己开发。
作用:在 DispatcherServlet 的控制下,Handler对具体的用户请求进行处理
4)HandlerAdapter
处理器适配器 ,由框架提供。
作用:根据映射器找到的处理器 Handler 信息,按照特定的规则去执行相关的处理器 Handler。
小结:
Handler 是用来干活的工具;
HandlerMapping 用于根据需要干的活找到相应的工具;
HandlerAdapter 是使用工具干活的人。详细讲解可以看这篇博客(115条消息) SpringMVC 处理器适配器详解_aFa攻防实验室的博客-CSDN博客_处理器适配器
5)ViewResolver
视图解析器,由框架提供。
作用: ViewResolver 负责将处理结果生成 View 视图。 ViewResolver 首先根据逻辑视图名解析成物理图名,即具体的页面地址,再生成 View 视图对象,最后对 View 进行渲染将处理结果通过页面展示给用户。
6)View
视图,工程师自己开发
作用:View接口的职责就是接收model对象、Request对象、Response对象,并渲染输出结果给Response对象。
流程图:
主要流程:
1. 用户通过浏览器发起 HttpRequest 请求到前端控制器 (DispatcherServlet)。
2. DispatcherServlet 将用户请求发送给处理器映射器 (HandlerMapping)。
3. 处理器映射器 (HandlerMapping)会根据请求,找到负责处理该请求的处理器,并将其封装为处理器执行链 返回 (HandlerExecutionChain) 给 DispatcherServlet
4. DispatcherServlet 会根据 处理器执行链 中的处理器,找到能够执行该处理器的处理器适配器(HandlerAdaptor) --注,处理器适配器有多个
5. 处理器适配器 (HandlerAdaptoer) 会调用对应的具体的 Controller
6. Controller 将处理结果及要跳转的视图封装到一个对象 ModelAndView 中并将其返回给处理器适配器 (HandlerAdaptor)
7. HandlerAdaptor 直接将 ModelAndView 交给 DispatcherServlet ,至此,业务处理完毕
8. 业务处理完毕后,我们需要将处理结果展示给用户。于是DisptcherServlet 调用 ViewResolver,将 ModelAndView 中的视图名称封装为视图对象
9. ViewResolver 将封装好的视图 (View) 对象返回给 DIspatcherServlet
10. DispatcherServlet 调用视图对象,让其自己 (View) 进行渲染(将模型数据填充至视图中),形成响应对象 (HttpResponse)
11. 前端控制器 (DispatcherServlet) 响应 (HttpResponse) 给浏览器,展示在页面上。
总的来说工作做流程就是:
前端控制器DispatcherServlet -> 处理器映射HandlerMapping -> 处理器适配器HandlerAdapter -> 具体的Controller -> 视图解析ViewResolver -> View -> 响应给客户端。
MVC优点:
MVC三个模块相互独立,松耦合架构
多视图共享一个模型,大大提高代码的可重用性
控制器提高了应用程序的灵活性和可配置性
有利于软件工程化管理
MVC缺点:
增加了系统结构和实现的复杂性,不适合小型规模的项目
视图层与模型之间需要控制器做中间的连接控制,所以效率较低
二、创建Spring MVC程序
1.下载JAR文件
<!--版本锁定-->
<spring.version>5.2.7.RELEASE</spring.version>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<!-- spring -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.19</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<!-- aop -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>1.9.5</version>
</dependency>
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.0</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
<!-- 整合spring和mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
<!-- SpringMVC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- utils -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.28</version>
</dependency>
2.编写配置文件
创建Spring MVC的配置文件:springmvc-servlet.xml
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 配置controller -->
<bean id="/indexController" class="com.cskt.controller.IndexController"> </bean>
</beans>
在web.xml中配置DispatcherServlet,命名为springmvc
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- servlet servletMapping -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:spring-mvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
三、工作流程:
四、@Controller、@RequestMapping
Spring 2.5 版本新增了 Spring MVC 注解功能,用于替换传统的基于 XML 的 Spring MVC 配置。
1、使用注解的优点
在基于注解的控制器类中可以编写多个处理方法,进而可以处理多个请求(动作),这就允许将相关的操作编写在同一个控制器类中,从而减少控制器类的数量,方便以后维护。
基于注解的控制器不需要在配置文件中部署映射,仅需要使用 @RequestMapping 注解一个方法进行请求处理即可。
2、@Controller
@Controller 注解用于声明某类的实例是一个控制器。
2.1 使用步骤
在Controller类中加上注解
package com.hqyj.cl.controller;
import org.springframework.stereotype.Controller;
@Controller
public class AnnotationTest {
// 方法代码
}
springmvc-servlet.xml配置包扫描
Spring MVC 使用扫描机制找到应用中所有基于注解的控制器类,所以,为了让控制器类被 Spring MVC 框架扫描到,需要在配置文件中声明 spring-context,并使用 <context:component-scan/> 元素指定控制器类的基本包(请确保所有控制器类都在基本包及其子包下)。
<!-- 使用扫描机制扫描控制器类,控制器类都在com.hqyj.controller包及其子包下 -->
<context:component-scan base-package="com.hqyj.controller" />
3、@RequestMapping
一个控制器内有多个处理请求的方法,如 UserController 里通常有增加用户、修改用户信息、删除指定用户、根据条件获取用户列表等。每个方法负责不同的请求操作,而 @RequestMapping 就负责将请求映射到对应的控制器方法上。
@RequestMapping 注解可用于类或方法上。用于类上,表示类中的所有响应请求的方法都以该地址作为父路径。
五、Spring MVC传递参数
Spring MVC Controller 接收请求参数的方式有很多种,有的适合 get 请求方式,有的适合 post 请求方式,有的两者都适合。主要有以下几种方式:
通过实体 Bean 接收请求参数
通过处理方法的形参接收请求参数
通过 HttpServletRequest 接收请求参数
通过 @PathVariable 接收 URL 中的请求参数
通过 @RequestParam 接收请求参数
1、通过实体Bean接收请求参数
实体 Bean 接收请求参数适用于 get 和 post 提交请求方式。需要注意,Bean 的属性名称必须与请求参数名称相同。示例代码如下
@RequestMapping("/login")
public String login(User user, Model model) {
if ("admin".equals(user.getUsername())
&& "112112".equals(user.getPassword())) {
model.addAttribute("message", "登录成功");
return "index"; // 登录成功,跳转到 index.jsp
} else {
model.addAttribute("message", "用户名或密码错误");
return "login";
}
}
2、通过处理方法的形参接收请求参数
通过处理方法的形参接收请求参数就是直接把表单参数写在控制器类相应方法的形参中,即形参名称与请求参数名称完全相同。该接收参数方式适用于 get 和 post 提交请求方式。示例代码如下
@RequestMapping("/login")
public String login(String username, String password, Model model) {
if ("admin".equals(username)
&& "112112".equals(password)) {
model.addAttribute("message", "登录成功");
return "index"; // 登录成功,跳转到 index.jsp
} else {
model.addAttribute("message", "用户名或密码错误");
return "login";
}
}
3、通过HttpServletRequest接收请求参数
同servlet阶段获取方式,controller层方法参数中包含HttpServletRequest参数,可以获取请求中的参数。
4、通过@PathVariable接收URL中的请求参数
@RequestMapping(value = "/login/{username}/{password}")
public String login(@PathVariable("username") String username, @PathVariable("password") String password) {
System.out.println(username);
System.out.println(password);
return "index";
}
在访问http://localhost:8080/user/login/admin/123456路径时,上述代码会自动将 URL 中的模板变量 {username} 和 {password} 绑定到通过 @PathVariable 注解的同名参数上,即 username=admin、password=123456。