SpringMVC概述
-
三层结构
-
概述
- SpringMVC 是一种基于 Java 的实现 MVC 模型的轻量级 Web 框架。
- SpringMVC 已经成为目前最主流的MVC框架之一,并且随着Spring3.0 的发布,全面超越 Struts2,成为最优秀的 MVC 框架。它通过一套注解,让一个简单的 Java 类成为处理请求 的控制器,而无须实现任何接口。同时它还支持 RESTful 编程风格的请求。
SpringMVC入门案例
-
开发步骤
- ①引入相关依赖
- ②编写web.xml
- 配置DispatcherServlet,加载spring-mvc.xml 。类似于ModelBaseServlet
- ③编写spring-mvc.xml
- 扫描注解
- 配置视图解析器。类似于ViewBaseServlet
- ④编写UserController
- ⑤代码测试
-
①引入相关依赖
<properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> <junit.version>4.13.2</junit.version> <lombok.version>1.18.22</lombok.version> <spring.version>5.3.13</spring.version> <logback.version>1.2.7</logback.version> <slf4j.version>1.7.32</slf4j.version> <servlet.version>4.0.1</servlet.version> </properties> <dependencies> <!--web start--> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>${servlet.version}</version> </dependency> <!--web end--> <!--logback start--> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>${logback.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <!--logback end--> <!--junit start--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> <!--junit end--> <!--lombok start--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>${lombok.version}</version> </dependency> <!--lombok end--> <!--spring start--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</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-webmvc</artifactId> <version>${spring.version}</version> </dependency> <!--spring end--> </dependencies>
-
②编写web.xml
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app> <!--类似于ModelBaseServlet--> <servlet> <servlet-name>mvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!--加载spring-mvc.xml--> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-mvc.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>mvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
-
③编写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.atguigu"></context:component-scan> <!--视图解析器,类似于ViewBaseServlet--> <bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver"> <property name="order" value="1"/> <property name="characterEncoding" value="UTF-8"/> <property name="templateEngine"> <bean class="org.thymeleaf.spring5.SpringTemplateEngine"> <property name="templateResolver"> <bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver"> <!--视图前缀--> <property name="prefix" value="/WEB-INF/templates/"/> <!--视图后缀--> <property name="suffix" value=".html"/> <property name="templateMode" value="HTML5"/> <property name="characterEncoding" value="UTF-8" /> </bean> </property> </bean> </property> </bean> </beans>
-
④编写UserController
@Controller public class UserController { @RequestMapping("/selectUserList") public ModelAndView selectUserList(){ List<User> userList = new ArrayList<>(); userList.add(new User(1,"陈磊","alei")); userList.add(new User(2,"土澳","tuAo")); //存储数据,并跳转页面 ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("userList",userList); modelAndView.setViewName("demo01"); return modelAndView; } }
-
⑤代码测试
SpringMVC的执行流程
-
执行流程
-
①浏览器发起请求(/framework25/selectUserList),给前端控制器DispatcherServlet
-
②前端控制器DispatcherServlet通过处理器映射器查询所有的处理器执行链
-
③处理器映射器返回处理器执行链
-
④前端控制器DispatcherServlet通过处理器适配找匹配的处理器
-
⑤如果找到了匹配的处理器,处理器Handler就开始处理请求
-
⑥处理器Handler返回响应(ModelAndView)给处理器适配器
-
⑦处理器适配器将响应(ModelAndView)返回给前端控制器
-
⑧前端控制器DispatcherServlet将响应(ModelAndView)交给视图解析器进行解析
-
⑨视图解析器将渲染完毕的页面文件返回给前端控制器
-
⑩前端控制器将渲染完毕的页面文件响应给浏览器展示
SpringMVC核心组件
- 核心组件
- DispatcherServlet : 前端控制器,负责调度其他组件
- HandlerMapping : 处理器映射器,负责获取处理器执行链
- HandlerAdapter:处理器适配器,负责给请求适配对应的处理器
- Handler:处理器,处理请求
- ViewResolver:视图解析器,处理视图(ModelAndView)
SpringMVC核心组件配置
-
概述
- SpringMVC默认已经对HandlerMapping、HandlerAdapter进行配置
-
代码实现
<!--处理器映射器--> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"></bean> <!--处理器适配器--> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"></bean>
<!--处理器映射器、处理器适配器,同时也配置一些其他的辅助组件:类型转换器等等--> <mvc:annotation-driven></mvc:annotation-driven>
静态资源放行
-
静态资源
- 图片、css、js、html、文本等等
-
方式一
<!--放行静态资源--> <!-- mapping: 访问路径 location: 磁盘路径 --> <mvc:resources mapping="/css/**" location="/css/"></mvc:resources> <mvc:resources mapping="/js/**" location="/js/"></mvc:resources> <mvc:resources mapping="/img/**" location="/img/"></mvc:resources>
-
方式二
<mvc:default-servlet-handler></mvc:default-servlet-handler>
@RequestMapping注解概述
-
概述
- Annotation for mapping web requests onto methods in request-handling classes with flexible method signatures.
- 用于将请求映射到处理器方法上。
-
常用属性
- path : 设置访问路径
- method : 设置请求方式
- params : 设置必须要携带的请求参数
-
作用
- ①设置处理器的访问路径
- ②窄化请求
- ③限定请求方式
-
代码实现
@RequestMapping(path = "/request/testRequestMapping" , params = "username") public ModelAndView testRequestMapping(){ ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName("index"); return modelAndView; }
@RequestMapping注解之访问路径
-
分类
- ①精确匹配
- ②模糊匹配
-
①精确匹配
-
②模糊匹配
/** * 模糊匹配 * @return */ @RequestMapping(path = "/myrequest/*") public ModelAndView testRequestMapping2(){ ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName("index"); return modelAndView; }
@RequestMapping注解之窄化请求
-
概述
- 将@RequestMapping注解应用在类上。
-
代码实现
@Controller @RequestMapping("/request") public class RequestController { }
@RequestMapping注解之请求方式
-
概述
- 常用请求方式为:get、post、put、delete
-
代码实现
/** * 处理GET * @return */ @RequestMapping(path = "/request/testRequestMapping3",method = RequestMethod.GET) public ModelAndView testRequestMapping3(){ ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName("index"); return modelAndView; } /** * 处理POST * @return */ @RequestMapping(path = "/request/testRequestMapping4",method = RequestMethod.POST) public ModelAndView testRequestMapping4(){ ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName("index"); return modelAndView; }
@GetMapping("/request/testRequestMapping3") public ModelAndView testRequestMapping3(){ ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName("index"); return modelAndView; } @PostMapping("/request/testRequestMapping4") public ModelAndView testRequestMapping4(){ ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName("index"); return modelAndView; }
请求参数绑定概述
- 概述
- 就是将页面上的请求参数绑定到java数据中。
- 分类
- 简单类型
- javabean
- 容器
- javabean包装类
- …
请求参数绑定之简单类型
-
代码实现
<form th:action="@{/request/testRequestParam1}" method="get"> 账户:<input type="text" name="userName" ><br> 密码:<input type="text" name="userPwd" ><br> <button type="submit">提交</button> </form>
@RequestMapping("/request/testRequestParam1") public ModelAndView testRequestParam1(String userName ,String userPwd){ System.out.println("userName = " + userName); System.out.println("userPwd = " + userPwd); ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName("index"); return modelAndView; }
view-controller标签
-
概述
- 当一个处理器只是用来转发页面的话,就可以使用View-Controller来代替。
-
代码实现
<mvc:view-controller path="/demo02.html" view-name="demo02"></mvc:view-controller> <mvc:view-controller path="/demo03.html" view-name="demo03"></mvc:view-controller>
@RequestParam注解
-
概述
- 把请求中的指定名称的参数值传递给控制器中的形参赋值
-
作用
- ①设置请求参数名称
- ②设置参数是否必需的参数
- ③设置参数的默认值
-
代码实现
@RequestMapping("/request/testRequestParam2") public ModelAndView testRequestParam2(@RequestParam(value = "username" ,required = true ,defaultValue = "missing") String userName ){ System.out.println("userName = " + userName); ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName("index"); return modelAndView; }
请求参数绑定之JavaBean
-
代码实现
<form th:action="@{/request/testRequestParam3}" method="get"> 账户:<input type="text" name="userName" ><br> 密码:<input type="text" name="userPwd" ><br> <button type="submit">提交</button> </form>
@RequestMapping("/request/testRequestParam3") public ModelAndView testRequestParam3(User user ){ System.out.println("user = " + user); ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName("index"); return modelAndView; }
-
注意事项
- form表单中的name属性值和setXxx方法名有关。
请求参数绑定之JavaBean包装类
-
概述
- 如果一个JavaBean类(对象A)中包含另外一个JavaBean类(对象B)
-
代码实现
public class UserWrapper { private User user; }
<form th:action="@{/request/testRequestParam4}" method="get"> 账户:<input type="text" name="user.userName" ><br> 密码:<input type="text" name="user.userPwd" ><br> <button type="submit">提交</button> </form>
@RequestMapping("/request/testRequestParam4") public ModelAndView testRequestParam4(UserWrapper userWrapper ){ System.out.println("userWrapper = " + userWrapper); ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName("index"); return modelAndView; }
请求参数中文乱码
-
回顾
- 在tomcat8.0,get请求没有中文参数乱码问题,post请求有中文参数乱码问题。
- 之前,可以通过自定义CharacterEncodingFitler来解决该问题。
- 在SpringMVC框架中有提供类似的过滤器用于解决中文参数乱码问题。
-
代码实现
<filter> <filter-name>encoding</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> </filter> <filter-mapping> <filter-name>encoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
请求参数绑定之容器
-
代码实现
<form th:action="@{/request/testRequestParam6}" method="post"> javase : <input type="checkbox" name="hobbys" value="javase"><br> javame : <input type="checkbox" name="hobbys" value="javame"><br> javaee : <input type="checkbox" name="hobbys" value="javaee"><br> <button type="submit">提交</button> </form>
@RequestMapping("/request/testRequestParam5") public ModelAndView testRequestParam5(String[] hobbys){ System.out.println(Arrays.toString(hobbys)); ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName("index"); return modelAndView; }
@RequestMapping("/request/testRequestParam6") public ModelAndView testRequestParam6(@RequestParam("hobbys") List<String> hobbys){ System.out.println(hobbys); ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName("index"); return modelAndView; }
请求参数绑定练习
-
环境准备
public class Student { private String stuName; private School school; private List<Subject> subjectList; private Subject[] subjectArray; private Map<String, Double> scores; }
public class School { private String schoolName; }
public class Subject { private String subjectName;//学科名称 }
-
代码实现
<form th:action="@{/request/testRequestParam7}" method="post"> 学生姓名: <input type="text" name="stuName"><br> 学校名称: <input type="text" name="school.schoolName"><br> 学科1名称[List类型]: <input type="text" name="subjectList[0].subjectName"><br> 学科2名称[List类型]: <input type="text" name="subjectList[1].subjectName"><br> 学科3名称[List类型]: <input type="text" name="subjectList[2].subjectName"><br> 学科1名称[数组类型]: <input type="text" name="subjectArray[0].subjectName"><br> 学科2名称[数组类型]: <input type="text" name="subjectArray[1].subjectName"><br> 学科3名称[数组类型]: <input type="text" name="subjectArray[2].subjectName"><br> 学科1分数: <input type="text" name="scores['javase']"><br> 学科2分数: <input type="text" name="scores['javame']"><br> 学科3分数: <input type="text" name="scores['javaee']"><br> <button type="submit">提交</button> </form>
@RequestMapping("/request/testRequestParam7") public ModelAndView testRequestParam7(Student student){ System.out.println(student); ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName("index"); return modelAndView; }
@RequestHeader注解
-
概述
- 通过这个注解获取请求消息头中的具体数据。
-
代码实现
@RequestMapping("/request/header") public ModelAndView getRequestHeader(@RequestHeader(value = "user-agent",defaultValue = "missing") String userAgent){ System.out.println(userAgent); ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName("index"); return modelAndView; }
@CookieValue注解
-
概述
- 获取当前请求中的 Cookie 数据
-
代码实现
@RequestMapping("/request/cookie") public ModelAndView getCookie(@CookieValue(name = "JSESSIONID",defaultValue = "missing") String JSESSIONID){ System.out.println(JSESSIONID); ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName("index"); return modelAndView; }
处理器返回ModelAndView
- 概述
- ModelAndView封装了数据和逻辑视图名称
处理器返回字符串
-
概述
- 一般情况下,就是逻辑视图名称
-
代码实现
@RequestMapping("/response/testResponseStr") public String testResponseStr(Model model) { List<User> userList = new ArrayList<>(); userList.add(new User(1, "陈磊", "alei")); userList.add(new User(2, "土澳", "tuAo")); model.addAttribute("userList", userList);//存储数据 return "demo01";//跳转逻辑视图 }
处理器返回值操作转发和重定向
-
概述
- 默认情况下,处理器只能在视图解析器设置的目录范围内进行页面的跳转;
- 如果想要跳到目录范围以外的资源,那么就需要用到前缀符号!!!
-
代码实现
/** * 转发到目录范围以外的资源 * * @return */ @RequestMapping("/response/forward") public String response2Forward() { return "forward:/mydemo01.html"; } /** * 重定向到目录范围以外的资源 * * @return */ @RequestMapping("/response/redirect") public String response2Redirect() { return "redirect:/mydemo01.html"; } /** * 重定向到具体的处理器 * @return */ @RequestMapping("/response/jump2Method") public String jump2Method(){ return "redirect:/response/testResponseStr"; }
-
注意事项
- 使用"redirect:"操作重定向时,MVC框架已经内置了项目的访问路径。
原生ServletAPI对象
- 原生Servlet对象
- HttpServletRequest
- HttpServletResponse
- HttpSession
- ServletContext
获取request和response对象
-
代码实现
@RequestMapping("/servlet/getRequestResponse") public String getRequestResponse(HttpServletRequest request , HttpServletResponse response){ System.out.println("request = " + request); System.out.println("response = " + response); return "index"; }
获取session对象
-
代码实现
@RequestMapping("/servlet/getSession") public String getSession(HttpServletRequest request){ System.out.println("session = " + request.getSession()); return "index"; } @RequestMapping("/servlet/getSession2") public String getSession2(HttpSession session){ System.out.println("session = " + session); return "index"; }
获取ServletContext对象
-
代码实现
@RequestMapping("/servlet/getServletContext") public String getServletContext(HttpServletRequest request){ System.out.println("servletContext = " + request.getServletContext()); return "index"; } @Autowired private ServletContext servletContext; @RequestMapping("/servlet/getServletContext2") public String getServletContext2(){ System.out.println("servletContext = " + servletContext); return "index"; }
象(掌握)
-
代码实现
@RequestMapping("/servlet/getSession") public String getSession(HttpServletRequest request){ System.out.println("session = " + request.getSession()); return "index"; } @RequestMapping("/servlet/getSession2") public String getSession2(HttpSession session){ System.out.println("session = " + session); return "index"; }
获取ServletContext对象
-
代码实现
@RequestMapping("/servlet/getServletContext") public String getServletContext(HttpServletRequest request){ System.out.println("servletContext = " + request.getServletContext()); return "index"; } @Autowired private ServletContext servletContext; @RequestMapping("/servlet/getServletContext2") public String getServletContext2(){ System.out.println("servletContext = " + servletContext); return "index"; }