第一天
Spring的注解编程
注解与xml形式的作用是一样的
xml中做的配置
对象管理
是否单例 scope=“singleton | prototype”
机制 什么时候加载 scope lazy-init
自动注入 autowire=“byName”
当前对象创建时执行的方法 method-init=“test1”
当前对象销毁时执行的方法 method-destroy=“test2”
注解中做的配置
1.用于替代原有的bean标签 对象创建
@Component
MVC分层架构更加清晰
控制层@Controller
业务层@Service
持久层@Repository
2.用于替代原有bean标签中的属性 对象机制的管理
@Scope(“singleton | prototype”)
@Lazy(true | false)
@PostConstructor 当前对象创建时执行的方法
@ProDestroy 当前对象销毁时执行的方法
3.用于对象创建后的自动注入
@Autowired byName方式 byType方式
@Qualifier 搭配着上面的注解做一个对象的微调整
@Value 支持SpEL
@Resource (使用时必须在括号中指定名字)不是Spring家族的注解
4.以上注解都是写在自己定义的类中
有些时候类不是我们写的 JdbcTemplate DataSource
还想要通过注解的方式去管控这些对象
4.1.自己定义类
类中定义方法,作用是为了创建那些需要管控的对象
方法通常有返回值,就是那些类的对象
方法上面添加@Bean
4.2.需要在自己写的类上面添加注解---->核心xml文件一样 让spring知道 读取我
@Configuration
4.3.改变了原有读取xml文件的过程 创建工厂的方式也要相应进行改变
BeanFactory factory = new AnnotationConfigApplicationContext(xxx.class);
4.4.如果我们想要添加一些外部文件的信息
可以采用@PropertySource引入外部文件中的内容
内容可以利用SpEL来读取
4.5.自定义的类中可能会有很多的方法
其实可以将自定义类拆分 好多个小配置类
通过@Import(xxx.class)引入小配置类
=======================================================================================================
对象的管控
SpringIOC SpringDI SpringAOP
用于与数据库交互
SpringJDBC
用于做任务处理
SpringTimer
用于做请求与响应的处理
SpringMVC
回顾一下之前的请求与响应
1.导包 别人写好的类
2.主配置 web.xml DispatcherServlet *.do
3.小配置 请求--真实类(方法) 对应关系
4.浏览器发请求 找到真实类
5.请求参数 真实类方法中写参数变量就行了----参数的IOC和DI
普通类型 String int map类型 domain类型
6.响应信息 返回值void String ModelAndView
第二天
使用流程
1.导入jar包(8个jar包)
SpringMVC应该是Spring框架的一个部分,类似于SpringJDBC
包名字 web mvc
SpringMVC充当了控制层的管理
SpringMVC中间也会存在一个自己的配置 建议用注解
请求 响应 Controller层次
Controller层次的类对象通常会交给Spring来管理 @Controller
SpringMVC使用依赖于Spring(核心的包 beans core)
2.核心配置web.xml 核心入口执行类DispatcherServlet
<servlet>
<servlet-name>mvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>mvc</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
自己写一个Controller类
实现
org.springframework.web.servlet.mvc.Controller接口
重写方法
@Override
public ModelAndView handleRequest(HttpServletRequest arg0, HttpServletResponse arg1) throws Exception {
return null;
}
3.小配置(请求名字----真实资源对应关系) properties annotation
配置ApplicationContext.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/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!--配置一个请求和真实资源(Controller-Bean)的关系 -->
<!--将Controller这个类的对象交给Spring容器管理 -->
<bean id="atmController" class="controller.AtmController" />
<!-- 请求和这个类对象之间的映射关系 通过请求找到他 -->
<!-- DispatcherServlet类有一个自己的小弟 负责处理映射关系 SimpleUrlHandlerMapping -->
<bean id="simpleUrlHandlerMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<!-- 真实的请求和类对应关系 -->
<prop key="atmController.do">atmController</prop>
</props>
</property>
</bean>
</beans>
发送请求localhost:8080/SpringMVC01/atmController.do
提示异常Servlet.init() for servlet [mvc] threw exception
java.io.FileNotFoundException: Could not open ServletContext resource [/WEB-INF/mvc-servlet.xml]
之前是配置在src根目录下ApplicationContext.xml
发现这里是一个web项目
SpringMVC默认去web-inf文件夹下找配置文件
SpringMVC默认的配置文件名 <servlet-name>标签里面的名字 - servlet.xml
所以有两种解决方式
方式一,将 ApplicationContext.xml 文件放置在规定的位置,且名字为 标签里面的名字 - servlet.xml
方式二, 如果想要修改默认的配置路径
可以在web.xml中 servlet标签内添加init-param
<servlet>
<servlet-name>mvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:ApplicationContext.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>mvc</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
4.浏览器可以发送请求
========================================================================================================================
以上的流程虽然可以实现
但是相比较而言跟最早的Tomcat一样
Controller类有很多规则 耦合度太高了
基于xml形式的配置相较于注解稍微麻烦了一些
将上述的流程改成注解的方式 controller的规则去掉
Tomcat核心web.xml没动的
小配置(Spring的核心配置)
所有的xml形式去掉了
扫描所有带注解的包
<context:component-scan base-package="controller"/>
开启请求响应注解的处理(加载HandlerMapping类)
<mvc:annotation-driven/>
具体如下
<?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
https://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">
<!--将刚才的bean标签配置去掉 改为开启注解扫描 -->
<context:component-scan base-package="controller"/>
<!-- 上述一堆删掉 添加一个新的配置 开启注解驱动 相当于是加载了HandlerMapping类对象 -->
<mvc:annotation-driven/>
</beans>
原有的Controller类就不用了那么多规则啦
类上面添加@Controller注解
类上面添加@RequestMapping("test.do")注解------请求名字对应
类中的方法上添加@RequestMapping注解----请求执行的方法.
第三天
发送请求----DispatcherServlet
一个请求对应一个Servlet类(继承关系 重写方法)
如何让Servlet类减少
DAO Service层都是跟表格domain个数对应
想要变成一个请求对应一个Servlet类中的一个方法
发送请求的时候Servlet类中只有一个方法被认识(service doPost/doGet)
将Servlet类中的service方法改变了一种方式
原来service方法是做具体的控制 1.取值 2.调用业务 3.响应
将service方法升级成一个"小总管" 1.接收请求 2.分析(哪个方法) 3.分发
后来又发现每一个Servlet类中都有一个"小总管"
"小总管提取出来了" DispatcherServlet
1.接收请求
2.分析(哪个类 哪个方法)
3.分发让方法执行
4.过程中还做了请求参数处理 响应信息的处理 IOC+DI
========================================================================================
0.@RequestMapping注解放置在什么位置
@Target({ElementType.TYPE, ElementType.METHOD})
可以放置在类上面(通常这个类应该是Controller)
可以放置在方法上面(Controller类中某个具体方法)
1.如何发送请求
#方式一: 发送时候直接写 类名.do
在类上面写注解@RequestMapping(path | value = "类名.do")
在类中只有一个方法 方法上面添加注解@RequestMapping
@Controller
@RequestMapping(value="a.do" )
public class AtmController{
@RequestMapping
public void test() {
System.out.println("test执行了");
}
}
#方式二:发送请求时候 类名字.do?method=方法名
类上面写注解(类名.do)
方法上面写注解(params={""})
(请求结构就比较麻烦 类名.do?method=方法名)
(类的注解也很麻烦 类上一个 方法上一个 方法的这个注解还有params参数)
@Controller
@RequestMapping(value="a.do" )
public class AtmController{
@RequestMapping( params = {"name=admin","pass="})
public void test() {
System.out.println("test执行了");
}
@RequestMapping()
public void test1() {
System.out.println("test1执行了");
}
}
方式三: 发送请求的时候 xxx.do (xxx通常是一个方法名)
类上面就不用写注解啦
类中方法的上面写注解 注解中写与请求对应的那个 xxx.do
@Controller
@RequestMapping
public class AtmController{
@RequestMapping(value="a.do" )
public void testa() {
System.out.println("a执行了");
}
@RequestMapping(value="b.do" )
public void testb() {
System.out.println("b执行了");
}
}
2.@RequestMapping注解中的"方法"
String name() default "";
//路径
@AliasFor("path")
String[] value() default {};
//路径
@AliasFor("value")
String[] path() default {};
//RequestMethod.GET,RequestMethod.POST,...
RequestMethod[] method() default {};
//参数
String[] params() default {};
//请求头
String[] headers() default {};
第四天
研究一下SpringMVC提供的接收参数方式
1.方法中直接传入变量
变量直接接收 要求变量名字与前面传递的key一致
即便是一个变量也需要对应key一致 否则接收不到
如果变量和前面传递的key不一致,可以利用注解@RequestParam(“key”)放在参数的前面
参数的类型可以不一定是String ,int可以
@Controller
@RequestMapping
public class AtmController{
//localhost:8080/SpringMVC01/test1.do?name=zhangsan&pass=asd123fgh
@RequestMapping(value="test1.do" )
public void test1(String name,String pass) {
System.out.println("test1"+name);
System.out.println(pass);
}
//localhost:8080/SpringMVC01/test2.do?param1=zhangsan¶m2=asd123fgh
@RequestMapping(value="test2.do" )
public void test2(@RequestParam("param1") String name, @RequestParam("param2") String pass) {
System.out.println("test2"+name);
System.out.println(pass);
}
}
2.方法中直接传入实体对象
如果传递的参数可以组合成一个对象
可以用对象直接接收
对象中的属性名和前面传递的key一致
如果对象里面还有对象属性(套娃)
只需要在请求的时候写 对象的属性.属性名即可
比如User中有一个Wallet对象 Wallet中有个money属性
wallet.money
@Controller
@RequestMapping
public class AtmController{
//localhost:8080/SpringMVC01/test3.do?name=zhangsan&pass=asd123fgh
@RequestMapping(value="test3.do" )
public void test3(Atm atm) {
System.out.println("test3"+atm);
}
}
当Person对象里有一个Atm属性时
@Controller
@RequestMapping
public class AtmController{
//localhost:8080/SpringMVC01/test4.do?name=zhangsan&age=123&atm.name=zhangsan&atm.pass=asd123fgh
@RequestMapping(value="test4.do" )
public void test4(Person person) {
System.out.println("test4"+person);
}
}
list/set一致
当Person对象里有一个List属性时
<form action="test5.do" method="post">
<input type="text" name="name">
<input type="text" name="age">
<input type="text" name="atms[0].name">
<input type="text" name="atms[0].pass">
<input type="text" name="atms[1].name">
<input type="text" name="atms[1].pass">
<input type="submit" value="go">
</form>
@Controller
@RequestMapping
public class AtmController{
@RequestMapping(value="test5.do" )
public void test5(Person person) {
System.out.println("test5"+person);
}
}
当Person对象里有一个Map属性时
<form action="test6.do" method="post">
<input type="text" name="name">
<input type="text" name="age">
<input type="text" name="atms['param1'].name">
<input type="text" name="atms['param1'].pass">
<input type="text" name="atms['param2'].name">
<input type="text" name="atms['param3'].pass">
<input type="submit" value="go">
</form>
@Controller
@RequestMapping
public class AtmController{
@RequestMapping(value="test6.do" )
public void test6(Person person) {
System.out.println("test6"+person);
}
}
3.方法中传入Map集合的方式
可以使用Map类型来接收请求的参数的
前提是 Map参数的前面 必须添加@RequestParam
否则Map是无法接收到参数的
4.方法中传递原生Request对象
直接在方法中传递参数变量即可接收
HttpServletRequest
HttpServletResponse
第五天
接收请求参数的时候产生的中文乱码问题
可以利用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>
如何自定义类型转换器
Converter
1.自定义一个类
2.实现上面这个接口
接口是支持泛型 Converter<String,Type>
3.重写接口中的转换方法
方法内部该做具体转化的事情
方法会返回一个转化后的对象
4.告知Spring这里有一个自定义的类型转换器
需要让Spring帮我们加载并管理起来
配置
在ApplicationContext.xml中配置
<!-- 加载自定义的类型转换器 -->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<!-- 自己写的转换类 -->
<bean class="util.StringToConverters"/>
</property>
</bean>
<!-- 手动配置这个类的驱动 -->
<mvc:annotation-driven conversion-service="conversionService"/>
-----------------------------------------------------------
接收请求参数的时候
@RequestParam注解 写在变量前面 或者 Map前面
@RequestHeader注解 接收协议头数据
放在方法参数里 @RequestHeader("Accept-Language")String header
@CookieValue
放在方法参数里 @CookieValue("JSESSIONID")String cookieValue
@RequestBody注解(JSON) 接收 key=value;key=value 放在参数前面
放在方法参数里 @RequestBody String body
注解只能接收post请求方式 post请求是存在协议体(参数)
get请求只有协议头没有协议体
@ResponseBody注解(JSON) 响应
@ModelAttribute注解
放在某一个方法上面@ModelAttribute("test.do")
方法在请求的方法执行之前先执行的(块 init)
第六天
浏览器发送一个请求
请求xxx.do
通过核心的"小总管"DispatcherServlet分发
具体的类中的某个具体的方法
通过方法中的参数列表接收请求的信息
方法中调用业务层执行具体逻辑-----service.login(name,pass);----dao----DB
根据结果进行响应信息的处理 控制层---控制响应信息View
处理响应信息的方式
1.采用原生response对象,获取输出流的方式进行直接响应
方法返回值void就可以了
方法的参数HttpServletResponse response
方法的内部获取PrintWriter输出流对象 response.getWriter();
writer.write("<>");
如果响应信息中含有中文
需要在方法的最上面设置中文字符集的解析方式
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
2.转发 request.getRequestDispatcher().forward(request,response);
3.重定向response.sendRedirect();
以上这种方式并不好,不建议大家使用
利用"小总管"来帮我们处理转发和重定向的事情
方法的返回值利用String类型
方法内部return需要转发/重定向的资源位置
重定向需要在资源名字之前添加 redirect:xxx.jsp
转发也可以填写关键字 forward:xxx.jsp 默认不写就当做转发啦
第七天
继续研究一下如何处理响应信息
void String以外
现在开发项目通常都是前后端分离形式
JSP(编译过程 性能不好) 静态数据+动态数据 一次请求 一次拼接 一次响应
静态数据先响应 动态数据发送异步请求 而后在浏览器端进行拼接展示
HTML+AJAX+JSON(JS操作)
String 转发路径 AJAX请求直接响应
Map domain--->AJAX响应--JSON
总结
响应信息方式如下
void表示不需要框架帮我们处理响应信息
只能自己通过原生response获取输出流 回写响应信息
String(没有@ResponseBody注解)
表示请求框架帮我们处理响应信息路径的转发或重定向
forward:
redirect:
通常发送异步请求 map domain list set
表示需要框架帮我们处理响应信息 将这些对象转化成JSON形式响应回去
1.导包jackson(core databind annotations)
2.方法上面添加@Responsebody注解告知框架帮我们解析
注解@ResponseBody,可以放在方法的上面或者返回值的前面
具体如下
<html>
<head>
<script type="text/javascript">
window.onload = function(){
document.getElementById("i1").onclick = function(){
var xhr = new XMLHttpRequest();
/* 可以在这里传递参数给Controller */
xhr.open("POST","ajax.do?name=zhangsan",true);
xhr.onreadystatechange = function(){
if(xhr.readyState==4 && xhr.status==200){
alert(xhr.responseText);
}
}
xhr.send();
}
}
</script>
<title>$Title$</title>
</head>
<body>
<input type="button" value="go" id="i1">
</body>
</html>
@ResponseBody
@RequestMapping("ajax.do")
public Atm test1(String name) {
System.out.println(111);
System.out.println(name);
//将对象转为JSON返回
//导入json相关的jar包(三个)
//添加注解@ResponseBody,可以放在方法的上面或者返回值的前面
return new Atm("张三","123",99F);
}
发送请求如果是JSON形式该如何处理
发送端设置JSON形式
接收端(服务端的方法) 参数上面@RequestBody即可 domain对象接收
<html>
<head>
<script type="text/javascript">
window.onload = function(){
document.getElementById("i1").onclick = function(){
var xhr = new XMLHttpRequest();
/* 可以在这里传递参数给Controller */
xhr.open("POST","ajax.do",true);
//如果发送json数据,需要告知浏览器解析规则,如果不是发送json数据,下面这一行不用写
xhr.setRequestHeader("Content-type","application/json;charset=UTF-8")
xhr.onreadystatechange = function(){
if(xhr.readyState==4 && xhr.status==200){
alert(xhr.responseText);
}
}
/* 也可以在这里发送数据给Controller*/
xhr.send('{"pass":"asd123","name":"zhangsan"}');
}
}
</script>
<title>$Title$</title>
</head>
<body>
<input type="button" value="go" id="i1">
</body>
</html>
接收端的方法参数前面添加@RequestBody()注解
@Controller
@RequestMapping
public class AtmController{
@ResponseBody
@RequestMapping("ajax.do")
public Atm test1(@RequestBody() Atm atm) {
System.out.println(111);
System.out.println(atm);
//将对象转为JSON返回
//导入json相关的jar包(三个)
//添加注解@ResponseBody,可以放在方法的上面或者返回值的前面
return new Atm("张三","123",99F);
}
}
第八天
利用控制层的方法返回值来处理响应
1.void 不用框架帮我们处理 需要自己处理 response.getWriter() write()
2.String 让框架帮我们去做转发、重定向 String----资源名字
forward: redirect:
3.Object domain String Map List----->JSON
1.处理工具---jar
2.告知框架方法的返回值需要解释 @Responsebody
4.ModelAndView
存储信息
转发的路径
服务端业务层可能会产生一些数据
这些数据我们需要存入作用域中带走
request.setAttribute();
1.可以利用原生Map来处理
Map接收请求参数(@RequestParam)
Map可以返回数据(@ResponseBody)
2.可以利用Model 或 ModelMap
Model底层继承ModelMap
存储数据之前不需要自己创建
只需将变量放置在方法的参数里即可 框架会帮我们自动注入
m.addAttribute("",object);
但是只能存储数据
不能携带转发的路径资源
对象不需要返回
3.可以利用ModelAndView
不能放在方法的参数里 框架不会帮我们注入
需要用的时候 自己new即可
mv.addObject("key",object);
mv.setViewName("xxx.jsp");
可以包含数据和转发路径
需要将自己创建的mv对象返回
4.如果想要将值存入session作用域范畴内
需要在类名上面添加注解
@SessionAttributes({"key1","key2","key3"})
当m.addAttribute("",object);或者mv.addObject("key",object);时,
如果key的值和SessionAttributes注解里得值相同,会先存入request内,再存入session内
第九天 异常的处理
1.自己定义一个异常类MyException将所有的异常都统一捕获 变成一个唯一的异常 交给总管
public class MyException {
private String mess;
public MyException() {
super();
// TODO Auto-generated constructor stub
}
public MyException(String mess) {
super();
this.mess = mess;
}
}
将可能产生异常的代码用try包起来,并且在catch里抛出异常throw new MyException(“异常了”);
2.自己定义一个异常处理类ExceptionResolver(核心)(处理异常 做转发 响应) 实现规则
实现接口HandlerExceptionResolver
重写方法public ModelAndView resolveException(request,response,object,exception){
判断一下exception对象是否是我们自己抛出
创建ModelAndView对象 存储信息 转发路径 error.jsp
return mv;
}
具体如下
public class ExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2,
Exception e) {
ModelAndView mv= new ModelAndView();
//验证捕获的异常是不是抛出的
if(e instanceof MyException) {
//到这里说明代码产生异常了
mv.setViewName("error.jsp");
mv.addObject("rtv",e.getMessage());
}
return mv;
}
}
3.告知Spring将我们自己定义的处理类管理起来(配置文件 xml 注解)
自己定义的处理类上面添加@Component注解(别忘了扫描包)
第十天
SpringMVC的拦截器(Interceptor)
原生Tomcat时候
Servlet----资源类
1.请求 2.找业务 3.响应处理(拼接响应信息String<><>)
JSP(Java Server Page)----本质就是Servlet
帮助Servlet服务的 响应拼接 静态资源+动态数据
静态动态分离 HTML+AJAX+JSON
Filter-----过滤器 特殊的Servlet
责任链设计模式
动态代理机制----AOP设计思想
SpringMVC的拦截器可以理解为是以前的Filter
在真正到达资源(Controller---Servlet)之前做事情的
SpringAOP----自己定义类和方法---交给Spring帮我们管理
拦截器使用流程
1.自己定义一个拦截器的类(规则)
继承HandlerInterceptorAdapter
或者 实现HandlerInterceptor(接口中三个方法都是default修饰)
2.自定义类的方法需要重写
preHandle 预先处理(controller之前执行) SpringAOP前置
返回true表示放行,返回false表示不放行,如果不放行可以用req转发或重定向
postHandle 请求后处理(controller之后执行) SpringAOP后置
afterCompletion 完成后处理(controller执行完毕后)
3.配置ApplicationContext.xml文件配置(告知Spring框架有一个拦截器 帮我们进行管理)
过滤器Filter 拦截器Interceptor
Tomcat容器提供的 SpringMVC框架提供
没有框架的时候可以 必须有框架支持
配置web.xml Spring核心文件ApplicationContext.xml "小总管" /* *.do
处理所有请求 处理Servlet请求
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/*">
<bean class="自定义类1">
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/*">
<bean class="自定义类2">
</mvc:interceptor>
</mvc:interceptors>
第十一天
文件上传/下载
依赖于Apache提供的两个jar
commons-io
commons-fileupload
基于SpringMVC的方式
1.配置一个文件解析器 CommonsMultipartResolver
2.自己写一个Controller
方法内部像之前一样接收参数即可
文件参数MultipartFile类型 变量名与前面的key一致
3.用MultipartFile对象做文件的传输
transferTo(new File("上传路径"))
第十二天
知识回顾
文件上传问题
1.导包 fileupload commons-io
2.DiskFileItemFactory ServletFileUpload parseRequest
3.List
4.判断是否为表单 item.isFormField()
item.getFieldName
item.getString(“UTF-8”)
5.文件对象
item.getName()
item.write(new File(“上传路径”));
基于SpringMVC方式
1.导包
2.配置文件解析器
3.Controller类中做简单操作即可
方法参数可以直接用变量来接收
String text
MultipartFile upload
4.获取文件名字 文件内容 传输
upload.getOriginalFilename();
upload.transferTo(new File(“上传路径”));