模型-视图-控制器(MVC)是一个众所周知的以设计界面应用程序为基础的设计思想。它主要通过分离模型、视图及控制器在应用程序中的角色将业务逻辑从界面中解耦。
模型:
负责封装应用程序数据在视图层展示。
视图:
仅仅只是展示这些数据,不包含任何业务逻辑。
控制器:
负责接收来自用户的请求,并调用后台服务(service或者dao)来处理业务逻辑。
处理后,后台业务层可能会返回了一些数据在视图层展示。控制器收集这些数据及准备模型在视图层展示。
MVC模式的核心思想是将业务逻辑从界面中分离出来,允许它们单独改变而不会相互影响。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YEgjHYMp-1651160155894)(JavaEE.assets/1651121869179.png)]
Spring MVC是Spring家族中的一个web成员,它是一种基于Java的实现了Web MVC设计思想的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职责解耦,基于请求驱动指的就是使用请求-响应模型,框架的目的就是帮助我们简化开发,Spring MVC也是要简化我们日常Web开发的。
Spring MVC是服务到工作者思想的实现。中央控制器是DispatcherServlet;应用控制器拆为处理器 映射器(Handler Mapping)进行处理器管理和视图解析器(View Resolver)进行视图管理;支持本地化/国际化(Locale)解析及文件上传等;提供了非常灵活的数据验证、格式化和数据绑定机制;提供了强大的约定大于配置(惯例优先原则)的契约式编程支持。
Spring MVC框架也是一个基于请求驱动的Web框架,并且使用了前端控制器模式(是用来提供一个集中的请求处理机制,所有的请求都将由一个单一的处理程序处理来进行设计,再根据请求映射规则分发给相应的页面控制器(动作/处理器)进行处理。首先让我们整体看一下Spring MVC处理请求的流程:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c6E7t9Cq-1651160155895)(JavaEE.assets/1651122327182.png)]
首先用户发送请求,请求被SpringMvc前端控制器(DispatherServlet)捕获;
前端控制器(DispatherServlet)对请求URL解析获取请求URI,根据URI,调用HandlerMapping;
前端控制器(DispatherServlet)获得返回的HandlerExecutionChain(包括Handler对象以及
Handler对象对应的拦截器);
DispatcherServlet 根据获得的 HandlerExecutionChain,选择一个合适的HandlerAdapter。(附
注:如果成功获得HandlerAdapter后,此时将开始执行拦截器的preHandler(…)方法);
HandlerAdapter根据请求的Handler适配并执行对应的Handler;HandlerAdapter(提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)。 在填充Handler的入参过程中,根据配置,Spring将做一些额外的工作:
Handler执行完毕,返回一个ModelAndView(即模型和视图)给HandlerAdaptor
HandlerAdaptor适配器将执行结果ModelAndView返回给前端控制器。
前端控制器接收到ModelAndView后,请求对应的视图解析器。
视图解析器解析ModelAndView后返回对应View;
渲染视图并返回渲染后的视图给前端控制器。
最终前端控制器将渲染后的页面响应给用户或客户端
还有比如RESTful(一种软件架构风格,设计风格而不是标准,只是提供了一组设计原则和约束条
件。它主要用于客户端和服务器交互类的软件,目前了解即可)风格的支持、简单的文件上传、约定大
于配置的契约式编程支持、基于注解的零配置支持等等。
新建wep-app项目
pom.xml坐标添加—>配置web.xml—>配置spring.xml—>页面控制器编写—>视图页面(.jsp)编写—>启动服务器
pom.xml 坐标添加
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<!-- spring web -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.2.4.RELEASE</version>
</dependency>
<!-- spring mvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.4.RELEASE</version>
</dependency>
<!-- web servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 编译环境插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>11</source>
<target>11</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<!-- jetty插件 -->
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.4.27.v20200227</version>
<configuration>
<scanIntervalSeconds>10</scanIntervalSeconds>
<!-- 设置端口 -->
<httpConnector>
<port>8080</port>
</httpConnector>
<!-- 设置项目路径 -->
<webAppConfig>
<contextPath>/springmvc01</contextPath>
</webAppConfig>
</configuration>
</plugin>
</plugins>
</build>
配置 web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<!-- 编码过滤 utf-8 -->
<filter>
<description>char encoding filter</description>
<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>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*
springMvc
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:spring.xml
1
springMvc
/
要想启动我们的 SpringMVC 环境,目前对于 mvc 框架的配置还未进行。以上在 web.xml 中引用了
spring.xml 文件。
spring.xml 配置
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
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">
<!-- 开启扫描器 -->
<context:component-scan base-package="com.xxxx.controller"/>
<!-- 使用默认的 Servlet 来响应静态文件 -->
<mvc:default-servlet-handler/>
<!-- 开启注解驱动-->
<mvc:annotation-driven/>
<!-- 配置视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
id="internalResourceViewResolver">
<!-- 前缀:在WEB-INF目录下的jsp目录下 -->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!-- 后缀:以.jsp结尾的资源 -->
<property name="suffix" value=".jsp"/>
</bean>
</beans>
页面控制器的编写
@Controller
@RequestMapping("user")
public class HelloConstroller {
@RequestMapping("hello")
public ModelAndView hello(){
ModelAndView mv = new ModelAndView();
mv.addObject("msg","hello springmvc");
mv.setViewName("hello");
return mv;
}
添加视图页面
在 WEB-INF 下新建 jsp 文件夹 ,并在文件夹下新建 hello.jsp
<%--
Created by IntelliJ IDEA.
User: KT
--%>
<%@ page contentType="text/html;charset=UTF-8" isELIgnored="false" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<!-- el表达式接收参数值 -->
<h2>${msg}</h2>
</body>
</html>
启动 jetty/tomcat 服务器开启测试
@RequestMapping
细化请求路径
通过注解 @RequestMapping 将请求地址与方法进行绑定,可以在类级别和方法级别声明。类级别的注解负责将一个特定的请求路径映射到一个控制器上,将 url 和类绑定;通过方法级别的注解可以细化映射,能够将一个特定的请求路径映射到某个具体的方法上,将 url 和类的方法绑定。
@RequestMapping("") 或 @RequestMapping(value="")
声明在方法上面,映射单个 URL
访问地址:(如果有类路径需要写在方法路径前面)
@Controller
public class DataController {
@RequestMapping("test")
public void test(Integer age,String name){
System.out.println(age+"---"+name);
}
@RequestMapping({"",""}) 或 @RequestMapping(value={"",""})
声明在方法上面,映射多个 URL,多个地址都可以映射到同一个方法
用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。
@RequestMapping
声明在类上面,类中的的方法都是以该地址作为父路径
声明级别:
类级别 + 方法级别 (/类路径/方法路径)
默认没有设置请求方式,在HTTP 请求中最常用的请求方法是 GET、POST,还有其他的一些方法,如:DELETE、PUT、HEAD 等。
可以通过 method 属性设置支持的请求方式,如 method=RequestMethod.POST;如设置多种请求方式,以大括号包围,逗号隔开即可。
设置了请求方式,则只能按照指定的请求方式请求。
访问地址:(只能使用POST请求访问)
通过参数名称访问
访问地址:
http://ip:port/springmvc01/url?test06
其中?后面的内容是参数
@RequestMapping(params = "test06")
public ModelAndView test06(){
ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("hello","test06");
modelAndView.setViewName("hello"); return modelAndView;
}
客户端请求的参数到控制器功能处理方法上的参数的绑定,对于参数绑定非常灵活。
参数值必须存在。如果没有指定参数值,也没有设置参数默认值,则会报500异常。
通过注解 @RequestParam 标记一个形参为请求参数。(注解声明在形参的前面)
* 可以通过注解的属性设置相关内容
* 设置参数的默认值 defaultValue
SpringMVC 默认采用服务器内部转发的形式展示页面信息。同样也支持重定向页面。
重定向是发一个302的状态码给浏览器,浏览器自己去请求跳转的网页。地址栏会发生改变。
请求转发,直接调用跳转的页面,让它返回。对于浏览器来说,它无法感觉服务器有没有forward。 地址栏不发生改变。可以获取请求域中的数据
页面中获取数据
获取传递的参数:${param.参数名}
获取请求域的数据:${请求域中设置的名称}
注意:
如果没有redirect和forward这两个跳转行为,Spring MVC会介入视图解析器加上前后缀
概念
Json 在企业开发中已经作为通用的接口参数类型,在页面(客户端)解析很方便。SpringMVC 对于json 提供了良好的支持,这里需要修改相关配置,添加 json 数据支持功能
@ResponseBody
该注解用于将 Controller 的方法返回的对象,通过适当的 HttpMessageConverter 转换为指定格式后,写入到 Response 对象的 body 数据区。
返回的数据不是 html 标签的页面,而是其他某种格式的数据时(如 json、xml 等)使用(通常用于ajax 请求)。
@RequestBody
该注解用于读取 Request 请求的 body 部分数据,使用系统默认配置的 HttpMessageConverter 进行解析,然后把相应的数据绑定到要返回的对象上 ,再把 HttpMessageConverter 返回的对象数据绑定到controller 中方法的参数上。
概念
SpringMVC 中的 Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理。比如通过它来进行权限验证,或者是来判断用户是否登陆等操作。
对于 SpringMVC拦截器的定义方式有两种:
实现接口:org.springframework.web.servlet.HandlerInterceptor
继承适配器:org.springframework.web.servlet.handler.HandlerInterceptorAdapter