SpringMVC-01
1. 什么是SpringMVC?
Spring MVC是Spring提供的一个实现了Web MVC设计模式的轻量级Web框架。它与Struts2框架一样,都属于MVC框架,但其使用和性能等方面比Struts2更加优异。
springmvc 封装了serlvlet,实现的功能和BaseServlet类似,所有的路径分发都是经过DispatcherServlet
Spring MVC具有以下特点:
- 是Spring框架的一部分,可以方便的利用Spring所提供的其他功能。
- 灵活性强,易于与其他框架集成。
- 提供了一个前端控制器DispatcherServlet,使开发人员无需额外开发控制器对象。
- 可自动绑定用户输入,并能正确的转换数据类型。
- 内置了常见的校验器,可以校验用户输入。如果校验不能通过,那么就会重定向到输入表单。
- 支持国际化。可以根据用户区域显示多国语言。
- 支持多种视图技术。它支持JSP、Velocity和FreeMarker等视图技术。
- 使用基于XML的配置文件,在编辑后,不需要重新编译应用程序。
2.创建springmvc javaweb工程
2.1创建maven-web 工程并引入依赖
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<!--在当前pom 或者父类pom 中声明属性 -->
<spirng.version>5.0.16.RELEASE</spirng.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!-- 添加 servlet 依赖 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spirng.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spirng.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.6.12</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spirng.version}</version>
</dependency>
</dependencies>
2.2创建java,resource文件夹,并标注
2.3配置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>
<display-name>Archetype Created Web Application</display-name>
<!-- 声明 前端控制器 tomcat启动时 加载DispatcherServlet -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 为前端控制器 配置文件(spring)-->
<init-param>
<param-name>contextConfigLocation</param-name>
<!--
配置文件名可以为 servlet-name + ‘-’+servlet.xml 名字
此时使规范的名字,可以不用明确声明 初始化配置文件 可以不写出事参数contextConfigLocation
如果不规范 必须写明 要求 规范 + 明写
-->
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<!--
localhost:8080/工程名/User/findUserById?id=1
/ 就是tomcat会根据 前端请求的路径 去访问相应的servlet 或者 资源文件 如果找到就访问,找不到就访问当前的 springmvc 对应的servlet
找不到对应的路径的 servlet 时才匹配 现在 / springmvc的servlet
-->
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
2.4创建配置文件springmvc-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: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 https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 开启包扫描器-->
<context:component-scan base-package="com.yth"></context:component-scan>
<!-- 开启 注解的控制器@Controller -->
<mvc:annotation-driven></mvc:annotation-driven>
<!-- 声明 helloController
为当前的HelloController 控制类配置 路径
控制器 控制界面的跳转 返回前端数据 等同于servlet
name 1.是在容器种 bean 的标识 name 还是一个url 路径 /helloController
-->
<bean class="com.yth.controller.HelloController" name="/helloController"></bean>
<!-- 以下三个 bean 我们不明写入容器 则容器将以下类型的bean自动加入到容器中-->
<!--
声明在容器种加入 处理器映射器: DispatcherServlet可以根据url 找到对应的处理
就是一个map key 就是url value 就是处理器
/HelloController HelloController.handleRequest 处理器
"/HiController//hi public ModelAndView hi() 处理器
url 组成是由 控制器路径 + 处理器路径
-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>
<!-- 处理器适配器
充手机的插排 就是适配器 解决的是 充电接口不匹配
ControllerHandlerAdapter 根据不同类型的处理器 选择调用处理器
插排 可以驱动 手机两插口 也可以驱动 电脑三插口
-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean>
<!-- 视图解析器 将处理器返回的 ModelAndView 进行解析 渲染视图 转换为html网页
找到对应 jsp ,并将数据给到 jsp -->
<bean class="org.springframework.web.servlet.view.InternalResorceViewResolver"></bean>
</beans>
2.5创建控制类
package com.yth.controller;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 创建一个类 实现 Controller 中的方法 handleRequest
* @author yth
* @date 2020/10/22 - 14:31
*/
public class HelloController implements Controller {
@Override// 处理器 处理前端请求的数据
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
// ModelAndView 封装了 数据 和 视图(jsp 的路径)
ModelAndView modelAndView = new ModelAndView();
// 设置视图路径 jsp 路径
modelAndView.setViewName("/jsp/hello.jsp");
//等价于 向 request 中写入属性
modelAndView.addObject("msg","你好");
// 返回数据 和 视图 的一个封装
return modelAndView;
}
}
2.6在web目录侠创建/jsp/hello.jsp
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2020/10/22
Time: 14:35
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>hello springmvc</h1>
<h3>${msg}</h3>
</body>
</html>
2.7开启tomcat,测试
3.SpringMVC执行流程
1、用户发送请求至前端控制器DispatcherServlet。
2、DispatcherServlet收到请求调用HandlerMapping处理器映射器。
3、处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
4、 DispatcherServlet调用HandlerAdapter处理器适配器。
5、HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
6、Controller执行完成返回ModelAndView。
7、HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
8、DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
9、ViewReslover解析后返回具体View.
10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
11、DispatcherServlet响应用户。
4.SpringMVC核心类和注解
4.1DispatcherServlet
DispatcherServlet的全名是org.springframework.web.servlet.DispatcherServlet,它在程序中充当着前端控制器的角色。作用就是分发url,找到对应控制器,去处理对应的请求,当前前端访问的路径找不到对的servlet 的路径时,就去DispatcherServlet 配置的路径下去找
http://localhost:8080/HelloController
1.首先找/HelloController Servelt 没有
2.进入DispatcherServlet ,根据/HelloController 去找对应的 处理器
3.找到处理器HelloController的handleRequest 实现 Controller
5.调用 HelloController 中的handleRequest 去处理前端的请求
在使用时,只需将其配置在项目的web.xml文件中,其配置代码如下:
<!-- 声明 前端控制器 tomcat启动时 加载DispatcherServlet -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 为前端控制器 配置文件(spring)-->
<init-param>
<param-name>contextConfigLocation</param-name>
<!--
配置文件名可以为 servlet-name + ‘-’+servlet.xml 名字
此时使规范的名字,可以不用明确声明 初始化配置文件 可以不写出事参数contextConfigLocation
如果不规范 必须写明 要求 规范 + 明写
-->
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<!--
localhost:8080/工程名/User/findUserById?id=1
/ 就是tomcat会根据 前端请求的路径 去访问相应的servlet 或者 资源文件 如果找到就访问,找不到就访问当前的 springmvc 对应的servlet
找不到对应的路径的 servlet 时才匹配 现在 / springmvc的servlet
-->
<url-pattern>/</url-pattern>
</servlet-mapping>
4.2@Controller注解
org.springframework.stereotype.Controller注解类型用于指示Spring类的实例是一个控制器,其注解形式为@Controller。该注解在使用时不需要再实现Controller接口,只需要将@Controller注解加入到控制器类上,然后通过Spring的扫描机制找到标注了该注解的控制器即可。
1.将当前对象标记加入到容器
2.标记当前类是一个控制器
@Controller
public class FirstController {
@RequestMapping(value = "/first",method = RequestMethod.GET)
public ModelAndView first(){
// 数据 和 view 的封装
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("msg","first");
modelAndView.setViewName("jsp/hello.jsp");
return modelAndView;
}
}
注意扫描必须配置
<!--
使用注解开发springmvc web
-->
<!--开启包扫描器 让contrller生成 bean -->
<context:component-scan base-package="com.wgz.spring.controller"/>
<!--开启 url注解 绑定 handler 和 url -->
<mvc:annotation-driven />
<mvc:annotation-driven />主要做用
启用后,Spring会默认帮我们注册处理请求,参数和返回值的类。,其中最主要的两个类:DefaultAnnotationHandlerMapping 和 AnnotationMethodHandlerAdapter
4.3@RequestMapping
可以标记方法上,也标记在类上 当时都是控制器内(需要和@Controller)
标记在类上面:
为当前控制器配置路径,控制下面所有处理器 的url 都要加上当前 控制器路径
@Controller // 标记当前类是一个控制 @RequestMapping("/HiController") public class HiController {
标记在方法:将当前方法作为为处理以 key:value形式放置到处理器映射其中
// key: 控制器路径 + 处理器路径 :/HiController//hi // value: 当前处理器 方法
package com.yth.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
/**
* @author yth
* @date 2020/10/22 - 17:07
*/
@Controller
@RequestMapping("/HiController")
public class HiController {
@RequestMapping("/hi")
public ModelAndView hi(){
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("/jsp/hello.jsp");
modelAndView.addObject("msg","你好");
return modelAndView;
}
//(path = {"hi1","hi2"} 一个处理器可以配置多个路径
//method = RequestMethod.POST 标记当前处理器 只处理 post 请求
//浏览器浏览则报405请求方法错误
@RequestMapping(path = {"hi1","hi2"},method = RequestMethod.POST)
public ModelAndView he(){
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("/jsp/hello.jsp");
modelAndView.addObject("msg","你好");
return modelAndView;
}
}
4.4组合注解
Spring框架的4.3版本中,引入了新的组合注解,来帮助简化常用的HTTP方法的映射,并更好的表达被注解方法的语义。
- @GetMapping:匹配GET方式的请求;
- @PostMapping:匹配POST方式的请求;
- @PutMapping:匹配PUT方式的请求;
- @DeleteMapping:匹配DELETE方式的请求;
- @PatchMapping:匹配PATCH方式的请求。
package com.yth.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
/**
* @author yth
* @date 2020/10/22 - 19:15
*/
@Controller
@RequestMapping("/FirstController")
public class FirstController {
// 当前方法只让 get 访问
// @RequestMapping(value = "/first",method = RequestMethod.GET)
@GetMapping("/first1") // 等价于 @RequestMapping(value = "/first",method = RequestMethod.GET)
public ModelAndView h1(){
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("/jsp/hello.jsp");
modelAndView.addObject("msg","你好");
return modelAndView;
}
// 只接受 post 方式
// @RequestMapping(value = "/first2",method = RequestMethod.POST)
@PostMapping("/first2") // 等价于 @RequestMapping(value = "/first2",method = RequestMethod.POST)
public ModelAndView h2(){
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("/jsp/hello.jsp");
modelAndView.addObject("msg","你好");
return modelAndView;
}
}
4.5请求处理方法自带的参数和返回类型
在控制器类中,每一个请求处理方法都可以有多个不同类型的参数,以及一个多种类型的返回结果。在请求处理方法中,可以出现的参数类型如下:
javax.servlet.ServletRequest javax.servlet.http.HttpServletRequest
javax.servlet.ServletResponse javax.servlet.http.HttpServletResponse
javax.servlet.http.HttpSession java.util.Map
org.springframework.ui.Model org.springframework.ui.ModelMap
返回值类型:
ModelAndView 可以添加Model数据,并指定视图
String 返回jsp视图地址 最为常用
void 在异步请求时使用,它只返回数据,而不会跳转视图
package com.yth.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Map;
/**
* @author yth
* @date 2020/10/22 - 20:15
*/
@Controller
@RequestMapping("/Controller")
public class SecondController {
@GetMapping("/second1")
public ModelAndView second1(HttpServletRequest request, HttpSession session){
ModelAndView modelAndView = new ModelAndView();
//等价于 modelAndView.addObject("msg","session:"+session.getId())
request.setAttribute("msg","session:"+session.getId());
modelAndView.setViewName("/jsp/hello.jsp");
return modelAndView;
}
/**
* 返回值 是String InternalResourceViewResolver 把字符串当成 jsp 路径解析
* @return
*/
@GetMapping("/second2")
public String second2(HttpServletRequest request, ModelMap modelMap ,Model model, Map map,HttpSession session){
// 向 model 中添加属性 等价与 向 httpServletRequest 添加
// model.addAttribute("msg","来自model---session:"+session.getId());
// 向modelMap
modelMap.addAttribute("msg","session```:"+session.getId());
return "/jsp/hello.jsp";// InternalResourceViewResolver 可以解析ModelAndView 还可以解析 字符串 字符串作为jsp 路径去解析
@GetMapping("/second3")
public void second3(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setAttribute("msg","request");
//转发
//request.getRequestDispatcher("/jsp/hello.jsp").forward(request, response);
//重定向
response.sendRedirect("/jsp/hello.jsp");
}
}
4.6ViewResolver视图解析器
视图解析器的目的就是帮助我们简化view的路径,为我们自动补全jsp的路径
Spring MVC中的视图解析器负责解析视图。可以通过在配置文件springmvc-servlet.xml中定义一个ViewResolver来配置视图解析器,其配置示例如下:
<!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/jsp/"></property> <!--前缀-->
<property name="suffix" value=".jsp"></property> <!--后缀-->
</bean>