Spring MVC概述
Spring MVC是由Spring官方提供的基于MVC设计理念的web框架。(相当于Servlet)
Spring MVC是基于Servlet封装的用于实现MVC控制的框架。实现前端与服务端的数据交互。
Spring MVC 与 Servlet 对比 优势
- 严格遵守了MVC分层思想
- 采用了松耦合,插件式结构,相比较于我们封装的BaseServlet以及其他的MVC框架来说,更灵活,更具扩展性。
- Spring MVC是基于Spring扩展、提供了一套完善的MVC注解
- Spring MVC在进行数据绑定、视图解析都提供了多种处理方式,可灵活配置
- Spring MVC 对RESTful,URL设计方法提供了良好的支持
Spring MVC 本质工作
- 接收并解析请求
- 处理请求
- 数据渲染,响应请求
Spring MVC框架部署
1、创建maven-web工程
2、添加依赖
- junit
- spring-context
- spring-aspect
- spring-jdbc
- spring-web
- spring-webmvc
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.12.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.2.12.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.12.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.2.12.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.12.RELEASE</version>
</dependency>
</dependencies>
3、创建Spring MVC配置文件
-
在resources目录下创建名为spring-servlet.xml的文件
-
添加MVC命名空间
-
<?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/> <context:component-scan base-package="com.ccl"/> <!-- 声明MVC使用注解驱动--> <mvc:annotation-driven/> </beans>
4、在web.xml中配置SpringMVC的前端控制器
SpringMVC中提供了一个名为DispatcherServlet类(SpringMVC中央处理器,也就是前端控制器) , 用于拦截用户请求交给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>
<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>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
静态资源配置
/* 与/ 的区别
/* 拦截所有的HTTP请求,包括.jsp的请求,将所有请求映射成对控制器类的请求路径来处理
/ 拦截所有的HTTP请求,但不包括.jsp请求,但不会放心静态资源请求,html,css,js,图片
静态资源放行配置
html,css,js,图片,字体等
<!-- 配置静态资源放行-->
<mvc:resources mapping="/css/**" location="/css/"/>
<mvc:resources mapping="/static/**" location="/static/"/>
<mvc:resources mapping="/imges/**" location="/imges/" />
Spring MVC框架使用
在SpringMVC中,我们把接收用户请求、处理用户请求的类称之为COntroller(控制器)
创建控制器
1、创建控制器类
-
创建一个名为com.ccl.controllers包(包需要在Spring注解扫描的范围内)
-
创建BookCOntroller(无需做任何继承和实现)
-
在类上添加@Controller注解,声明此类为SpringMVC的控制器
-
声明请求路径:@RequestMaapping("/url")声明此控制器类的请求url
-
@Controller @RequestMapping("/book") public class BookController { }
2、在控制器类中定义处理请求的方法
-
在一个控制器类中可以定义多个方法处理不同的请求
-
在每个方法上添加@RequestMapping(”url“)用于声明当前方法请求的url
-
类名前面的注解可以省略
-
@RequestMapping("/add") public void add(){ System.out.println("----BookAdd----"); } @RequestMapping("/list") public void list(){ System.out.println("----BookList----"); }
访问
- http://localhost:8080/Spring/book/add
- http://localhost:8080/Spring/book/list
前端提交数据到控制器类
创建前端页面jsp
-
book-add.jsp表单的action属性设置控制器类的url和对应方法的url的组合路径
-
<%-- Created by IntelliJ IDEA. User: 13749 Date: 2021/10/31 Time: 17:22 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>AddBook</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>
前端页面提交数据
表单提交
-
表单提交:输入框需要提供name属性,SpringMVC控制器通过name属性取值的
-
<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>
url提交
Ajax提交
-
Ajax提交:请求行、请求头、请求体都可以用来传值
-
<input type="button" value="提交" id="btn1"/><script type="text/javascript" src="js/jquery-3.2.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>
控制器接收前端提交的数据
请求行传值
- 表单提交
- URL提交
- $.ajax()请求的url传值
- . p o s t ( ) / .post()/ .post()/.get()中的{}传值
@RequestParam注解用于接收请求行传递的数据
- 前端提交数据
<form action="book/add" method="post"> <p>图书名称:<input type="text" name="bookName"/></p> <p>图书作者:<input type="text" name="bookAuthor"/></p> <p>图书价格:<input type="text" name="bookPrice"/></p> <p><input type="submit" value="提交"/></p></form>
- 控制器接收数据
@RequestMapping("/add")public void add(@RequestParam("bookName") String a , @RequestParam("bookAuthor") String b , @RequestParam("bookPrice") double c){ System.out.println("---BookAdding...."); System.out.println(a); System.out.println(b); System.out.println(c);}
如果控制器方法的参数名称与前端name相同则不用写@RequestParam注解
请求头传值
-
ajax封装请求头数据
-
$.ajax({ ... headers:{ }, .....})
@RequestHeader注解用于接收请求头接收的数据:
前端:
<h3>Ajax提交</h3> <input type="button" value="提交" id="btn1"/> <script type="text/javascript" src="js/jquery-3.2.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/list", type:"post", headers:{ token:"qwer" }, // contentType:"application/json", // data:obj, success:function (res){ console.log(res) } }) }); </script>
后端:
@RequestMapping("list")public void list(@RequestHeader("token") String token){ System.out.println("--BookListing...."); System.out.println(token);}
请求头、请求行传值可以同时接收
请求体传值
-
ajax封装请求体数据
-
$.ajax({ url:"book/update", type:"post", contentType:"application/json", data: s , success:function (res){ console.log(res) }
@RequestBody注解用于接收请求体传递的数据
@RequestBody 将前端请求提交的JSON格式数据转换成Java对象,依赖jackson包
前端
<script type="text/javascript"> $("#btn1").click(function (){ var obj = {}; obj.bookName = "Java"; obj.bookAuthor = "张三"; obj.bookPrice = 3.33; var s =JSON.stringify(obj); //将对象转换成JSON格式 console.log(s); $.ajax({ url:"book/update", type:"post", contentType:"application/json", data: s ,//如果data的值为json格式字符串,contentType必须设置为“application/JSON” success:function (res){ console.log(res) } }) });</script>
-
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.12.1</version></dependency>
-
控制器:
-
public void update (@RequestBody Book book){ System.out.println("----book update "); System.out.println(book); }
控制器响应前端请求
控制器响应同步请求
同步请求:form表单、超链接
-
处理同步请求的方法的返回类型定义为String或者为ModelAndVIew
-
返回类型为String:
-
请求转发
@RequestMapping("/add")public String add(@RequestParam("bookName") String a , @RequestParam("bookAuthor") String b , @RequestParam("bookPrice") double c){ System.out.println("---BookAdding...."); System.out.println(a); System.out.println(b); System.out.println(c); return "/tips.jsp";}
重定向
@RequestMapping("/add")public String add(@RequestParam("bookName") String a , @RequestParam("bookAuthor") String b , @RequestParam("bookPrice") double c){ System.out.println("---BookAdding...."); System.out.println(a); System.out.println(b); System.out.println(c); return "redirect:/tips.jsp";}
-
返回类型为ModelAndView:
-
请求转发
-
@RequestMapping("/add")public ModelAndView add(@RequestParam("bookName") String a , @RequestParam("bookAuthor") String b , @RequestParam("bookPrice") double c){ System.out.println("---BookAdding...."); 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("bookName") String a , @RequestParam("bookAuthor") String b , @RequestParam("bookPrice") double c){ System.out.println("---BookAdding...."); System.out.println(a); System.out.println(b); System.out.println(c); ModelAndView modelAndView = new ModelAndView("redirect:/tips.jsp"); return modelAndView;}
-
控制器响应异步请求
异步请求:ajax请求
-
第一种方式:使用response中的输出流进行响应(返回类型为void)
-
在方法中添加HttpServletResponse参数
-
在方法中通过response获取输出流,使用流进行响应
@RequestMapping("/update") public void update (@RequestBody Book book , HttpServletResponse response) throws IOException { System.out.println("----book update "); System.out.println(book); //使用ObjectMapper将对象转换成JSON格式字符串 String s = new ObjectMapper().writeValueAsString(book); response.setCharacterEncoding("utf-8"); PrintWriter out = response.getWriter(); out.flush(); out.close(); }
-
-
第二种方式:直接在控制器方法返回响应的对象
-
控制器返回方法的返回类型设置为响应给ajax请求的对象类型
-
在控制器方法前添加@ResponseBody注解,将返回的对象转换成JSON响应给ajax请求
-
@RequestMapping("/update")@ResponseBodypublic List<Book> update () { System.out.println("----book update "); List<Book> books = new ArrayList<Book>(); books.add(new Book(1,"java","张三",2.33)); books.add(new Book(2,"C++","李四",56.0)); for (Book book1 : books) { System.out.println(book1 ); } return books;}
-
控制器响应同步请求的数据传递
对于同步请求的转发响应,我们可以传递参数到转发的页面
-
返回类型为String:
-
1、在控制器方法中定义一个Model类型的参数
-
2、在return页面之前,想model中添加键值对,添加键值对就会被传递到转发的页面
@RequestMapping("/add2")public String add(String bookName,String bookAuthor,String bookPrice , Model model){ System.out.println("---BookAdding2...."); //相当于request对象 model.addAttribute("key1","value1"); model.addAttribute("key2",new Book(1,"java","张三",9.93)); return "/tips.jsp";}
-
除了使用Model传值之外,还可以使用HttpServletRequest对象
-
@RequestMapping("/add3")public String add3(String bookName,String bookAuthor,String bookPrice ,HttpServletRequest request){ System.out.println("---BookAdding2...."); //相当于request对象 request.setAttribute("key1","value1"); request.setAttribute("key2",new Book(1,"java","张三",9.93)); return "/tips.jsp";}
-
返回类型ModelAndView
-
@RequestMapping("/add4")public ModelAndView add3(String bookName,String bookAuthor,String bookPrice ){ System.out.println("---BookAdding2...."); ModelAndView modelAndView = new ModelAndView("/tips.jsp"); modelAndView.addObject("key","modelling1"); modelAndView.addObject("book",new Book(1,"C++","Mr.Cao",99.0)); return modelAndView;}
解决中文乱码问题
前端页面
-
jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" %>
-
html页面
<meta charset="UTF-8">
设置服务器编码
-
tomcat/conf/server.xml
-
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8" />
设置SpingMVC的编码方式
编码过滤器
-
在web.xml中配置SpringMVC编码过滤器
-
<!-- 编码过滤器--> <filter> <filter-name>EncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <!--设置编码格式为utf-8--> <init-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </init-param> <!-- 强制编码为utf-8--> <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>