- 🤪个人主页:i笨笨i
- 🐽版权:本文由【i笨笨i】原创,需要转载联系博主
- 🎉欢迎关注、点赞、收藏(一键三连)和订阅专栏哦!
SpringMVC
一、SpringMVC介绍
1.1、回顾MVC三层架构
模型一般由实现JavaBean,javaBean分为实体Bean和业务Bean,业务Bean包含了业务逻辑类和数据访问类。展示层包含控制器和视图。
展示层:jsp+servlet,SpringMVC;业务逻辑层:JavaBean和Spring;数据访问层:jdbc、springjdbc、MyBatis;
控制器:servlet、SpringMVC
分层、解耦、责任分明化;
1.2、介绍
SpringMVC是Spring框架的一部分,是基于Java实现的轻量级Web框架。学习SpringMVC框架最核心的就是DispatcherServlet的设计,掌握好DispatcherServlet是掌握SpringMVC的核心关键。
1.3、SpringMVC优点
- 轻量级,可适配,非侵入
- 高效,基于请求响应的MVC框架(解耦、可重用、提高维护性)
- 与Spring兼容好
- 约定优于配置
- 功能强大:灵活的URL映射,RESTful、数据验证、格式化、本地化、主题标签库等
- 简洁灵活
1.4、SpringMVC的实现原理
Spring的Web框架围绕==DispatcherServlet(前端控制器)==设计。DispatcherServlet的作用是将请求分发到不同的处理器。从Spring 2.5开始,使用java 5 或者以上版本用户可以采用基于注解的controller声明方式。
SpringMVC框架像许多其他MVC框架一样,以请求为驱动,围绕一个中心Servlet分派请求及提供其他功能,DispatcherServlet是一个实际的Servlet(它继承自HttpServlet基类)。
SpringMVC的具体执行流程:
当发起请求时被前置的控制器拦截到请求,根据请求参数生成代理请求,找到请求对应的实际控制器,控制器处理请求,再创建数据模型,访问数据库,将模型响应给中心控制器,控制器使用模型与视图渲染视图结果,将结果返回给中心控制器,再将结果返回给请求者。
二、SpringMVC入门案例
2.1、基于注解的SpringMVC
1️⃣使用SpringMVC技术需要先导入SpringMVC坐标与Servlet坐标
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope><!-- Tomcat内置了servlet所以这里设置了范围 -->
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
2️⃣创建SpringMVC控制器类(等同于Servlet功能)处理请求
package com.item.controller;
//2.定义Controller
//2.1使用@Controller来定义bean
@Controller
public class UserController {
//2.2设置当前操作的访问路径
@RequestMapping("/save")
//2.3设置当前操作的返回值类型
@ResponseBody//将返回值作为一个整体给外部
public String save(){
System.out.println("user save ...");
return "{'module':'springmvc'}";
}
}
3️⃣初始化SpringMVC环境(同Spring环境),设定SpringMVC加载对应的bean
package com.item.config;
@Configuration
@ComponentScan("com.item.controller")
public class SpringMvcConfig {
}
4️⃣初始化Servlet容器,加载SpringMVC环境,并设置SpringMVC技术处理的请求
package com.item.config;
//4. 定义一个servlet容器启动的配置类,在里面加载Spring的配置
public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {
/**
* 加载springMVC容器配置
* @return
*/
@Override
protected WebApplicationContext createServletApplicationContext() {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(SpringMvcConfig.class);
return ctx;
}
/**
* 设置哪些请求归属springMVC处理
* @return
*/
@Override
protected String[] getServletMappings() {
return new String[]{"/"};// "/"表示所以请求
}
/**
* 加载Spring容器配置
* @return
*/
@Override
protected WebApplicationContext createRootApplicationContext() {
/*加载Spring容器配置,SpringConfig类为Spring配置类
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(SpringConfig.class);
return ctx;
*/
return null;
}
}
- 简化开发
AbstractAnnotationConfigDispatcherServletInitializer是AbstractDispatcherServletInitializer的子类。
public class ServletContainersInitConfig
extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{SpringConfig.class};
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{SpringMvcConfig.class};
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
5️⃣在IDEA中启动Tomcat
- 导入插件(pom.xml内)
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<port>8080</port><!--端口号-->
<path>/</path><!--访问路径-->
</configuration>
</plugin>
</plugins>
</build>
- 方式一
点击 Add Configuration
点击
加号
再找到Maven(此项目用Maven构建)。
再Run框内输入
tomcat7:run
,即可点击apply,ok
- 方式二
导入插件后,可以通过快捷方式运行,在程序区右击如何选择Run Maven,再选择tomcat7:run
2.1.1、相关注解介绍
名称:
@Controller
类型:类注解
位置:SpringMVC控制器类定义上方
作用:设定SpringMVC的核心控制器bean
- 范例
@Controller
public class UserController {
}
名称:
@RequestMapping
类型:方法注解
位置:SpringMVC控制器方法定义上方
作用:设置当前控制器方法请求访问路径
- 范例
@RequestMapping("/save")
public void save(){
System.out.println("user save ...");
}
- 相关属性
- value(默认):请求访问路径
名称:
@RequestMapping
类型:方法注解
位置:SpringMVC控制器方法定义上方
作用:设置当前控制器方法响应内容为当前返回值,无需解析
- 范例
@RequestMapping("/save")
@ResponseBody
public String save(){
System.out.println("user save ...");
return "{'module':'springmvc'}";
}
2.1.2、总结
-
SpringMVC入门程序开发总结(1+N)
- 一次性工作
- 创建工程、设置服务器、加载工程
- 导入坐标
- 创建web容器启动类,加载SpringMVC配置,并设置SpringMVC请求拦截路径
- SpringMVC核心配置类(设置配置类,扫描controller包,加载controller控制器bean)
- 多次工作
- 定义处理请求的控制器类
- 定义处理请求的控制器类方法,并配置映射路径(@RequestMapping)与返回json数据(@ResponseBody)
- 一次性工作
-
AbstractDispatcherServletInitializer
类是SpringMVC提供的快速初始化Web3.0容器的抽象类 -
AbstractDispatcherServletInitializer
提供三个接口方法供用户实现- createServletApplicationContext方法,创建Servlet容器时,加载SpringMVC对应的bean并放入WebApplicationContext对象范围中,而WebApplicationContext的作用范围为ServletContext范围,即整个web容器范围。
- getServletMappings方法,设定SpringMVC对应的请求映射路径,设置为
/
表示拦截所以请求,任意请求都转入到SpringMVC进行处理。 - createRootApplicationContext方法,如果创建Servlet容器时需要加载非SpringMVC对应的bean,使用当前方法进行,使用方式同createServletApplicationContext
public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer { /** * 加载springMVC容器配置 * @return */ @Override protected WebApplicationContext createServletApplicationContext() { AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext(); ctx.register(SpringMvcConfig.class); return ctx; } /** * 设置哪些请求归属springMVC处理 * @return */ @Override protected String[] getServletMappings() { return new String[]{"/"};// "/"表示所以请求 } /** * 加载Spring容器配置 * @return */ @Override protected WebApplicationContext createRootApplicationContext() {、 return null; } }
2.1.3、入门案例工作流程分析
- 启动服务器初始化过程
- 服务器启动,执行ServletContainersInitConfig类,初始化web容器
- 执行createServletApplicationContext方法,创建了WebApplicationContext对象
- 加载SpringMvcConfig(SpringMVC配置类)
- 执行
@ComponentScan
加载对应的bean - 加载UserController,每个
@RequestMapping
的名称对应一个具体的方法 - 执行getServletMappings方法,定义所有的请求都通过SpringMVC
- 单次请求过程(返回json数据等)
- 发送请求localhost/save
- web容器发现所有请求都经过SpringMVC,将请求交给SpringMVC处理
- 解析请求路径 /save
- 由 /save 匹配执行对应的方法 save()
- 执行 save()
- 检测到有
@ResponseBody
直接将 save()方法的返回值作为响应请求体返回给请求方
工作流程
- DispatcherServlet表示前端控制器,是整个SpringMVC的控制中心。用户发出请求,DispatcherServlet接收请求并拦截请求。
- HanderMapping为处理器映射。DispatcherServlet调用HanderMapping,HanderMapping根据请求URL查找Hander(处理器)。
- 返回处理执行链,根据URL查找控制器,并且将解析后的信息转递给DispatcherServlet
- HandlerAdapter表示处理器适配器,其按照特定的规则去执行Handler。
- 执行handler找到具体的处理器
- Controller将具体的执行信息返回给HandlerAdapter,如ModuleAndView
- HandlerAdapter将视图逻辑名或模型传递给DispatcherServlet
- DispatcherServlet调用视图解析器(ViewResolver)来解析HandlerAdapter传递的逻辑名。
- 视图解析器将解析的逻辑视图名传给DispatcherServlet。
- DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图,进行渲染。
- 将响应数据返回给客户端。
简单版的流程
-
用户发出请求
-
由Tomcat接收到对应的请求
-
SpringMVC的DispatcherServlet(前端控制器)接收到所有请求
-
查看请求地址和
@RequestMapping
注解的哪个匹配,来找到具体的类的处理方法 -
前端控制器找到目标处理类和方法之后,执行目标方法
-
方法执行完毕之后会有一个返回值,SpringMVC会将这个返回值用视图解析器进行解析拼接成完整的页面地址
-
DispatcherServlet拿到页面地址之后,转发到具体的页面
2.1.4、Controller加载控制与业务bean加载控制
- SpringMVC相关bean(表现层bean)
- Spring控制的bean
- 业务bean(Service)
- 功能bean(DataSource等)
❓因为功能不同,如何避免Spring错误的加载到SpringMVC的bean?
解决方案:加载Spring控制的bean的时候排除掉SpringMVC控制的bean。
- SpringMVC相关bean加载控制
- SpringMVC加载的bean对应的包均在com.item.controller包内
- Spring相关bean加载控制
- 方式一:Spring加载的bean设定扫描范围为com.item,排除掉controller包内的bean
- 方式二:Spring加载的bean设定扫描范围为精准范围,例如service包,dao包等
- 方式三:不区分Spring与SpringMVC的环境,加载到同一个环境中
//方式一
@ComponentScan({"com.item.dao","com.item.service"})
//方式二
@ComponentScan(value = "com.item",
excludeFilters = @ComponentScan.Filter(
type = FilterType.ANNOTATION,
classes = Controller.class
)
)
注意:SpringMvcConfig和SpringConfig配置类在com.item.config包内
如果使用第二种方式排除,则必须将SpringMvcConfig类上的
@Configuration
注解去掉,因为方式二中只排除了Controller
注解但没有排除@Configuration
注解,并且@Configuration
注解是将类注册为配置类,所以会将SpringMvcConfig类中配置的@ComponentScan
路径进行扫描并进行注册bean。 解决方法:可以将SpringMvcConfig和SpringConfig配置类放到com包下或其他位置。
名称:
@ComponentScan
类型:类注解
- 范例:
@Configuration
//@ComponentScan({"com.item.dao","com.item.service"})
@ComponentScan(value = "com.item",
excludeFilters = @ComponentScan.Filter(
type = FilterType.ANNOTATION,
classes = Controller.class
)
)
public class SpringConfig {
}
属性:
- excludeFilters:排除扫描路径中的加载的bean,需要指定类别(type)与具体项(classes)
- includeFilters:加载指定的bean,需要指定类别(type)与具体项(classes)
2.2、基于XML的SpringMVC
- 使用IDEA创建空的Maven项目
- 要创建Web项目,添加web目录
右击项目名(springmvc01),找到Add Framework Support,找到WebApplication勾选即可,可选择版本。
- 配置Tomcat
点击右上角的 Add Configuration。
点击加号,找到Tomcat Server,点击Local,选择Deployment,点击加号,选择Artifacts。
选中添加的Artifacts,修改Application context,修改成项目名(从属性是访问的路径)。
如果遇到报错,可能是out下WEB-INF的lib没有SpringMVC相关jar包,导入即可。
点击File选择ProjectStructure,点击Artifacts的加号,选择Web Application:Exploded的FromModules即可。
选择WEB-INF文件右击创建文件夹,选中右边项目名下的所有jar包,右击选择Put into /WEB-INF/lib。再点击aplly。
2.2.1、添加依赖pom.xml
<!-- SpringMVC坐标 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
2.2.2、编写web.xml
<?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">
<!--配置DispatcherServlet
接收除了.jsp的请求都交给SpringMVC去处理
-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 初始化参数
contextConfigLocation 配置SpringMVC的xml配置文件,指定路径
也可以不配置:会自动去WEB-INF去找一个名字叫 [servlet-name]-servlet.xml(springmvc-servlet.xml)文件
-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<!-- 启动服务器时加载servlet
当web服务器启动时就会创建servlet(会自动调用servlet的构造函数及init()方法)
init()方法内加载springmvc配置文件
-->
<load-on-startup>1</load-on-startup>
</servlet>
<!-- 配置DispatcherServlet映射
通常会为SpringMVC映射的路径为:/*,/,*.do,*.action,/request/*
/:除了.jsp的请求都会被拦截
/*:所有请求都会被拦截
*.do,*.action:URL结尾以.do或.action的请求会拦截
-->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<!-- 配置拦截请求路径 -->
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
2.2.3、编写springmvc需要的配置文件,spring-mvc.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 https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.item"/>
</beans>
2.2.4、HelloController类
package com.item.controllers;
@Controller
public class HelloController {
/**
* @RequestMapping将方法映射给对应的URL请求处理
* @param name SpringMVC的自动匹配
* @return
*/
@RequestMapping("/Hello")
public String hello(String name){
System.out.println("hello SpringMVC:"+name);
/**
* 响应
* redirect:重定向
* forward:转发(默认)return "index.jsp";
*/
return "redirect:index.jsp";
}
}