文章目录
- 项目源码地址
- 回顾-MVC
- 什么是MVC?
- MVC各部分组成
- 回顾-Servlet
- Maven创建Web项目
- 1、创建Maven父工程pom,并导入依赖
- 2、用Maven新建一个Web Module
- 3、代码:HelloServlet.java
- 3、代码-hello.jsp
- 3、代码-web.xml
- 4、配置Tomcat
- 5、浏览器测试
- Maven创建jar项目,并手动添加web依赖
- 初识SpringMVC
- SpringMVC的基础知识
- DispatcherServlet:中心控制器
- SpringMVC执行原理
- 第一个SpringMVC程序
- xml配置实现
- 1、在上述父工程下,创建一个Web Module
- 2、配置web.xml,注册DispatchServlet
- 3、编写Spring MVC的配置文件【不同】
- 4、编写操作业务Controller【不同】
- 5、编写要跳转的jsp页面
- 6、启动测试
- annotation注解实现
- 1、在上述父工程下,创建一个Web Module
- 2、配置web.xml,注册DispatchServlet
- 3、编写Spring MVC的配置文件【不同】
- 4、编写操作业务Controller【不同】
- 5、编写要跳转的jsp页面
- 6、启动测试
- 控制器:Controller
- 控制器的作用
- 控制器实现
- 项目Module名称
- 实现--接口定义
- 实现--注解实现
- 总结
- 注解:@RequestMapping
- 作用
- 示例
- RestFul风格
- 什么是RestFul?
- RestFul
- 资源和资源操作
- 资源操作方法对比
- 示例
- 代码
- 应用:@PathVariable
- 应用:method属性
- 应用:@GetMapping、......
- 数据处理及跳转
- 项目Module名称
- 结果跳转
- ModelAndView
- ServletAPI
- SpringMVC-无需视图解析器
- SpringMVC-有视图解析器
- 数据处理-提交到后端的数据
- 数据处理-数据显示到前端
- 乱码处理
- 方法1-springMVC-过滤器
- 方法2-Tomcat修改配置文件
- 方法3-自定义过滤器
- 总结
- Json
- 项目Module名称
- 什么是Json?
- 概念
- 语法格式
- Json和JavaScript的区别
- Json和JavaScript的相互转换
- Controller返回Json数据:jackson
- Module准备
- Controller核心代码
- 统一处理乱码问题
- Controller返回Json数据:fastjson
- Module准备
- fastjson三大核心类
- 数据类型相互转换
- Ajax
- 拦截器:Interceptor
- 什么是拦截器?
- 概念
- 过滤器和拦截器的区别
- 拦截器使用
- 文件上传和下载
- Module准备
- 核心代码展示
- 前端页面
- Controller
项目源码地址
GitHub | https://github.com/Web-Learn-GSF/Java_Learn_Examples |
---|---|
父工程 | Java_Framework_SpringMVC |
回顾-MVC
什么是MVC?
MVC是(Model、View、Controller的缩写)一种软件设计规范,将业务逻辑、数据、显示三者分离开来组织代码
MVC主要作用是降低了视图与业务逻辑间的双向耦合
MVC各部分组成
模块 | 组成 |
---|---|
Model(模型) | 提供要展示的数据,可以认为是领域模型或JavaBean组件(包含数据和行为) |
View(视图) | 负责进行模型的展示,一般就是我们见到的用户界面,客户想看到的东西 |
Controller(控制器) | 接收用户请求,委托给模型进行处理(状态改变),处理完毕后把返回的模型数据返回给视图,由视图负责展示。也就是说控制器做了个调度员的工作 |
回顾-Servlet
这一章将讲述两种创建Web项目的方法来回顾servlet:
-
Maven创建web项目,运行servlet
-
Maven创建jar项目,手动添加框架依赖,运行servlet**(还没调试通顺,后续有空继续整)**
同时也将讲述Tomcat9和Tomcat10在servlet包依赖上的不同
Maven创建Web项目
1、创建Maven父工程pom,并导入依赖
- 若Tomcat版本为10,依赖导入
<dependencies><!-- 没有争议的依赖 --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.1</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>6.0.9</version></dependency><!-- 有版本争议的依赖:servlet、jsp--><!-- https://mvnrepository.com/artifact/org.apache.tomcat/tomcat-servlet-api --><dependency><groupId>org.apache.tomcat</groupId><artifactId>tomcat-servlet-api</artifactId><version>10.0.4</version></dependency><!-- https://mvnrepository.com/artifact/org.apache.tomcat/tomcat-jsp-api --><dependency><groupId>org.apache.tomcat</groupId><artifactId>tomcat-jsp-api</artifactId><version>10.0.4</version></dependency></dependencies>
- 若Tomcat版本为9,依赖导入
<dependencies><!-- 没有争议的依赖 --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.1</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>6.0.9</version></dependency><!-- 有版本争议的依赖:servlet、jsp--><dependency><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId><version>2.5</version></dependency><dependency><groupId>javax.servlet.jsp</groupId><artifactId>jsp-api</artifactId><version>2.2</version></dependency><dependency><groupId>javax.servlet</groupId><artifactId>jstl</artifactId><version>1.2</version></dependency>
</dependencies>
Tomcat9及以前,servlet依赖包名是 javax.servlet;Tomcat10之后,servlet依赖包名是 jakarta.servlet
如若不注意版本匹配,启动Tomcat会爆出404问题
2、用Maven新建一个Web Module
Module名字:Demo-01-ServletReview-MavenWebCreate
Module内容解释:
- pom文件里面的packaging标签是war
整体结构及后续代码
- Maven创建的web项目,webapp在main目录下,跟手动添加web依赖所在的目录不一样
3、代码:HelloServlet.java
Tomcat版本为10的代码
package GSF.Example.Servlet;import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;public class HelloServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//取得参数String method = req.getParameter("method");if ("add".equals(method)){req.getSession().setAttribute("msg","执行了add方法");}if ("delete".equals(method)){req.getSession().setAttribute("msg","执行了delete方法");}//业务逻辑:暂无//视图跳转req.getRequestDispatcher("/WEB-INF/jsp/hello.jsp").forward(req,resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}
Tomcat版本为9的代码
package GSF.Example.Servlet;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;public class HelloServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//取得参数String method = req.getParameter("method");if ("add".equals(method)){req.getSession().setAttribute("msg","执行了add方法");}if ("delete".equals(method)){req.getSession().setAttribute("msg","执行了delete方法");}//业务逻辑:暂无//视图跳转req.getRequestDispatcher("/WEB-INF/jsp/hello.jsp").forward(req,resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);}
}
区别:包的名字
- Tomcat10:jakarta.servlet
- Tomcat9:javax.servlet
3、代码-hello.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false" %>
<html>
<head><title>Kuangshen</title>
</head>
<body>
${msg}
</body>
</html>
- web2.4之后,默认禁止el表达式,即${}不会从session域中获取数据
- 通过添加上边的第二行代码:
<%@ page isELIgnored="false" %>
,可以关闭对el表达式的禁止,实现从session域中获取数据
3、代码-web.xml
Maven创建web项目,默认的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><servlet><servlet-name>HelloServlet</servlet-name><servlet-class>GSF.Example.Servlet.HelloServlet</servlet-class></servlet><servlet-mapping><servlet-name>HelloServlet</servlet-name><url-pattern>/user</url-pattern></servlet-mapping></web-app>
若是手动添加框架依赖,创建的web.xml
<?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>HelloServlet</servlet-name><servlet-class>GSF.Example.Servlet.HelloServlet</servlet-class></servlet><servlet-mapping><servlet-name>HelloServlet</servlet-name><url-pattern>/user</url-pattern></servlet-mapping></web-app>
4、配置Tomcat
- 暂不清楚为啥要选这个,也不知道选不带有war exploded的会有啥问题
5、浏览器测试
- localhost:8080/user?method=add
- localhost:8080/user?method=delete
Maven创建jar项目,并手动添加web依赖
暂时没调试通顺
初识SpringMVC
SpringMVC的基础知识
Spring MVC是Spring Framework的一部分,是基于Java实现MVC的轻量级Web框架
官方文档:https://docs.spring.io/spring/docs/5.2.0.RELEASE/spring-framework-reference/web.html#spring-web
Spring MVC特点
- 轻量级,简单易学
- 高效 , 基于请求响应的MVC框架
- 与Spring兼容性好,无缝结合
- 约定优于配置
- 功能强大:RESTful、数据验证、格式化、本地化、主题等
- 简洁灵活
Spring的web框架围绕DispatcherServlet [ 调度Servlet ] 设计。
DispatcherServlet的作用是将请求分发到不同的处理器。从Spring 2.5开始,使用Java 5或者以上版本的用户可以采用基于注解形式进行开发,十分简洁。
DispatcherServlet:中心控制器
Spring的web框架围绕DispatcherServlet设计:
- DispatcherServlet的作用是将请求分发到不同的处理器
- 从Spring 2.5开始,使用Java 5或者以上版本的用户可以采用基于注解的controller声明方式
Spring MVC框架像许多其他MVC框架一样, 以请求为驱动 , 围绕一个中心Servlet分派请求及提供其他功能,DispatcherServlet是一个实际的Servlet (它继承自HttpServlet 基类)
SpringMVC执行原理
实现部分:表示框架已经帮忙完成;虚线部分:表示需要我们手动编写的地方
步骤1:
- DispatcherServlet表示前置控制器,是整个SpringMVC的控制中心。用户发出请求,DispatcherServlet接收请求并拦截请求
- 假设请求的url为 : localhost:8080/SpringMVC/hello
- web.xml中定义,拦截所有请求
<servlet><servlet-name>springmvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><!--关联一个springmvc的配置文件:【servlet-name】-servlet.xml--><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:springmvc-servlet.xml</param-value></init-param><!--启动级别-1--><load-on-startup>1</load-on-startup></servlet><!--/ 匹配所有的请求;(不包括.jsp)--><!--/* 匹配所有的请求;(包括.jsp)--><servlet-mapping><servlet-name>springmvc</servlet-name><url-pattern>/</url-pattern></servlet-mapping>
步骤2:
- HandlerMapping为处理器映射,被DispatcherServlet调用
- HandlerMapping根据请求url查找Handler
- springmvc-servlet.xml中注册HandlerMapping的bean
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
步骤3:
- HandlerExecution表示具体的Handler,其主要作用是根据url查找控制器
- 如上url被查找控制器为:hello
步骤4:
- HandlerExecution将解析后的信息传递给DispatcherServlet
- 解析后的信息:处理器对象及处理器拦截器
步骤5:
- HandlerAdapter表示处理器适配器,其按照特定的规则去执行Handler
- springmvc-servlet.xml中注册HandlerAdapter的bean
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
步骤6:
- Handler让具体的Controller执行
- springmvc-servlet.xml中注册Handler的bean
<bean id="/hello" class="GSF.Example.Controller.HelloController"/>
步骤7:
- Controller将具体的执行信息返回给HandlerAdapter
- 返回的信息如:ModelAndView
步骤8:
- HandlerAdapter将视图逻辑名或模型传递给DispatcherServlet
步骤9:
- DispatcherServlet调用视图解析器(ViewResolver)来解析HandlerAdapter传递的逻辑视图名
- springmvc-servlet.xml中注册bean,并完成相关配置
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver"><!--前缀--><property name="prefix" value="/WEB-INF/jsp/"/><!--后缀--><property name="suffix" value=".jsp"/>
</bean>
步骤10:
- 视图解析器将解析的逻辑视图名传给DispatcherServlet
步骤11:
- DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图
步骤12:
- 最终视图呈现给用户
第一个SpringMVC程序
xml配置实现
1、在上述父工程下,创建一个Web Module
Module名字:Demo-02-SpringMVC-xml
整体结构图及后续写入代码
2、配置web.xml,注册DispatchServlet
- 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><!--1.注册DispatcherServlet--><servlet><servlet-name>springmvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><!--关联一个springmvc的配置文件:【servlet-name】-servlet.xml--><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:springmvc-servlet.xml</param-value></init-param><!--启动级别-1--><load-on-startup>1</load-on-startup></servlet><!--/ 匹配所有的请求;(不包括.jsp)--><!--/* 匹配所有的请求;(包括.jsp)--><servlet-mapping><servlet-name>springmvc</servlet-name><url-pattern>/</url-pattern></servlet-mapping>
</web-app>
3、编写Spring MVC的配置文件【不同】
- 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"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/><bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/><!--视图解析器:DispatcherServlet给他的ModelAndView--><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver"><!--前缀--><property name="prefix" value="/WEB-INF/jsp/"/><!--后缀--><property name="suffix" value=".jsp"/></bean><!--Handler--><bean id="/hello" class="GSF.Example.Controller.HelloController"/></beans>
4、编写操作业务Controller【不同】
- HelloController.java
package GSF.Example.Controller;import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;//注意:这里我们先导入Controller接口
public class HelloController implements Controller {public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {//ModelAndView 模型和视图ModelAndView mv = new ModelAndView();//封装对象,放在ModelAndView中。Modelmv.addObject("msg","HelloSpringMVC!");//封装要跳转的视图,放在ModelAndView中mv.setViewName("hello"); //: /WEB-INF/jsp/hello.jspreturn mv;}
}
- 在springmvc-servlet.xml中注册该实现类的bean
5、编写要跳转的jsp页面
- hello.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false" %>
<html>
<head><title>Kuangshen</title>
</head>
<body>
${msg}
</body>
</html>
6、启动测试
- localhost:8080/hello
annotation注解实现
1、在上述父工程下,创建一个Web Module
Module名称:Demo-02-SpringMVC-annotation
整体结构图及后续写入代码
2、配置web.xml,注册DispatchServlet
- web.xml
<?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"><!--1.注册servlet--><servlet><servlet-name>SpringMVC</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><!--通过初始化参数指定SpringMVC配置文件的位置,进行关联--><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><!--所有请求都会被springmvc拦截 --><servlet-mapping><servlet-name>SpringMVC</servlet-name><url-pattern>/</url-pattern></servlet-mapping></web-app>
3、编写Spring MVC的配置文件【不同】
- 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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/mvchttps://www.springframework.org/schema/mvc/spring-mvc.xsd"><!-- 自动扫描包,让指定包下的注解生效,由IOC容器统一管理 --><context:component-scan base-package="GSF.Example.Controller"/><!-- 让Spring MVC不处理静态资源 --><mvc:default-servlet-handler /><!--支持mvc注解驱动在spring中一般采用@RequestMapping注解来完成映射关系要想使@RequestMapping注解生效必须向上下文中注册DefaultAnnotationHandlerMapping和一个AnnotationMethodHandlerAdapter实例这两个实例分别在类级别和方法级别处理。而annotation-driven配置帮助我们自动完成上述两个实例的注入。--><mvc:annotation-driven /><!-- 视图解析器 --><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"id="internalResourceViewResolver"><!-- 前缀 --><property name="prefix" value="/WEB-INF/jsp/" /><!-- 后缀 --><property name="suffix" value=".jsp" /></bean></beans>
4、编写操作业务Controller【不同】
package GSF.Example.Controller;import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;@Controller
@RequestMapping("/HelloController")
public class HelloController {//真实访问地址 : 项目名/HelloController/hello@RequestMapping("/hello")public String sayHello(Model model){//向模型中添加属性msg与值,可以在JSP页面中取出并渲染model.addAttribute("msg","hello, SpringMVC");//web-inf/jsp/hello.jspreturn "hello";}
}
- 通过注解扫描,实现自动注入bean
5、编写要跳转的jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page isELIgnored="false" %>
<html>
<head><title>你好</title>
</head>
<body>
${msg}
</body>
</html>
6、启动测试
- localhost:8080/HelloController/hello
控制器:Controller
控制器的作用
控制器复杂提供访问应用程序的行为,通常通过接口定义或注解定义两种方法实现。
控制器负责解析用户的请求并将其转换为一个模型。
在Spring MVC中一个控制器类可以包含多个方法
在Spring MVC中,对于Controller的配置方式有很多种
控制器实现
项目Module名称
Demo-03-SpringMVC-Controller_Restful
实现–接口定义
package GSF.Example.Controller;import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.ui.Model;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;public class HelloController_Interface implements Controller {@Overridepublic ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {ModelAndView mv = new ModelAndView();mv.addObject("msg", "hello, SpringMVC, Controller_Interface");mv.setViewName("hello");return mv;}
}
实现–注解实现
package GSF.Example.Controller;import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;@Controller
@RequestMapping("/controller")
public class HelloController_Annotation {//真实访问地址 : 项目名/controller/hello@RequestMapping("/annotation")public String sayHello(Model model){//向模型中添加属性msg与值,可以在JSP页面中取出并渲染model.addAttribute("msg","hello,SpringMVC, Controller_Annotation");//web-inf/jsp/hello.jspreturn "hello";}
}
总结
注解开发会更频繁,且高效
两个方法的跳转指向同一个jsp页面,视图复用,可以看出控制器和视图之间是弱耦合关系
注解:@RequestMapping
作用
用于映射url到控制器类或一个特定的处理程序方法
可用于类或方法上:
- 用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径
- 用于方法上,表示可以通过该路径,访问到该方法
示例
// 仅注解在方法上:localhost:8080 / 项目名 / h1@Controller
public class TestController {@RequestMapping("/h1")public String test(){return "test";}
}
// 既注解在类上,也注解在方法上:localhost:8080 /项目名/ admin / h1@Controller
@RequestMapping("/admin")
public class TestController {@RequestMapping("/h1")public String test(){return "test";}
}
RestFul风格
什么是RestFul?
RestFul
Restful就是一个资源定位及资源操作的风格,不是标准也不是协议,只是一种风格
基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制
资源和资源操作
- 资源:互联网所有的事物都可以被抽象为资源
- 资源操作:
- 使用POST、DELETE、PUT、GET对资源进行操作
- 分别对应对资源的增、删、改、查(查单一、查全部)操作
资源操作方法对比
操作 | Restful | 传统 |
---|---|---|
增 | http://127.0.0.1/item,POST方法 | http://127.0.0.1/item/saveItem.action,POST方法 |
删 | http://127.0.0.1/item/1,DELETE方法 | http://127.0.0.1/item/deleteItem.action?id=1,GET方法或POST方法 |
改 | http://127.0.0.1/item,PUT方法 | http://127.0.0.1/item/updateItem.action,POST方法 |
查(单一) | http://127.0.0.1/item/,GET方法(不带参数) | http://127.0.0.1/item/queryItem.action?id=1,GET方法 |
查(全部) | http://127.0.0.1/item/1/,GET方法(带参数) | http://127.0.0.1/item/queryItem.action/all,GET方法 |
示例
代码
- test1
package GSF.Example.Restful;import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;@Controller
public class Restful {@RequestMapping("/restful/{var1}/{var2}")public String calculate(@PathVariable int var1, @PathVariable int var2, Model model){int result = var1 + var2;model.addAttribute("msg", "求和结果:" + result);return "hello";}
}
- test2
package GSF.Example.Restful;import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;@Controller
public class Restful_method {//@RequestMapping(value = "/restful_method/{var1}/{var2}", method = {RequestMethod.POST})@RequestMapping(value = "/restful_method/{var1}/{var2}")@GetMappingpublic String calculate(@PathVariable int var1, @PathVariable int var2, Model model){int result = var1 + var2;model.addAttribute("msg", "求和结果:" + result);return "hello";}
}
应用:@PathVariable
-
将url变量绑定到方法参数上
-
若url变量传入的类型和方法参数的类型不对应,会出现404无法访问,而不是在程序中出现类型不匹配异常
应用:method属性
- 指定该url的请求方法
应用:@GetMapping、…
-
通过注解的形式,指定url的请求方法类型
-
@GetMapping、@PostMapping、@PutMapping、@DeleteMapping、@PatchMapping
数据处理及跳转
项目Module名称
Demo-04-SpringMVC-DataProcess_Redirection
- 代码参考:上述连接
- 该部分,文章中不贴入完整代码
结果跳转
ModelAndView
package GSF.Example.ResultRedirection;import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.mvc.Controller;public class ModelAndView implements Controller {@Overridepublic org.springframework.web.servlet.ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {org.springframework.web.servlet.ModelAndView mv = new org.springframework.web.servlet.ModelAndView();mv.addObject("msg", "hello, Result Redirection, ModelAndView");mv.setViewName("hello");return mv;}
}
-
springmvc-servlet中注册bean
-
addObject:写入数据
-
setViewName:设置要跳转的视图资源
- 配合视图解析器
ServletAPI
package GSF.Example.ResultRedirection;import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;import java.io.IOException;@Controller
public class ServletAPI {@RequestMapping("servlet_redirection/test1")public void test1(HttpServletRequest req, HttpServletResponse rsp) throws IOException {// 输出rsp.getWriter().println("hello, Result Redirection, ServletAPI: rsp.getWriter().println");}@RequestMapping("servlet_redirection/test2")// 重定向:禁止指向受保护的视图资源public void test2(HttpServletRequest req, HttpServletResponse rsp) throws IOException {rsp.sendRedirect("/Result_Redirection/test2.jsp");}@RequestMapping("servlet_redirection/test3")public void test3(HttpServletRequest req, HttpServletResponse rsp) throws IOException, ServletException {// 请求转发:可以指向受保护的视图资源req.setAttribute("msg", "hello, Result Redirection, ServletAPI: req.setAttribute, req.getRequestDispatcher");req.getRequestDispatcher("/WEB-INF/jsp/hello.jsp").forward(req, rsp);}
}
-
注意:该代码针对Tomcat10,servlet包名前缀是“jakarta”
-
test1:直接在响应结果中写入数据,支持html标签
-
test2:响应重定向,重新请求资源(禁止请求受保护资源)
-
test3:请求转发,请求和响应信息可以继续传递(可以请求受保护资源)
SpringMVC-无需视图解析器
- 需要写全路径
package GSF.Example.ResultRedirection;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;// 请求前需要先注释掉springmvc-servlet.xml的视图解析器@Controller
public class SpringMVC_NoViewParser {@RequestMapping("/springMvc_redirection/test1")public String test1() {// 转发return "/index_1.jsp";}@RequestMapping("/springMvc_redirection/test2")public String test2() {// 转发//return "forward:/index.jsp";//return "forward:/index_1.jsp";return "forward:/WEB-INF/jsp/hello.jsp";}@RequestMapping("/springMvc_redirection/test3")public String test3() {// 重定向:不让定向到受保护的视图资源内//return "redirect:/index.jsp";return "redirect:/WEB-INF/jsp/hello.jsp";}
}
SpringMVC-有视图解析器
- 根据视图解析器的前缀和后缀,补全剩余路径即可
- 针对响应重定向,不受视图解析器的影响,写入全路径即可
package GSF.Example.ResultRedirection;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;import java.io.IOException;@Controller
public class SpringMVC_ViewParser {@RequestMapping("/springMvc_redirection_VP/test1")public String test1() throws IOException {// 转发:自动借助视图解析器补充前缀和后缀// return "index_1"; // 不行// return "/index_2"; // 行return "/jsp/hello"; // 行}@RequestMapping("/springMvc_redirection_VP/test2")public String test2() throws IOException {// 重定向:不需要视图解析器,写全路径return "redirect:/Result_Redirection/test2.jsp";}
}
数据处理-提交到后端的数据
package GSF.Example.DataProcess;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;@Controller
@RequestMapping("/data_process")
public class ProcessSubmitData {@RequestMapping("/same_name")public String test1(String name){System.out.println(name);return "/jsp/hello";}@RequestMapping("/different_name")public String test2(@RequestParam("username") String name){System.out.println(name);return "/jsp/hello";}@RequestMapping("/object")public String test3(User user){System.out.println(user);return "/jsp/hello";}
}
- test1:localhost:8080/data_process/same_name?name=123456
- test2:localhost:8080/data_process/different_name?username=123456
- test3:localhost:8080/data_process/object?name=gsf&id=1&age=15
数据处理-数据显示到前端
package GSF.Example.DataShow;import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;@Controller
public class ShowDataToView {// 第一种:ModelAndView,参考ResultRedirection/ModelAndView// ModelMap@RequestMapping("/show_data")public String test1(@RequestParam("username") String name, ModelMap model){//封装要显示到视图中的数据//相当于req.setAttribute("name",name);model.addAttribute("msg",name);System.out.println(name);return "/jsp/hello";}// Model@RequestMapping("/show_data_2")public String test2(@RequestParam("username") String name, Model model){//封装要显示到视图中的数据//相当于req.setAttribute("name",name);model.addAttribute("msg",name);System.out.println(name);return "/jsp/hello";}
}
- test1:ModelMap
- test2:Model
乱码处理
方法1-springMVC-过滤器
- 使用springMVC提供的过滤器,在web.xml中配置
<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>
- 极端情况下,对get支持不好
方法2-Tomcat修改配置文件
<Connector URIEncoding="utf-8" port="8080" protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8443" />
方法3-自定义过滤器
- 过滤器
package com.kuang.filter;import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Map;/**
* 解决get和post请求 全部乱码的过滤器
*/
public class GenericEncodingFilter implements Filter {@Overridepublic void destroy() {}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {//处理response的字符编码HttpServletResponse myResponse=(HttpServletResponse) response;myResponse.setContentType("text/html;charset=UTF-8");// 转型为与协议相关对象HttpServletRequest httpServletRequest = (HttpServletRequest) request;// 对request包装增强HttpServletRequest myrequest = new MyRequest(httpServletRequest);chain.doFilter(myrequest, response);}@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}}
- 过滤器中调用的方法
//自定义request对象,HttpServletRequest的包装类
class MyRequest extends HttpServletRequestWrapper {private HttpServletRequest request;//是否编码的标记private boolean hasEncode;//定义一个可以传入HttpServletRequest对象的构造函数,以便对其进行装饰public MyRequest(HttpServletRequest request) {super(request);// super必须写this.request = request;}// 对需要增强方法 进行覆盖@Overridepublic Map getParameterMap() {// 先获得请求方式String method = request.getMethod();if (method.equalsIgnoreCase("post")) {// post请求try {// 处理post乱码request.setCharacterEncoding("utf-8");return request.getParameterMap();} catch (UnsupportedEncodingException e) {e.printStackTrace();}} else if (method.equalsIgnoreCase("get")) {// get请求Map<String, String[]> parameterMap = request.getParameterMap();if (!hasEncode) { // 确保get手动编码逻辑只运行一次for (String parameterName : parameterMap.keySet()) {String[] values = parameterMap.get(parameterName);if (values != null) {for (int i = 0; i < values.length; i++) {try {// 处理get乱码values[i] = new String(values[i].getBytes("ISO-8859-1"), "utf-8");} catch (UnsupportedEncodingException e) {e.printStackTrace();}}}}hasEncode = true;}return parameterMap;}return super.getParameterMap();}//取一个值@Overridepublic String getParameter(String name) {Map<String, String[]> parameterMap = getParameterMap();String[] values = parameterMap.get(name);if (values == null) {return null;}return values[0]; // 取回参数的第一个值}//取所有值@Overridepublic String[] getParameterValues(String name) {Map<String, String[]> parameterMap = getParameterMap();String[] values = parameterMap.get(name);return values;}
}
总结
- 为了避免乱码问题,在可能设置编码的地方,都设置为UTF-8
- springMVC提供的过滤器,基本就够用了
Json
项目Module名称
Demo-05-SpringMVC-Json
- 代码参考:上述连接
- 该部分,文章中不贴入完整代码
什么是Json?
概念
- JSON(JavaScript Object Notation, JS 对象标记)是一种轻量级的数据交换格式,目前使用特别广泛。
- 采用完全独立于编程语言的文本格式来存储和表示数据。
- 简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。
- 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
语法格式
- 对象表示为键值对,数据由逗号分隔
- 花括号保存对象
- 方括号保存数组
Json和JavaScript的区别
JSON 是 JavaScript 对象的字符串表示法,它使用文本表示一个 JS 对象的信息,本质是一个字符串
var obj = {a: 'Hello', b: 'World'}; //这是一个对象,注意键名也是可以使用引号包裹的
var json = '{"a": "Hello", "b": "World"}'; //这是一个 JSON 字符串,本质是一个字符串
Json和JavaScript的相互转换
var obj = JSON.parse('{"a": "Hello", "b": "World"}');
//结果是 {a: 'Hello', b: 'World'}var json = JSON.stringify({a: 'Hello', b: 'World'});
//结果是 '{"a": "Hello", "b": "World"}'
Controller返回Json数据:jackson
Module准备
1、导包
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.9.8</version>
</dependency>
2、建立Module,完成springmvc-servlet.xml、web.xml配置(大差不差,不再详细贴出代码)
Controller核心代码
package GSF.Example.Controller;import GSF.Example.Pojo.User;
import GSF.Example.Utils.JsonUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;//@Controller // 使用Controller,需要在方法上添加@ResponseBody注解,保证返回json形式数据
@RestController // 使用RestController,保证返回的都是json形式数据
public class UserController {@RequestMapping("/json1")//@RequestMapping(value = "/json1",produces = "application/json;charset=utf-8") // 设置返回数据字符集,避免乱码//@ResponseBodypublic String json1() throws JsonProcessingException {//创建一个jackson的对象映射器,用来解析数据ObjectMapper mapper = new ObjectMapper();//创建一个对象User user = new User("秦疆1号", 3, "男");//将我们的对象解析成为json格式String str = mapper.writeValueAsString(user);System.out.println(str);//由于@ResponseBody注解,这里会将str转成json格式返回;十分方便return str;}@RequestMapping("/json2")public String json2() throws JsonProcessingException {//创建一个jackson的对象映射器,用来解析数据ObjectMapper mapper = new ObjectMapper();//创建一个对象User user1 = new User("秦疆1号", 3, "男");User user2 = new User("秦疆2号", 3, "男");User user3 = new User("秦疆3号", 3, "男");User user4 = new User("秦疆4号", 3, "男");List<User> list = new ArrayList<User>();list.add(user1);list.add(user2);list.add(user3);list.add(user4);//将我们的对象解析成为json格式String str = mapper.writeValueAsString(list);return str;}// 默认返回一个时间戳,是一个lang整数值@RequestMapping("/json3")public String json3() throws JsonProcessingException {ObjectMapper mapper = new ObjectMapper();//创建时间一个对象,java.util.DateDate date = new Date();//将我们的对象解析成为json格式String str = mapper.writeValueAsString(date);return str;}// 通过定义返回时间的格式返回数据@RequestMapping("/json4")public String json4() throws JsonProcessingException {ObjectMapper mapper = new ObjectMapper();//不使用时间戳的方式mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);//自定义日期格式对象SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//指定日期格式mapper.setDateFormat(sdf);Date date = new Date();String str = mapper.writeValueAsString(date);return str;}@RequestMapping("/json5")public String json5() throws JsonProcessingException {Date date = new Date();String json = JsonUtils.getJson(date); // 将代码抽出来,自定义一个工具类return json;}
}
统一处理乱码问题
- springmvc-servlet.xml配置
<!--Jackson统一解决乱码问题-->
<mvc:annotation-driven><mvc:message-converters register-defaults="true"><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>
Controller返回Json数据:fastjson
Module准备
1、导包
<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.60</version>
</dependency>
2、建立Module,完成springmvc-servlet.xml、web.xml配置(大差不差,不再详细贴出代码)
fastjson三大核心类
核心类 | 代表 | 解释 |
---|---|---|
JSONObject | 代表 json 对象 | JSONObject实现了Map接口,猜想 JSONObject底层操作是由Map实现的 JSONObject对应json对象,通过各种形式的get()方法可以获取json对象中的数据,也可利用诸如size(),isEmpty()等方法获取"键:值"对的个数和判断是否为空 其本质是通过实现Map接口并调用接口中的方法完成的 |
JSONArray | 代表 json 对象数组 | 内部是有List接口中的方法来完成操作的 |
JSON | 代表 JSONObject和JSONArray的转化 | JSON类源码分析与使用 主要是实现json对象,json对象数组,javabean对象,json字符串之间的相互转化 |
数据类型相互转换
- json对象,json对象数组,javabean对象,json字符串之间的相互转化
package GSF.Example.Controller;import GSF.Example.Pojo.User;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;import java.util.ArrayList;
import java.util.List;public class FastJsonDemo {public static void main(String[] args) {//创建一个对象User user1 = new User("秦疆1号", 3, "男");User user2 = new User("秦疆2号", 3, "男");User user3 = new User("秦疆3号", 3, "男");User user4 = new User("秦疆4号", 3, "男");List<User> list = new ArrayList<User>();list.add(user1);list.add(user2);list.add(user3);list.add(user4);System.out.println("*******Java对象 转 JSON字符串*******");String str1 = JSON.toJSONString(list);System.out.println("JSON.toJSONString(list)==>"+str1);String str2 = JSON.toJSONString(user1);System.out.println("JSON.toJSONString(user1)==>"+str2);System.out.println("\n****** JSON字符串 转 Java对象*******");User jp_user1=JSON.parseObject(str2,User.class);System.out.println("JSON.parseObject(str2,User.class)==>"+jp_user1);System.out.println("\n****** Java对象 转 JSON对象 ******");JSONObject jsonObject1 = (JSONObject) JSON.toJSON(user2);System.out.println("(JSONObject) JSON.toJSON(user2)==>"+jsonObject1.getString("name"));System.out.println("\n****** JSON对象 转 Java对象 ******");User to_java_user = JSON.toJavaObject(jsonObject1, User.class);System.out.println("JSON.toJavaObject(jsonObject1, User.class)==>"+to_java_user);}
}
Ajax
学一半,后边再说吧,有点学不明白
拦截器:Interceptor
什么是拦截器?
概念
SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。开发者可以自己定义一些拦截器来实现特定的功能
过滤器和拦截器的区别
过滤器 | 拦截器 |
---|---|
servlet规范中的一部分,任何java web工程都可以使用 | 拦截器是SpringMVC框架自己的,只有使用了SpringMVC框架的工程才能使用 |
通过配置,可以对所有要访问的资源进行拦截 | 是AOP思想的具体应用,只会拦截访问的控制器方法,如果访问的是jsp/html/css/image/js是不会进行拦截的 |
拦截器使用
- java代码
package GSF.Example.Interceptor;import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;public class MyInterceptor implements HandlerInterceptor {//在请求处理的方法之前执行//如果返回true执行下一个拦截器//如果返回false就不执行下一个拦截器public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {System.out.println("------------处理前------------");return true;}//在请求处理方法执行之后执行public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {System.out.println("------------处理后------------");}//在dispatcherServlet处理后执行,做清理工作.public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {System.out.println("------------清理------------");}
}
- springmvc-servlet.xml配置
<!--关于拦截器的配置-->
<mvc:interceptors><mvc:interceptor><!--/** 包括路径及其子路径--><!--/admin/* 拦截的是/admin/add等等这种 , /admin/add/user不会被拦截--><!--/admin/** 拦截的是/admin/下的所有--><mvc:mapping path="/**"/><!--bean配置的就是拦截器--><bean class="GSF.Example.Interceptor.MyInterceptor"/></mvc:interceptor>
</mvc:interceptors>
文件上传和下载
Module准备
1、建立相关Module
2、导包
<!--文件上传有关的第三方库-->
<dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.3.3</version>
</dependency>
3、springmvc-servlet.xml配置bean!!
<!--文件上传配置-->
<bean id="multipartResolver" class="org.springframework.web.multipart.support.StandardServletMultipartResolver"/>
- 这个bean的名字必须叫这个,不能为其他的
核心代码展示
前端页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<body>
<h2>Hello World!</h2><h1>上传文件</h1>
<h2>上传单个文件,java原生代码实现</h2>
<form action="/upload" enctype="multipart/form-data" method="post"><input type="file" name="file"/><input type="submit" value="upload">
</form><h2>上传单个文件,调file.TransferTo保存文件代码</h2>
<form action="/upload2" enctype="multipart/form-data" method="post"><input type="file" name="file"/><input type="submit" value="upload">
</form><h2>上传多个文件(多个文件选择框实现),调file.TransferTo保存文件代码</h2>
<form action="/upload3" enctype="multipart/form-data" method="post"><input type="file" name="file"/><input type="file" name="file"/><input type="submit" value="upload">
</form><h2>上传多个文件(单个文件选择框实现),调file.TransferTo保存文件代码</h2>
<form action="/upload3" enctype="multipart/form-data" method="post"><input type="file" name="file" multiple/><input type="submit" value="upload">
</form>
</body><h1>下载文件</h1>
<h2>java原生代码实现</h2>
<a href="/download">点击下载</a>
</html>
Controller
package GSF.Example.Controller;import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;import java.io.*;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;@Controller
public class FileController {@RequestMapping("/upload")public String fileUpload_onefile_manualsave(@RequestParam("file") MultipartFile file , HttpServletRequest request) throws IOException {//获取文件名 : file.getOriginalFilename();String uploadFileName = file.getOriginalFilename();//如果文件名为空,直接回到首页!if ("".equals(uploadFileName)){return "redirect:/index.jsp";}System.out.println("上传文件名 : "+uploadFileName);//上传路径保存设置String path = request.getServletContext().getRealPath("/upload");System.out.println(path);//如果路径不存在,创建一个File realPath = new File(path);if (!realPath.exists()){realPath.mkdir();}System.out.println("上传文件保存地址:"+realPath);InputStream is = file.getInputStream(); //文件输入流OutputStream os = new FileOutputStream(new File(realPath,uploadFileName)); //文件输出流//读取写出int len=0;byte[] buffer = new byte[1024];while ((len=is.read(buffer))!=-1){os.write(buffer,0,len);os.flush();}os.close();is.close();return "redirect:/index.jsp";}/** 采用file.Transto 来保存上传的文件*/@RequestMapping("/upload2")public String fileUpload2(@RequestParam("file") MultipartFile file, HttpServletRequest request) throws IOException {//上传路径保存设置String path = request.getServletContext().getRealPath("/upload");File realPath = new File(path);if (!realPath.exists()){realPath.mkdir();}//上传文件地址System.out.println("上传文件保存地址:"+realPath);//通过CommonsMultipartFile的方法直接写文件(注意这个时候)file.transferTo(new File(realPath +"/"+ file.getOriginalFilename()));return "redirect:/index.jsp";}@RequestMapping("/upload3") // 等价于 @RequestMapping(value = "/upload", method = RequestMethod.POST)public String fileUpload(HttpServletRequest req, @RequestParam("file") MultipartFile[] files) throws IOException {List<String> pathStrs = new ArrayList<String>();if(files.length > 0){//循环多次上传多个文件for (MultipartFile file : files) {if(!file.isEmpty()){//上传路径保存设置String path = req.getServletContext().getRealPath("/upload");File realPath = new File(path);if (!realPath.exists()){realPath.mkdir();}//上传文件地址System.out.println("上传文件保存地址:"+realPath);//通过CommonsMultipartFile的方法直接写文件(注意这个时候)file.transferTo(new File(realPath +"/"+ file.getOriginalFilename()));}}}return "redirect:/index.jsp";}// 下载文件的步骤:// 1、设置response响应头// 2、读取文件:InputStream// 3、写出文件:OutputStream// 4、执行操作// 5、关闭流(先开的流后关)@RequestMapping(value="/download")public String downloads(HttpServletResponse response , HttpServletRequest request) throws Exception{//要下载的图片地址String path = request.getServletContext().getRealPath("/upload");String fileName = "基础语法.jpg";//1、设置response 响应头response.reset(); //设置页面不缓存,清空bufferresponse.setCharacterEncoding("UTF-8"); //字符编码response.setContentType("multipart/form-data"); //二进制传输数据//设置响应头response.setHeader("Content-Disposition","attachment;fileName="+ URLEncoder.encode(fileName, "UTF-8"));File file = new File(path,fileName);//2、 读取文件--输入流InputStream input=new FileInputStream(file);//3、 写出文件--输出流OutputStream out = response.getOutputStream();byte[] buff =new byte[1024];int index=0;//4、执行 写出操作while((index= input.read(buff))!= -1){out.write(buff, 0, index);out.flush();}out.close();input.close();return null;}
}