文章目录
二、SpringMVC概述
- Spring MVC是由Spring官方提供的基于MVC设计理念的web框架
- Spring MVC是基于Servlet封装的用于实现MVC控制的框架,实现前端和服务端的交互。
2.1 SpringMVC优势
- 严格遵守了MVC分层思想
- 采用了松耦合、插件式结构;相比较于我们封装的BaseServlet以及其他的一些MVC框架来说更灵活、更具扩展性
- SpringMVC是基于Spring的扩展、提供了一套完善的MVC注解
- SpringMVC在数据绑定、视图解析都提供了多种处理方式,可灵活配置
- SpringMVC对RESTful URL设计方法提供了良好的支持
2.2 SpringMVC本质工作
- 接收并解析请求
- 处理请求
- 数据渲染、响应请求
三、SpringMVC框架部署
3.1 基于Maven创建一个Web工程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WNXhhZUP-1651847342866)(https://note.youdao.com/yws/public/resource/7d8c16ef13900aefaa5e948a417c2c48/xmlnote/110FEEB45EF04A49A19CAE0ED788034F/72)]
3.2 添加SpringMVC依赖
- spring-context
- spring-aspects
- spring-jdbc
- spring-web
- spring-webmvc
- spring-junit
<spring.version>5.2.13.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependencies/>
<?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>com.liguoqing</groupId>
<artifactId>springmvc-demo2</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<spring.version>5.2.13.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</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-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<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>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
</project>
3.3 创建SpringMVC配置文件
- 在resource目录下创建名为spring-servlet.xml 文件
- 添加MVC命名空间
spring-servlet.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"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:mvc="http://www.springframework.org/schema/mvc"
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 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 声明使用注解配置-->
context:annotation-config/ <!-- 声明Spring工厂注解的扫描范围-->
<context:component-scan base-package="com.liguoqing"/>
<!-- 声明mvc使用注解驱动-->
< mvc:annotation-driven/>?
</beans>
3.4 在web.xml中配置SpringMVC的前端控制器
SpringMVC提供了一个名为DispatcherServlet的类(SpringMVC前端控制器),用于拦截用户请求交由SpringMVC处理
webapp/WEB-INF/web.xml
1
<?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>
<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-servlet.xml</param-value>
</init-param>
<!-- 服务器启动时 创建DispatcherServlet 而不是第一次访问时创建-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping> <!-- /* 拦截所有的HTTP请求,包括.jsp的请求,都做为控制器类的请求路径来处理--> <!-- / 拦截所有的HTTP请求,但不包括.jsp的请求,但不会放行静态资源请求,html/js/css/图片-->
</web-app>
三、SpringMVC框架使用
3.1
在SpringMVC中,我们把接收用户请求,处理用户请求的类称之为Controller(控制器)
3.1.1 创建控制器
- 创建一个名为 com.liguoqing.controllers 的包(包需要在Spring注解扫描的范围内)
- 创建一个类(无需做任何的继承和实现)
- 在类上添加 @Controller 注解声明此类为SpringMVC的控制器
- 在类上添加 @RequestMapping(“/url”) 声明此控制器类的请求url
package com.liguoqing.controllers; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller @RequestMapping(“/book”) public class BookController { }
3.1.2 在控制器类中定义处理请求的方法
- 在一个控制器类中可以定义多个方法处理不同的请求
- 在每个方法上添加 @RequestMapping(“/url”) 用于声明当前方法请求的url
3.1.3 访问
- http://localhost:8081/springmvc_demo22_war_exploded/book/add
- http://localhost:8081/springmvc_demo22_war_exploded/book/list
3.2 静态资源配置
静态资源:就是项目中的HTML、CSS、JS、图片等
3.2.1 /* 和 / 区别
<!-- /* 拦截所有的HTTP请求,包括.jsp的请求,都做为控制器类的请求路径来处理--> <!-- / 拦截所有的HTTP请求,但不包括.jsp的请求,但不会放行静态资源请求(html/js/css/图片)-->
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
3.2.2 静态资源放行配置
- 在springMVC的配置文件中,添加如下静态资源放行的配置
spring-servlet.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"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:mvc="http://www.springframework.org/schema/mvc"
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 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 声明使用注解配置-->
context:annotation-config/
<!-- 声明Spring工厂注解的扫描范围-->
<context:component-scan base-package="com.liguoqing"/>
<!-- 声明mvc使用注解驱动--> mvc:annotation-driven/
------------------------------------------------ <!--放行资源-->
<mvc:resources mapping="/css/" location="/css/"/>
<mvc:resources mapping="/pages/" location="/pages/"/>
<mvc:resources mapping="/imgs/" location="/imgs/"/>
<mvc:resources mapping="/js/" location="/js/"/>
</beans>
------------------------------------------------ <!--放行资源-->
<mvc:resources mapping="/css/" location="/css/"/>
<mvc:resources mapping="/pages/" location="/pages/"/>
<mvc:resources mapping="/imgs/" location="/imgs/"/>
<mvc:resources mapping="/js/" location="/js/"/>
mvc:default-servlet-handler/
dispatcherservlet处理不了静态资源 处理会报错,报完错后给
defaultservlet处理 default-servlet-handler 静态资源
先交给dispatcherservlet处理然后交给defaultservlet
<!--当springmvc处理不了静态资源的时候才会启用 默认servlet-handler 来处理静态资源-->
<mvc:default-servlet-handler/>
要设置
<!-- 将注解功能启动-->
<mvc:annotation-driven/> 不开启这个注解驱动,所有的注解都会没有用,会默认被默认的servlet处理
3.3 前端提交数据到控制器
3.3.1 表单提交
表单提交:输入框需要提供name属性,springMVC控制器是通过name属性取值的
<%-- Created by IntelliJ IDEA. User: Administrator Date: 2022/1/15 Time: 21:33 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title></head>
<body><h3>添加图书</h3>
<form action="book/add" method="post"><p>图书名称:<input type="text"></p>
<p>图书作者:<input type="text"></p>
<p>图书价格:<input type="text"></p>
<p><input type="submit" value="提交"></p></form>
</body>
</html>
3.2.2 URL提交
URL提交:<a href="book/add?bookName=java">url提交<a/>
3.3.3 AJAX提交
AJAX提交:请求行、请求头、请求体都可以用来传值
<h3>AJAX提交</h3> <input type="button" value="ajax提交"/>
<script type="text/javascript" src="js/jquery-3.4.1.min.js"></script>
<script type="text/javascript"> $("#btn1").click(function () {
var obj = {};
obj.bookName = "Java";
obj.bookAuthor = "张三";
obj.bookPrice = 3.33;
$.ajax({
url: "book/add",
type: "post",
headers: {},
contentType: "application/json",
data: obj,
success: function (res) {
console.log(res);
}
});
}); </script>
3.3.4http协议
3.4 控制器中接收前端提交的数据
3.4.1 请求行传值
- 表单提交 method=“get”
- URL提交
- $.ajax请求的url传值
<h3>AJAX提交</h3> <input type="button" value="ajax提交"/>
<script type="text/javascript" src="js/jquery-3.4.1.min.js"></script>
<script type="text/javascript"> $("#btn1").click(function () {
var obj = {};
obj.bookName = "Java";
obj.bookAuthor = "张三";
obj.bookPrice = 3.33;
$.ajax({
url:这里拼接url,把参数放url就是请求行传值,
type:"post",
headers:{
},
contentType:"application/json",
data:obj,
success:function (res){
console.log(res);
}
});
}); </script>
- . p o s t ( ) / .post()/ .post()/.get() 中的{}传值
@RequestParam 注解用于接收请求行传递的数据
- 前端提交数据
<h3>表单提交</h3>
<form action="book/add" method="post"><p>图书名称:<input type="text" name="name"></p>
<p>图书作者:<input type="text" name="author"></p>
<p>图书价格:<input type="text" name="price"></p>
<p><input type="submit" value="提交"></p></form>
- 控制器接收数据
package com.liguoqing.controllers;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
@RequestMapping("/book")
public class BookController { // <form action="book/add" method="post"> // <p>图书名称:<input type="text" name="name"></p> // <p>图书作者:<input type="text" name="author"></p> // <p>图书价格:<input type="text" name="price"></p> // <p><input type="submit" value="提交"></p> // </form> /接收请求行数据/
@RequestMapping("/add")
public void add(@RequestParam("name") String a, @RequestParam("author") String b, @RequestParam("price") double c) {
System.out.println("~book add");
System.out.println(a);
System.out.println(b);
System.out.println(c);
}
}
注意:
如果控制器方法中接收数据的参数名与请求行传值的key是一致的,则@RequestParam注解可以省略
public static void main(String[]args){
@RequestMapping("/add")
public void add(String name,String author,double price){
System.out.println("~book add");
System.out.println(name);
System.out.println(author);
System.out.println(price);
}
}
3.4.2 请求头传值
- $.ajax 封装请求头数据
$.ajax({
url: "book/add",
type: "post",
headers: {这里请求头传值},
contentType: "application/json",
data: obj,
success: function (res) {
console.log(res);
}
});
演示代码:(这里的请求头里如果写中文暂时是有问题的)
@RequestHeader 用于接收请求头传递的数据
@RequestMapping("/list")
public void list(@RequestHeader("token") String token){
System.out.println(token);
System.out.println("~book list"); }
<h3>AJAX提交</h3> <input type="button" value="ajax提交" id="btn1"/>
<script type="text/javascript" src="js/jquery-3.4.1.min.js"></script>
<script type="text/javascript"> $("#btn1").click(function () {
console.log("进入方法");
var obj = {};
obj.bookName = "Java";
obj.bookAuthor = "张三";
obj.bookPrice = 3.33;
console.log("obj");
$.ajax({
url: "book/list",
type: "post",
headers: {token: "Eqeqeq"},
// contentType:"application/json",
// data:obj,
success:function (res){
console.log(res);
}
});
console.log("结束");
});
</script>
3.4.3 请求体传值
- $.ajax 封装请求体数据
$.ajax({
url:"book/add",
type:"post",
headers:{
这里请求头传值
},
contentType:"application/json",
data:{
这里放请求体数据
},
success:function (res){
console.log(res);
}
});
@RequestBody 注解用于接收请求体传递的数据
- 前端
<input type="button" value="ajax提交" id="btn1"/>
<script type="text/javascript" src="js/jquery-3.4.1.min.js"></script>
<script type="text/javascript"> $("#btn1").click(function () {
console.log("进入方法");
var obj = {};
obj.bookName = "pytone";
obj.bookAuthor = "woshinidie";
obj.bookPrice = 3.33;
console.log("obj");
$.ajax({
url: "book/update",
type: "post", // headers:{
// token:"Eqeqeq"
// },
contentType:"application/json",
data: JSON.stringify(obj), //data的值为json格式字符串,
contentType:"application/json"
success:function (res){
console.log(res);
}
});
console.log("结束");
});
</script>
@RequestBody 将前端请 求提交的JSON格式数据转换成java对象,依赖jackson包
- 导入jackson的依赖
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.0</version>
</dependency>
-
控制器
@RequestMapping("/update") public void update(@RequestBody Book book){ System.out.println("~~~~~book update"); try{ System.out.println(book); } catch (Exception e) { e.printStackTrace(); } } ---------------------------------- // @RequestMapping("/update") // public void update(HttpServletRequest request){ // System.out.println("~~~~~book update"); // try{ Servlet的处理方法: 使用request 的输入流接收请求体数据 // ServletInputStream is = request.getInputStream(); // StringBuffer stringBuffer = new StringBuffer(); // byte[] bs = new byte[100]; // int len = -1; // while ((len = is.read(bs)) != -1){ // String s = new String(bs,0,len); // stringBuffer.append(s); // } // System.out.println(stringBuffer.toString()); // // } catch (IOException e) { // e.printStackTrace(); // } // }
3.5 控制器响应前端请求
3.5.1 控制器响应同步请求
同步请求:form , 超链接
转发
@RequestMapping("/add")
public String add(@RequestParam("name") String a,
@RequestParam("author") String b,
@RequestParam("price") double c){
System.out.println("~~~~~book add");
System.out.println(a);
System.out.println(b);
System.out.println(c);
//如何挑战到指定的页面呢?
return "/tips.jsp";
}
重定向
@RequestMapping("/add")
public String add(@RequestParam("name") String a,
@RequestParam("author") String b,
@RequestParam("price") double c){
System.out.println("~~~~~book add");
System.out.println(a);
System.out.println(b);
System.out.println(c);
//如何挑战到指定的页面呢?
return "redirect:/tips.jsp";
}
转发
@RequestMapping("/add")
public ModelAndView add(@RequestParam("name") String a,
@RequestParam("author") String b,
@RequestParam("price") double c){
System.out.println("~~~~~book add");
System.out.println(a);
System.out.println(b);
System.out.println(c);
//如何挑战到指定的页面呢?
ModelAndView modelAndView = new ModelAndView("/tips.jsp");
return modelAndView;
}
重定向
@RequestMapping("/add")
public ModelAndView add(@RequestParam("name") String a,
@RequestParam("author") String b,
@RequestParam("price") double c){
System.out.println("~~~~~book add");
System.out.println(a);
System.out.println(b);
System.out.println(c);
//如何挑战到指定的页面呢?
ModelAndView modelAndView = new ModelAndView("redirect/tips.jsp");
return modelAndView;
}
3.5.2 控制器响应异步请求
SpringMVC处理ajax(页面不发生跳转的情况下发生的交互)
异步请求:ajax请求
使用response中的输出流进行响应
- 控制器方法的返回类型为void,因为不需要跳转
- 控制器方法添加HttpServletResponse response 参数
- 在方法中通过response 获取输出流,使用流响应ajax请求
<input type="button" value="ajax提交" id="btn1"/>
<script type="text/javascript" src="js/jquery-3.4.1.min.js"></script>
<script type="text/javascript">
$("#btn1").click(function () {
console.log("进入方法");
var obj = {};
obj.bookName = "pytone";
obj.bookAuthor = "woshinidie";
obj.bookPrice = 3.33;
console.log("obj");
$.ajax({
url: "book/update",
type: "post",
// headers:{
// token:"Eqeqeq"
// },
contentType:"application/json",
data: JSON.stringify(obj), //data的值为json格式字符串,
dateType:"json"//预设接收的数据类型 是json
success:function (res){
console.log(res);
}
});
console.log("结束");
});
</script>
@RequestMapping("/update")
public void update(@RequestBody Book book, HttpServletResponse response){
System.out.println("~~~~~book update");
try{
System.out.println(book);
//使用ObjectMapper将对象转换成json格式字符串
String s = new ObjectMapper().writeValueAsString(book);
response.setCharacterEncoding("utf-8");
response.setContentType("application/json");//定义一下方便前端进行解析
PrintWriter out = response.getWriter();
out.println();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
直接在控制器方法返回响应的对象
- 控制器方法的返回类型设置为响应给ajax请求的对象类型
- 在控制器方法前添加一个 @ResponseBody 注解,将返回的对象转换成JSON格式返回给ajax请求
- 如果一个控制器类中的所有方法都是响应ajax请求,则可以直接在控制器类前添加 @ResponseBody 注解
- 响应的内容是一个 json 数组
@RequestMapping("/update")
@ResponseBody
public List<Book> update(){
System.out.println("~~~~~book update");
ArrayList<Book> books = new ArrayList<Book>();
books.add(new Book(1,"我朝","嘿嘿",2.33));
books.add(new Book(2,"到店","顶顶",2.33));
return books;
}
3.5.3 控制器响应同步请求的数据传递
对于同步请求的转发响应,我们可以传递参数到转发的页面
- 返回类型为String:
//1:在控制器方法中定义一个Model类型的参数
//2:在return页面之前,向model中添加键值对,添加的键值对就会被传递到转发的页面
@RequestMapping("/add1")
public String add1(@RequestParam("name") String a,
@RequestParam("author") String b,
@RequestParam("price") double c,
Model model){
model.addAttribute("key1","value1");
model.addAttribute("key1",new Book(1,"Java","老张",2.33));
return "/tips.jsp";
}
//除了使用Model对象传值外还可以直接使用HttpServletRequest对象
@RequestMapping("/add1")
public String add1(@RequestParam("name") String a,
@RequestParam("author") String b,
@RequestParam("price") double c,
HttpServletRequest request){
request.addAttribute("key1","value1");
request.addAttribute("key1",new Book(1,"Java","老张",2.33));
return "/tips.jsp";
}
- 返回类型ModelAndView
@RequestMapping("/add2")
public ModelAndView add2(@RequestParam("name") String a,
@RequestParam("author") String b,
@RequestParam("price") double c){
System.out.println("~~~~~book add");
ModelAndView modelAndView = new ModelAndView("/tips.jsp");
modelAndView.addObject("key1","value");
modelAndView.addObject("key2",new Book(1,"Java","老张",2.35));
return modelAndView;
}
3.6 解决中文乱码问题
3.6.1 前端编码
- JSP页面
<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="utf-8" %>
- HTML页面
<meta charset="UTF-8">
3.6.2 服务器编码
- tomcat/conf/server.xml
<Connector port="8081" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8"/>
3.6.3 设置SpringMVC的编码方式
- 在web.xml中配置SpringMVC编码过滤器的编码方式
<filter>
<filter-name>EncodingFilter</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>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>EncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
四:SpringMVC的请求处理流程
4.1
SpringMVC 通过前端控制器(DispatcherServlet)拦截并处理用户请求的
4.2 SpringMVC的核心组件
-
DispatcherServlet 前端控制器,总控制器
-
作用:接收请求,协同各组件工作,响应请求
-
HandlerMapping 处理器映射
-
作用:负责根据用户请求的URL找到对应的Handler
可以自定义配置 SpirngMVC提供多个处理器映射的实现,可以根据需要进行配置
-
HandlerAdapter 处理器适配器
-
作用:根据HandlerMapping 解析用户请求后产生的调用链,通过适配器模式完成Handler的调用
-
Handler 处理器/控制器
-
由工程师根据业务的需求进行开发
作用:处理请求
-
ModelAndView 视图模型
-
作用:用于封装处理器返回的数据以及响应的视图
ModelAndView = Model + View
-
ViewResolver 视图解析器
-
作用:对ModelAndView进行解析
可以自定义配置 SpirngMVC提供多个视图解析器的实现,可以根据需要进行配置
-
View 视图
-
作用:完成数据渲染
4.3 处理器映射器
不同的处理器映射器对URL处理的方式也不相同,使用对应的处理器映射器之后,我们的前端请求规则也需要发生响应的变化
SpringMVC提供的处理器映射器:
1:BeanNameUrlHandlerMappering:根据控制器的Id访问控制器
2:SimpleUrlHandlerMapping 根据控制器配置的URL访问(默认)
配置处理器映射器:
- 在SpringMVC的配置文件中通过Bean标签声明处理器映射器
- 配置 BeanNameUrlHandlerMapping
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>
例子:
<bean id="bookController" class="com.qfdue.controller.BookController"></bean>
@Controller
//@RequestMapping("/book")
//默认时bookController
//<bean id="bookController"class="com.qfdue.controller.BookController"></bean>
public class BookController {
}
- 配置SimpleUrlHandlerMapping
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<!--这里也可以通过注解的方式在controller上进行配置@RequestMapping("/aaa")-->
<prop key="/aaa">bookController</prop>
<prop key="/bbb">studentController</prop>
</props>
</property>
</bean>
4.4 视图解析器
SpringMVC提供了多个视图解析器:
1:UrlBasedViewResolver
2:InternalResourceViewResolver
-
UrlBasedViewResolver 需要依赖 jstl 包
-
添加JSTL的依赖
pom.xml
<!-- https://mvnrepository.com/artifact/javax.servlet/jstl -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
- 配置视图解析器
spring-servlet.xml
<bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>
</bean>
- InternalResourceViewResolver(不需要添加jstl依赖)
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>
</bean>
五: 日期格式处理
5.1 在控制器中使用对象接收数据
- 前端 前端与后端的 属性和name(key)要相等
<form action="test/add" method="post">
<p>图书名称:<input type="text" name="bookId"></p>
<p>图书作者:<input type="text" name="bookName"></p>
<p>图书价格:<input type="text" name="bookPrice"></p>
<p>图书出版时间:<input type="text" name="publish"></p>
<p><input type="submit" value="提交"></p>
</form>
- 后端
package com.liguoqing.beans;
import java.util.Date;
public class Book {
private int bookId;
private String bookName;
private String bookAuthor;
private double bookPrice;
private Date publish;
public Book(int bookId, String bookName, String bookAuthor, double bookPrice) {
this.bookId = bookId;
this.bookName = bookName;
this.bookAuthor = bookAuthor;
this.bookPrice = bookPrice;
}
@Override
public String toString() {
return "Book{" +
"bookId=" + bookId +
", bookName='" + bookName + '\'' +
", bookAuthor='" + bookAuthor + '\'' +
", bookPrice=" + bookPrice +
", publish=" + publish +
'}';
}
public int getBookId() {
return bookId;
}
public void setBookId(int bookId) {
this.bookId = bookId;
}
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public String getBookAuthor() {
return bookAuthor;
}
public void setBookAuthor(String bookAuthor) {
this.bookAuthor = bookAuthor;
}
public double getBookPrice() {
return bookPrice;
}
public void setBookPrice(double bookPrice) {
this.bookPrice = bookPrice;
}
public Date getPublish() {
return publish;
}
public void setPublish(Date publish) {
this.publish = publish;
}
public Book(int bookId, String bookName, String bookAuthor, double bookPrice, Date publish) {
this.bookId = bookId;
this.bookName = bookName;
this.bookAuthor = bookAuthor;
this.bookPrice = bookPrice;
this.publish = publish;
}
public Book() {
}
}
--------------------------
package com.liguoqing.controllers;
import com.liguoqing.beans.Book;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.Date;
@Controller
@RequestMapping("/test")
public class TestController {
@RequestMapping("/add")
//表单提交的多个参数,在控制器方法中可以使用对象接收,
//但是提交的数据的key必须要与对象的属性一致
public String addBook(Book book){
System.out.println(book);
return "tips";
}
}
spring-servlet.xml:
-------
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>
</bean>
5.2 日期格式处理
如果前端需要输入日期数据,在控制器中转换成Date对象,SpringMVC要求前端输入的日期格式必须为yyyy/MM/DD
如果甲方要求日期格式必须为指定的格式,而这个指定格式SpringMVC不接受,该如何处理呢?
自定义日期转换器:
5.2.1 创建自定义日期转换器
package com.liguoqing.utils;
import org.springframework.core.convert.converter.Converter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/*
* 1:创建一个类实现Converter接口,泛型指定从什么类型转换为什么类型
* 2:实现Converter准换方法
* */
public class MyDateConverter implements Converter<String,Date> {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
public Date convert(String s) {
Date date = null;
try {
date = sdf.parse(s);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
}
5.2.2 配置自定义转换器
<?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"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 声明使用注解配置-->
<context:annotation-config/>
<!-- 声明Spring工厂注解的扫描范围-->
<context:component-scan base-package="com.liguoqing"/>
--------------------------------------------------------------------------------
<!-- 声明mvc使用注解驱动-->
<mvc:annotation-driven conversion-service="converterFactory"/>
------------------------------------------------------------------------
<!--放行资源-->
<mvc:resources mapping="/css/**" location="/css/"/>
<mvc:resources mapping="/pages/**" location="/pages/"/>
<mvc:resources mapping="/imgs/**" location="/imgs/"/>
<mvc:resources mapping="/js/**" location="/js/"/>
<!--HandlerMapping-->
<!-- <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>-->
<!-- <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">-->
<!-- <property name="mappings">-->
<!-- <props>-->
<!-- <prop key="/aaa">bookController</prop>-->
<!-- <prop key="/bbb">studentController</prop>-->
<!-- </props>-->
<!-- </property>-->
<!-- </bean>-->
<!-- <bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">-->
<!-- <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>-->
<!-- <property name="prefix" value="/"/>-->
<!-- <property name="suffix" value=".jsp"/>-->
<!-- </bean>-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>
</bean>
-----------------------------------------------------------
<!--自定义日期转换器-->
<bean id="converterFactory" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<set>
<!-- //这里可以配置多个-->
<bean class="com.liguoqing.utils.MyDateConverter"/>
</set>
</property>
</bean>
----------------------------------------------
</beans>
//自己定义一个转换类
//MyDateConverter.class
package com.liguoqing.utils;
import org.springframework.core.convert.converter.Converter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/*
* 1:创建一个类实现Converter接口,泛型指定从什么类型转换为什么类型
* 2:实现Converter准换方法
* */
public class MyDateConverter implements Converter<String,Date> {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
public Date convert(String s) {
Date date = null;
try {
date = sdf.parse(s);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
}
六:文件上传
6.1 SpringMVC框架部署
-
基于Maven创建web工程
-
添加SpringMVC所需的依赖
-
- Spring-context aspects jdbc test web webmvc jackson
-
创建SpringMVC配置文件
-
在web.xml中配置SpringMVC的前端控制器
-
在web.xml中配置SpringMVC的编码过滤器
-
配置静态资源处理策略
6.2 文件上传
案例:添加图书,同时提交图书的封面图片
6.2.1 前端提交文件
- 表单提交方式必须为post
- 表单 enctype属性 设置为 multipart/form-data
<form action="book/add" method="post" enctype="multipart/form-data">
<p>图书名称:<input type="text" name="bookName"></p>
<p>图书作者:<input type="text" name="bookAuthor"></p>
<p>图书价格:<input type="text" name="bookPrice"></p>
<p>图书封面:<input type="file" name="ImgFile"></p>
<p>提交:<input type="submit" name="提交"></p>
</form>
6.2.2 控制器接收数据和文件
SpringMVC处理上传文件需要借助CommonsMultipartResolver文件解析器
- 添加依赖:commons-io commons-fileupload
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
- 在spring-servlet.xml中配置文件解析器
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--一些属性,自己百度-->
<property name="maxUploadSize" value="10240000"/>
<property name="maxInMemorySize" value="10240"/>
<property name="defaultEncoding" value="utf-8"/>
</bean>
-
控制器接收文件
-
在处理文件上传的方法中定义一个 MultipartFile 类型的对象,就可以接收图片了
package com.liguoqing.controller;
import com.liguoqing.beans.Book;
import org.springframework.http.HttpRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
@Controller
@RequestMapping("/book")
public class BookController {
@RequestMapping("/add")
public String addBook(Book book, MultipartFile ImgFile, HttpServletRequest request) throws IOException {
System.out.println("~~~~addBook");
System.out.println(book);
System.out.println(ImgFile);
//ImgFile表示上传的图片
//1:截取上传文件的后缀名,生成新的文件名
String originalFilename = ImgFile.getOriginalFilename();
String ext = originalFilename.substring( originalFilename.lastIndexOf(".") );// .jpg
String filename = System.currentTimeMillis()+ext;
//2:获取imgs目录在服务器的路径
String dir = request.getServletContext().getRealPath("imgs");
String savePath = dir + "/" + filename;//存储路径(C:/asd/ad/asdf/img.jpg)
//3:保存文件
ImgFile.transferTo(new File(savePath));
//4:将图片的访问路径设置到对象
book.setBookImg("imgs/"+ filename);
//5:调用service保存book到数据库
return "/tips.jsp";
}
}
6.3 文件下载
6.3.1
@RequestMapping("/list")
@ResponseBody
public String[] listImgs(HttpServletRequest request){
//1:从imgs目录下获取所有的图片信息
String dir = request.getServletContext().getRealPath("imgs");
File imgDir = new File(dir);
String[] filenames = imgDir.list();
return filenames;
}
6.3.2 实现文件下载
七:同一异常处理
在我们的应用系统运行的过程中,可能由于运行环境,用户操作,资源不足等各方面的原因导致系统出现异常(HTTP状态异常、Java异常Exception);如果系统出现了异常,这些异常将会通过浏览器呈现给用户,而这种异常的显示是没有必要的,因此我们可以在服务器进行特定的处理——当系统出现异常之后,呈现给用户一个统一的,可读的提示页面。
7.1 HTTP异常状态统一处理
HTTP Status 404
- 创建一个用于异常提示的页面:404.jsp
- 在web.xml中进行配置
<error-page>
<error-code>404</error-code>
<location>/404.jsp</location>
</error-page>
7.2 Java代码异常的统一处理(其他异常)
7.2.1基于Servlet-api的处理
- 创建异常提示页面:err.jsp
- 在web.xml中进行配置
<error-page>
<exception-type>java.lang.NullPointerException</exception-type>
<location>/err.jsp</location>
</error-page>
- 使用异常处理类进行统一处理
八:拦截器
8.1 拦截器介绍
SpringMVC提供的拦截器就类似与Servlet-api中的过滤器,可以对控制器的请求进行拦截实现相关的预处理和后处理。
-
过滤器(web.xml知道你的存在,tomcat管理)
是Servlet规范的一部分,所有web项目都可以使用
过滤器在web.xml配置(可以使用注解),
能够拦截所有web请求
-
拦截器(dispatchservlet知道拦截器的存在,springMvc管理)
是SpringMVC框架的实现,只有在SpringMVC框架中才能使用
拦截器在SpringMVC配置文件进行配置,
不会拦截SpringMVC放行的资源(js/html/css…)
------------------------------------------------ <!--放行资源--> <mvc:resources mapping="/css/" location="/css/"/> <mvc:resources mapping="/pages/" location="/pages/"/> <mvc:resources mapping="/imgs/" location="/imgs/"/> <mvc:resources mapping="/js/" location="/js/"/>
8.2 自定义拦截器
8.2.1 创建拦截器
实现HandInteceptor接口 满足拥BookId key值才能被拦截器预处理
8.2.2 配置拦截器
8.3拦截器链
将多个拦截器按照一定的顺序构成一个拦截器链
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="com.qfdue.utils.MyInterceptor1"/>
<mvc:exclude-mapping path="/book/query"/>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="com.qfdue.utils.MyInterceptor2"/>
<mvc:exclude-mapping path="/book/query"/>
</mvc:interceptor>
</mvc:interceptors>
如何将有道云笔记搬运到本地
2.可能是格式刷
[外链图片转存中…(img-roIyE5zD-1651847342877)]
八:拦截器
8.1 拦截器介绍
SpringMVC提供的拦截器就类似与Servlet-api中的过滤器,可以对控制器的请求进行拦截实现相关的预处理和后处理。
[外链图片转存中…(img-XVDVy1wL-1651847342878)]
-
过滤器(web.xml知道你的存在,tomcat管理)
是Servlet规范的一部分,所有web项目都可以使用
过滤器在web.xml配置(可以使用注解),
能够拦截所有web请求
-
拦截器(dispatchservlet知道拦截器的存在,springMvc管理)
是SpringMVC框架的实现,只有在SpringMVC框架中才能使用
拦截器在SpringMVC配置文件进行配置,
不会拦截SpringMVC放行的资源(js/html/css…)
------------------------------------------------ <!--放行资源--> <mvc:resources mapping="/css/" location="/css/"/> <mvc:resources mapping="/pages/" location="/pages/"/> <mvc:resources mapping="/imgs/" location="/imgs/"/> <mvc:resources mapping="/js/" location="/js/"/>
8.2 自定义拦截器
[外链图片转存中…(img-47RvTUjn-1651847342880)]
8.2.1 创建拦截器
实现HandInteceptor接口 满足拥BookId key值才能被拦截器预处理
[外链图片转存中…(img-iIkNSwWC-1651847342881)]
8.2.2 配置拦截器
[外链图片转存中…(img-SgN5mGON-1651847342881)]
8.3拦截器链
将多个拦截器按照一定的顺序构成一个拦截器链
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="com.qfdue.utils.MyInterceptor1"/>
<mvc:exclude-mapping path="/book/query"/>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="com.qfdue.utils.MyInterceptor2"/>
<mvc:exclude-mapping path="/book/query"/>
</mvc:interceptor>
</mvc:interceptors>
[外链图片转存中…(img-Vor4LotI-1651847342882)]
如何将有道云笔记搬运到本地
[外链图片转存中…(img-Bw5bPlgp-1651847342890)]
2.可能是格式刷