SpringMVC
SprintMVC#
框架学习:官方文档
重点:SprintMVC的执行流程
1.回顾MVC#
MVC是三个单词的首字母缩写,它们是Model(模型)、View(视图)和Controller(控制)。
-
Model(dao,service)
是核心的"数据层"(Model),也就是程序需要操作的数据或信息。
-
View(jsp..)
直接面向最终用户的"视图层"(View)。它是提供给用户的操作界面,是程序的外壳。
-
Controller(servlet)
它负责根据用户输入的指令,选取"数据层"中的数据,然后对其进行相应的操作调用"视图层,产生最终结果。
mvc要做的事#
1.将url映射到java类
2.封装用户提交的数据
3.处理请求-调用model-封装响应数据
4.渲染响应数据
2.初识SpringMVC#
Spring Web MVC是基于Servlet API构建的原始Web框架,从一开始就已包含在Spring Framework中。
优点:
-
轻量级,简单易学
-
高效,基于请求响应的MVC框架
-
与Spring无缝结合
-
约定大于配置
-
功能强大:restful,数据验证,格式化,本地化,主题等等
与其他许多Web框架一样,Spring MVC围绕前端控制器模式DispatcherServlet进行设计,在该模式下,中央Servlet DispatcherServlet提供了用于请求处理的共享算法,而实际工作是由可配置的委托组件执行的。 该模型非常灵活,并支持多种工作流程。
DispatcherServlet#
SpringMVC的核心就是DispatcherServlet,DispatcherServlet实质也是一个HttpServlet。DispatcherSevlet负责将请求分发,所有的请求都有经过它来统一分发。
DispatcherServlet 与任何Servlet一样,都需要使用Java配置或在web.xml中根据Servlet规范声明和映射DispatcherServlet。
反过来,DispatcherServlet使用Spring配置发现请求映射,视图解析,异常处理等所需的委托组件。
代码实现#
1.配置DispatcherServlet 在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>
<!-- 配置DispatcherServlet-->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 关联配置文件 springmvc-servlet.xml-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
<!-- 设置启动级别-->
<load-on-startup>1</load-on-startup>
</servlet>
<!-- / 拦截所以请求 除了jsp-->
<!-- /* 拦截所以请求 加上jsp-->
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
2.配置springmvc容器springmvc-servlet.xml#
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 处理映射器-->
<bean id="handlerMapping" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<!-- 处理适配器-->
<bean id="handlerAdapter" class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
<!-- 视图解析器-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 前缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!-- 后缀-->
<property name="suffix" value=".jsp"/>
</bean>
<!-- 注册controller-->
<bean id="/hello" class="com.cb.Controller.MyController"/>
</beans>
3.写controller#
package com.cb.Controller;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
//视图和模型
ModelAndView model = new ModelAndView();
//添加对象
model.addObject("msg","hello springmvc");
//添加视图名字
model.setViewName("hello");
return model;
}
}
3.springMVC执行流程#
处理器:是对控制器的封装
HandlerMapping:代表请求路径和控制器(或其方法)的映射关系,它会在 Web 务器启动 Spring MVC 时,就被扫描到HandlerMapping 的机制中存储,
HanderExecutionChain 对象:HandlerExecutionChain 对象包含一个处理器( handler 这里的处理器是对控制器( controller )的包装,因为我们的控制器方法可能存在参数,那么处理器就可以读入 HTTP和上下文的相关参数,然后再传递给控制器方法。而在控制器执行完成返回后,处理器又可以通过配置信息对控制器的返回结果进行处理。
HanderAdapter:
但是我们有普通 HTTP 请求,也有按 BeanName 的请求,甚至是 WebSocket 的请求,所以它还需要 个适配器去运行 HandlerExecutionChain 对象包含的处理器,这就是 HandlerAdapter 接口定义的实现类
分析流程:#
-
DispatcherServlet代表前端控制器,接受前端请求并拦截请求,调用HanderMapping
-
用户发起请求被 DispatcherServlet 拦截后,通过URL和其他的条件 ,通过HandlerMapper机制就能找到对应的控制器(或其方法)进行响应。只是通 HandlerMapping 返回的 是一个HanderExecutionChain 对象。
-
通过HanderAdapter对象:执行 Web 请求的 HandlerExecutionChain 对象包含的内容,这样就能
够执行我们的处理器( handler 了。
-
在处理器调用控制器时,它首先通过模型层得到数据,再放入数据模型中,最后将返回模型和视图( ModelAndView )对象,这里控制器设置的视图名称设置为“xxxx ”,这样就走到了视图解析器 ViewResolver ),去解析视图逻辑名称了。
-
DispatcherServlet 再调用视图,将数据模板渲染展示。
4.使用注解开发SpringMVC#
1.修改springmvc-servlet.xml文件#
<!-- //开启注解扫描 @Controller-->
<context:component-scan base-package="com.cb.Controller"/>
<!-- annotation-driven 开启注解驱动,让@requestMapping注解生效
并且自动注入 requestHandermappong 和 handerAdapter ,两个类是让@requestMapping注解生效的前提
-->
<mvc:annotation-driven/>
<!-- 处理静态资源 让springmvc不处理静态支援-->
<mvc:default-servlet-handler/>
2.使用注解#
@Controller
@RequestMapping("/hello")
package com.cb.Controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class MyController {
@RequestMapping("/hello")
public String handleRequest() {
//视图和模型
ModelAndView model = new ModelAndView();
//添加对象
model.addObject("msg","hello springmvc");
return "hello";
}
}
使用springMVC必须配置三大件:
-
HandlerMapping
-
HanderAdapter
-
ViewResolver
5.restful风格#
Representational State Transfer
RESTFUL是一种网络应用程序的设计风格和开发方式,基于HTTP,以使用XML格式定义或JSON格式定义。
RESTFUL特点包括:
1、每一个URI代表1种资源;
2、客户端使用GET、POST、PUT、DELETE
4个表示操作方式的动词对服务端资源进行操作:GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源; patch
方法用来更新局部资源
3、通过操作资源的表现形式来操作资源;
4、资源的表现形式是XML或者HTML;
5、客户端与服务端之间的交互在请求之间是无状态的,从客户端到服务端的每个请求都必须包含理解请求所必需的信息'
Spring对RESTful的支持#
- Spring MVC 对 RESTful应用提供了以下支持
- 利用@RequestMapping 指定要处理请求的URI模板和HTTP请求的动作类型
- 利用@PathVariable讲URI请求模板中的变量映射到处理方法参数上
- 利用Ajax,在客户端发出PUT、DELETE动作的请求
代码实现#
@GetMapping("/userr/{id}")
public String handleRequest(@PathVariable(value = "id")int id1) {
System.out.println(id1);
//视图和模型
ModelAndView model = new ModelAndView();
//添加对象
model.addObject("msg","hello springmvc");
return "hello";
}
6.重定向和请求转发#
请求转发#
return "forward:/hello";
return model ;
return "x.jsp"
重定向#
return "redirect:/hello";
7、接受请求参数#
1.请求参数和方法参数名字一致#
则直接可以接受
2.请求参数和方法参数名字不一致#
使用@RequestParam
3.请求参数是一个对象#
前端使用表单,用一个pojo接受,即用一个对象接收,要求对象属性和表单域名一致
请求参数传递接受#
# 请求参数
如果没有传递 为null
http://localhost:8989/user/demo?name 传递为''
json#
JSON(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式。它基于 ECMAScript
(欧洲计算机协会制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。
前端解析#
<script type="text/javascript">
var user = {
name:"chen",
age:12
}
//对象转换为json字符串
var str = JSON.stringify(user);
console.log(str)
//把json字符串转化为对象
var user1 = JSON.parse(str);
console.log(user1)
</script>
后台解析json#
1.导入包#
<!-- json转换-->
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.0</version>
</dependency>
2.配置乱码问题#
<!--Jackson乱码解决-->
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8"/>
</bean>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<property name="failOnEmptyBeans" value="false"/>
</bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
3.使用Jackson解析#
@RestController
public class JsonController {
@RequestMapping("/j1")
public String get1() throws JsonProcessingException {
User user = new User("张山","男",20);
User user2 = new User("张山2","男",20);
User user3 = new User("张山3","男",20);
List<User> list = new ArrayList<>();
list.add(user);
list.add(user2);
list.add(user3);
ObjectMapper objectMapper = new ObjectMapper();
String s = objectMapper.writeValueAsString(list);
return s;
}
}
使用fastjson
4.简单开发#
@RestController =
@Controller
@ResponseBody //标记返回json
使用@RestController 就会自动解析成json返回
解析json数据#
@RequestBody#
作用:
主要用来接收前端传递给后端的json字符串中的数据的(请求体中的数据的);
要求:
GET方式无请求体,所以使用@RequestBody接收数据时,前端不能使用GET方式提交数据,而是用POST方式进行提交。
在后端的同一个接收方法里,@RequestBody与@RequestParam()可以同时使用,@RequestBody最多只能有一个,而@RequestParam()可以有多个。
简言之:
一个请求——》只有一个@RequestBody;
一个请求——》可以有多个@RequestParam。
9、拦截器#
(1)过滤器:
依赖于servlet容器。在实现上基于函数回调,可以对几乎所有请求进行过滤,但是缺点是一个过滤器实例只能在容器初始化时调用一次。使用过滤器的目的是用来做一些过滤操作,获取我们想要获取的数据,比如:在过滤器中修改字符编码;在过滤器中修改HttpServletRequest的一些参数,包括:过滤低俗文字、危险字符等
(2)拦截器:
依赖于web框架,在SpringMVC中就是依赖于SpringMVC框架。在实现上基于Java的反射机制,属于面向切面编程(AOP)的一种运用。由于拦截器是基于web框架的调用,因此可以使用Spring的依赖注入(DI)进行一些业务操作,同时一个拦截器实例在一个controller生命周期之内可以多次调用。但是缺点是只能对controller请求进行拦截,对其他的一些比如直接访问静态资源的请求则没办法进行拦截处理。
自定义拦截器#
1.继承一个接口HandlerInterceptor#
package com.cb.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyInterceptor implements HandlerInterceptor {
public MyInterceptor() {
super();
}
//返回false 就不向下执行了
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion");
}
}
//执行结构:
// preHandle
//postHandle
//afterCompletion
2.注册拦截器#
<mvc:interceptors>
<mvc:interceptor>
<!-- /* 表示一个目录下的所有 /** 表示下面的所有-->
<mvc:mapping path="/**"/>
<bean class="com.cb.interceptor.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
10.文件上传#
SpringMVC很好的处理了文件上传,但是SpringMVC上下文默认没有装配MultipartResolver,因此默认不能进行文件上下传处理。需要处理文件需要配置。
前端表单要求:
表单的method必须为为post,enctype=“multipart/form-data”,这样才能浏览器才能把用户选择的文件以二进制数据发送给服务器。
1.引入依赖#
fileupload - servlet
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
和servlet
2.前端文件#
<%--
Created by IntelliJ IDEA.
User: 他知道
Date: 2020/8/4
Time: 20:43
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>
<form action="${pageContext.request.contextPath}/upload" enctype="multipart/form-data" method="post">
<input type="file" name="file">
<input type="submit" value="提交">
</form>
</body>
</html>
3.配置文件上传bean#
<!--id一定要按是multipartResolver-->
<!-- 文件上传配置-->
<bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver" id="multipartResolver">
<property name="defaultEncoding" value="utf-8"/>
<!-- 文件上传大小配置-->
<property name="maxUploadSize" value="10487560"/>
<!-- 在这里设置了文件放入临时文件夹的最小大小限制,那么这个属性到底还有什么作用呢?-->
<!-- 查询得知:此为阈值,低于此值,则保存在内存中,如高于此值,则生成硬盘上的临时文件-->
<property name="maxInMemorySize" value="40960"/>
</bean>
4.文件上传#
package com.cb.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
@RestController()
public class FileUp {
@PostMapping("/upload")
//把前端上传的文件转化为CommonsMultipartFile对象 ,如果是多个文件就转换为CommonsMultipartFile数组
public String up(@RequestParam("file") CommonsMultipartFile file,HttpServletRequest request){
//获取文件真实名
String filename = file.getOriginalFilename();
// 获取保存路径
String realPath = request.getServletContext().getRealPath("/upload");
// String realPath = "classpath:/upload";
System.out.println(realPath);
File pathfile = new File(realPath);
if(!pathfile.exists()){
pathfile.mkdir();
}
//保存文件
try {
file.transferTo(new File(realPath+"/"+filename));
} catch (IOException e) {
e.printStackTrace();
}
return "success : 成功";
}
}
作者:Esofar
出处:https://www.cnblogs.com/firsthelloworld/p/13437625.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本