文章目录
- 🚏 SpringMVC简介
- 🚏 SpringMVC 的第一个程序 Hello World
- 🚀 概括
- 🚄 创建Maven工程
- 🚌web.xml
- 🚒 创建请求控制器 注解
- 🚤 配置SpringMVC的配置文件(扫描组件、视图解析器) 扫描组件
- 🚬 SpringMVC的核心配置文件(可以直接复制剪贴使用)
- 🚬 SpringMVC.xml 配置 视图控制器view-controller
- 🚬 SpringMVC.xml 配置 开放对静态资源的访问(默认的Servlet)
- 🚬 SpringMVC.xml 配置 开启注解驱动
- 🚬 SpringMVC.xml 配置编码过滤器 CharacterEncodingFilter
- 🚬 SpringMVC.xml 配置编码过滤器 HiddenHttpMethodFilter(delect、put)
- 🚬 SpringMVC.xml 配置文件上传解析器,将上传的文件封装为MultipartFile
- 🚬 SpringMVC.xml 配置 拦截器
- 🚬 SpringMVC.xml 配置 异常处理器
- 🚗 测试访问Hello word
- 🚲 总结
😹 作者: gh-xiaohe
😻 gh-xiaohe的博客
😽 觉得博主文章写的不错的话,希望大家三连(✌关注,✌点赞,✌评论),多多支持一下!!!
🚏 SpringMVC简介
🚀 1、什么是MVC
MVC是一种软件架构的思想,将软件按照模型、视图、控制器来划分
M:Model,模型层,指工程中的JavaBean,作用是处理数据
JavaBean分为两类:
- 一类称为实体类Bean:专门存储业务数据的,如 Student、User 等
- 一类称为业务处理 Bean:指 Service 或 Dao 对象,专门用于处理业务逻辑和数据访问。
V:View,视图层,指工程中的html或jsp等页面,作用是与用户进行交互,展示数据
C:Controller,控制层,指工程中的servlet,作用是接收请求和响应浏览器
MVC的工作流程:
用户通过视图层发送请求到服务器,在服务器中请求被Controller接收,Controller调用相应的Model层处理请求,处理完毕将结果返回到Controller,Controller再根据请求处理的结果找到相应的View视图,渲染数据后最终响应给浏览器
🚄 2、什么是SpringMVC
SpringMVC是Spring的一个后续产品,是Spring的一个子项目
SpringMVC 是 Spring 为表述层开发提供的一整套完备的解决方案。在表述层框架历经 Strust、WebWork、Strust2 等诸多产品的历代更迭之后,目前业界普遍选择了 SpringMVC 作为 Java EE 项目表述层开发的首选方案。
注:三层架构分为表述层(或表示层)、业务逻辑层、数据访问层,表述层表示前台页面和后台servlet
🚒 3、SpringMVC的特点
- Spring 家族原生产品,与 IOC 容器等基础设施无缝对接
- 基于原生的Servlet,通过了功能强大的**前端控制器DispatcherServlet**,对请求和响应进行统一处理
- 表述层各细分领域需要解决的问题全方位覆盖,提供全面解决方案
- 代码清新简洁,大幅度提升开发效率
- 内部组件化程度高,可插拔式组件即插即用,想要什么功能配置相应组件即可
- 性能卓著,尤其适合现代大型、超大型互联网项目要求
🚤 4、MVC的工作流程
①用户用过视图层将请求发送到服务器,在服务器中请求被Controller接收
②Controller(调用相对应servlet处理业务逻辑,service在调用dao层来进行数据的操作 —> 将数据库访问的结果在 返回给 service 在返回到控制层 )调用响应的Model层处理请求,处理完毕将结果返回给Controller,Controller在根据请求处理的结果找到相应的Veiw视图,渲染数据后最终响应给浏览器
🚬 servlet
浏览器中以不同的方式来发送一个请求 ,超链接,form表单,发送一个请求,需要根据请求的地址,来找到相对应的servlet,在servlet中(servlet的声明周期 三个方法) 获取请求参数来调用 service 来处理 业务逻辑 service处理完业务逻辑后,返回一个结果。 比如查询操作 把数据放到指定的域对象中、或者说登录功能,需要把用户信息放到session中 处理数据后,根据结果,根据service处理业务逻辑之后的结果,来选择不同的方式,响应浏览器
🚬 springmvc 是基于servlet的:
在spring mvc,所以封装的,所封装的功能的servlet中,把我们处理请求的过程都进行了封装。
🚏 SpringMVC 的第一个程序 Hello World
🚀 概括
1.创建Maven工程 --> web工程 —> war包 依赖
2.web.xml
① 默认方式: ② 拓展方式:
a.前端控制器b.<init-param> 路径
<init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springMVC.xml</param-value> </init-param>
c.将初始化时间提前,不在第一次请求时生效
<load-on-startup>1</load-on-startup>
注解 + 扫描的方式
3.创建请求控制器(注解)
4.配置SpringMVC的配置文件(扫描)
5.测试访问 Hello World
①实现对首页的访问
②通过超链接跳转到制定页面
🚄 创建Maven工程
🚬 创建Maven工程
🚬 配置pom.xml
打包方式 war 包、依赖
<?xml version="1.0" encoding="UTF-8"?>
<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>org.example</groupId>
<artifactId>SpringMVC-demo1</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<!-- SpringMVC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.1</version>
</dependency>
<!-- 日志 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<!-- ServletAPI -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- Spring5和Thymeleaf整合包 -->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<version>3.0.12.RELEASE</version>
</dependency>
</dependencies>
</project>
🚭 依赖范围:在什么地方可以使用到当前的jar包
provided已被提供:当前的服务器中已经提供了servlet jar包
在此时把工程打成war包之后 这个 servlet的 jar包就不会 存在于当前打的 war 之后的 web-info 下的 lib中 这个jar包由服务器提供
🚬 变成web工程
如果:没有小蓝点,后面解决(应该存在小蓝点)
完成
🚌web.xml
🚬 前端控制器默认方式
此配置作用下,SpringMVC 的配置文件默认位于 WEB-INF 下,默认名称为 《servlet-name>-servlet.xml,例如,以下配置所对应 SpringMVC 的配置文件位于 WEB-INF 下,文件名为 springMVC-servlet.xml
<!-- 配置SpringMVC的前端控制器,对浏览器发送的请求统一进行处理 -->
<servlet>
<servlet-name>springMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>springMVC</servlet-name>
<!--
设置springMVC的核心控制器所能处理的请求的请求路径
/所匹配的请求可以是/login或.html或.js或.css方式的请求路径
但是/不能匹配.jsp请求路径的请求
-->
<url-pattern>/</url-pattern>
</servlet-mapping>
🚬 前端控制器DispatcherServlet拓展方式(推荐)
可通过 init-param 标签设置 SpringMVC 配置文件的位置和名称,通过 load-on-startup 标签设置 SpringMVC 前端控制器 DispatcherServlet 的初始化时间
<!-- 配置SpringMVC的前端控制器,对浏览器发送的请求统一进行处理 -->
<servlet>
<servlet-name>springMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 通过初始化参数指定SpringMVC配置文件的位置和名称 -->
<init-param>
<!-- contextConfigLocation为固定值 -->
<param-name>contextConfigLocation</param-name>
<!-- 使用classpath:表示从类路径查找配置文件,例如maven工程中的src/main/resources -->
<param-value>classpath:springMVC.xml</param-value>
</init-param>
<!--
作为框架的核心组件,在启动过程中有大量的初始化操作要做
而这些操作放在第一次请求时才执行会严重影响访问速度
因此需要通过此标签将启动控制DispatcherServlet的初始化时间提前到服务器启动时
-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springMVC</servlet-name>
<!--
设置springMVC的核心控制器所能处理的请求的请求路径
/所匹配的请求可以是/login或.html或.js或.css方式的请求路径
但是/不能匹配.jsp请求路径的请求
-->
<url-pattern>/</url-pattern>
</servlet-mapping>
注解 + 扫描组件的方式
🚒 创建请求控制器 注解
创建一个控制类 (HelloController) 并声明控制层注解 @Controller
一个类标识为IOC容器的注解有四个
@Compoment --> 普通组件
@Controller --> 控制层组件
@Server --> 业务层组件
@Repository --> 持久层组件
@Controller
public class HelloController {
}
由于前端控制器对浏览器发送的请求进行了统一的处理,但是具体的请求有不同的处理过程,因此需要创建处理具体请求的类,即请求控制器
请求控制器中每一个处理请求的方法成为控制器方法
因为 SpringMVC 的控制器由一个 POJO(普通的 Java 类)担任,因此需要通过 @Controller 注解将其标识为一个控制层组件,交给 Spring 的 IoC 容器管理,此时 SpringMVC 才能够识别控制器的存在
🚤 配置SpringMVC的配置文件(扫描组件、视图解析器) 扫描组件
xml (可以直接复制剪贴使用)
🚬 SpringMVC的核心配置文件(可以直接复制剪贴使用)
<!--扫描控制层组件-->
<context:component-scan base-package="com.atguigu.mvc.controller"></context:component-scan>
<!-- 配置Thymeleaf视图解析器 -->
<bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
<!--设置视图解析器的优先级-->
<property name="order" value="1"/>
<!--解析视图时使用的编码-->
<property name="characterEncoding" value="UTF-8"/>
<!--模板引擎-->
<property name="templateEngine">
<!--内部 bean 来对 templateEngine 属性赋值 -->
<bean class="org.thymeleaf.spring5.SpringTemplateEngine">
<!--模板解析器-->
<property name="templateResolver">
<!--此内部bean是解析当前视图的一个策略-->
<!--spring的资源模板解析器-->
<bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
<!-- 视图前缀 -->
<property name="prefix" value="/WEB-INF/templates/"/>
<!-- 视图后缀 -->
<property name="suffix" value=".html"/>
<!--模板的模型 HTML5 -->
<property name="templateMode" value="HTML5"/>
<!--页面中的编码 UTF-8-->
<property name="characterEncoding" value="UTF-8" />
</bean>
</property>
</bean>
</property>
</bean>
想要跳转到index.html 是不可以的
why? WEB-INF 下面的内容 通过浏览器是不是直接访问的、通过重定向也是不可以直接访问的 只能通过转发来进行访问
通过视图解析器,来解析我们当前的视图
🚭 SpringMVC.xml 配置JSP的视图解析器
<!--jsp视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/templates/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
🚬 SpringMVC.xml 配置 视图控制器view-controller
当控制器方法中,仅仅用来实现页面跳转,即只需要设置视图名称时,可以将处理器方法使用view-controller标签进行表示
@RequestMapping("/")
public String index() {
return "index";
}
@RequestMapping("/test_view")
public String testView() {
return "test_view";
}
可以书写成
<!--视图控制器-->
<!--
path:设置处理的请求地址
view-name:设置请求地址所对应的视图名称
-->
<mvc:view-controller path="/" view-name="index"></mvc:view-controller>
<mvc:view-controller path="/test_view" view-name="test_view"></mvc:view-controller>
<!--开启mvc的注解驱动-->
<mvc:annotation-driven />
🚬 SpringMVC.xml 配置 开放对静态资源的访问(默认的Servlet)
<!--开放对静态资源的访问-->
<!--
处理静态资源,例如html、js、css、jpg
若只设置该标签,则只能访问静态资源,其他请求则无法访问
此时必须设置<mvc:annotation-driven/>解决问题
-->
<mvc:default-servlet-handler/>
注:
当SpringMVC中设置任何一个view-controller时,其他控制器中的请求映射将全部失效,此时需要在SpringMVC的核心配置文件中设置开启mvc注解驱动的标签:
🚬 SpringMVC.xml 配置 开启注解驱动
<!-- 开启mvc注解驱动 -->
<mvc:annotation-driven>
<mvc:message-converters>
<!-- 处理响应中文内容乱码 -->
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="defaultCharset" value="UTF-8" />
<property name="supportedMediaTypes">
<list>
<value>text/html</value>
<value>application/json</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
🚬 SpringMVC.xml 配置编码过滤器 CharacterEncodingFilter
<!--配置springMVC的编码过滤器-->
<!--一定要配置到其他过滤器之前,否则无效-->
<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>forceResponseEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
注意:
①SpringMVC中处理编码的过滤器一定要配置到其他过滤器之前,否则无效
②设置请求编码的前提条件:如果在此之前已将获取了某一个请求参数,所设置的编码没有效果
🚬 SpringMVC.xml 配置编码过滤器 HiddenHttpMethodFilter(delect、put)
使用put delect 请求 HiddenHttpMethodFilter 隐藏的http的请求方式
<!--配置处理请求方式put和delete的HiddenHttpMethodFilter-->
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
注意:
有多个过滤器时,过滤器的执行顺序有决定,配置的越靠前,就先执行
目前为止,SpringMVC中提供了两个过滤器:CharacterEncodingFilter和HiddenHttpMethodFilter在web.xml中注册时,必须先注册CharacterEncodingFilter,再注册HiddenHttpMethodFilter
原因:
在 CharacterEncodingFilter 中通过 request.setCharacterEncoding(encoding) 方法设置字符集的
request.setCharacterEncoding(encoding) 方法要求前面不能有任何获取请求参数的操作
而 HiddenHttpMethodFilter 恰恰有一个获取请求方式的操作:
String paramValue = request.getParameter(this.methodParam);
🚬 SpringMVC.xml 配置文件上传解析器,将上传的文件封装为MultipartFile
依赖
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<!--配置文件上传解析器,将上传的文件封装为MultipartFile-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"></bean>
🚬 SpringMVC.xml 配置 拦截器
<!--配置方式一: bean-->
<mvc:interceptors>
<!--所写的拦截器 路径-->
<!--一个bean就是IOC的组件(对象) 表示某一个类型的对象就是一个拦截器-->
<bean class="com.atguigu.interceptor.FirstInterceptor"></bean>
</mvc:interceptors>
<!--配置方式二: ref-->
<!--ref引用IOC容器中的某个bean的id,引用某一个拦截器的id-->
<mvc:interceptors>
<!--所写的拦截器 类名 需要使用普通组件注解@Component 表示为IOC容器 + 扫描 -->
<ref bean="firstInterceptor"></ref>
</mvc:interceptors>
<!-- 以上两种配置方式都是对DispatcherServlet所处理的所有的请求进行拦截,没有办法设置拦截规则 -->
<!--配置方式三:--> (推荐)
<mvc:interceptors>
<mvc:interceptor>
<!--需要拦截的请求-->
<mvc:mapping path="/**"/>
<!--需要排除的请求,即不需要拦截的请求-->
<mvc:exclude-mapping path="/testRequestEntity"/>
<!--和上面的两种写法一样 bean 或者 ref-->
<ref bean="firstInterceptor"></ref>
</mvc:interceptor>
</mvc:interceptors>
<!--
以上配置方式可以通过ref或bean标签设置拦截器,通过mvc:mapping设置需要拦截的请求,通过mvc:exclude-mapping设置需要排除的请求,即不需要拦截的请求
-->
🚭 / 和 /* 和 /** 的区别
- / :拦截所有请求 包括静态资源和动态请求 但是不拦截jsp
- /*:拦截所有请求所有的文件夹,但是不包括子文件夹 包括静态资源和动态请求 也拦截jsp
- /**:的意思是所有文件夹及里面的子文件夹
🚬 SpringMVC.xml 配置 异常处理器
🚭 方式一:配置文件
<!--配置异常处理-->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<!--异常映射-->
<property name="exceptionMappings">
<props>
<!--
key properties的键表示处理器方法执行过程中出现的异常
error properties的值表示若出现指定异常时,设置一个新的视图名称,跳转到指定页面
-->
<prop key="java.lang.ArithmeticException">error</prop>
</props>
</property>
<!--exceptionAttribute属性设置一个属性名,将出现的异常信息在请求域中进行共享-->
<property name="exceptionAttribute" value="ex"></property>
</bean>
🚭 方式二:注解
//@ControllerAdvice将当前类标识为异常处理的组件
@ControllerAdvice
public class ExceptionController {
//@ExceptionHandler用于设置所标识方法处理的异常
@ExceptionHandler(value = {ArithmeticException.class, NullPointerException.class})
//ex表示当前请求处理中出现的异常对象
public String handleArithmeticException(Exception ex, Model model){
model.addAttribute("ex", ex);
return "error";
}
}
🚗 测试访问Hello word
🚬 ①实现对首页访问
🚭 controller
@Controller
public class HelloController {
// 通过@RequestMapping注解,可以通过请求路径匹配要处理的具体的请求
// /表示的当前工程的上下文路径
@RequestMapping("/")
public String index(){
return "index";
// -> WEB-INF\templates\index.html
// -> 去掉前缀WEB-INF\templates
// -> 去掉后缀.html
}
}
🚭 index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<h1>首页</h1>
</body>
</html>
🚬 ②通过超链接跳转到指定的页面
🚭 在主页 index.html 中设置超链接
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8" />
<title>首页</title>
</head>
<body>
<h1>首页</h1>
<a th:href="@{/hello}">HelloWorld</a><br />
</body>
</html>
🚭 在 templates 下创建第二个 html 页面名为 target
在里面写入:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8" />
<title>Title</title>
</head>
<body>
HelloWorld
</body>
</html>
🚭 在请求控制器中创建处理请求的方法
@RequestMapping("/hello")
public String HelloWorld() {
return "target";
}
🚲 总结
①浏览器发送请求,若请求地址符合前端控制器的 url-pattern
②该请求就会被前端控制器 DispatcherServlet 处理。
③前端控制器会读取 SpringMVC 的核心配置文件,通过扫描组件找到控制器
④将请求地址和控制器中 @RequestMapping 注解的 value 属性值进行匹配,
⑤若匹配成功,该注解所标识的控制器方法就是处理请求的方法。
⑥处理请求的方法需要返回一个字符串类型的视图名称,该视图名称会被视图解析器解析,加上前缀和后缀组成视图的路径
⑦通过 Thymeleaf 对视图进行渲染,
⑧最终转发到视图所对应页面。