Java框架-SpringMVC的应用(json数据交互、控制器方法返回值、文件上传)

1. 搭建SpringMVC开发环境

1.1 创建项目,添加依赖


<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0modelVersion>

    <groupId>com.azuregroupId>
    <artifactId>day56project_SpringMVC_day2artifactId>
    <version>1.0-SNAPSHOTversion>

    <dependencies>
        
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-contextartifactId>
            <version>5.0.2.RELEASEversion>
        dependency>
        
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-webmvcartifactId>
            <version>5.0.2.RELEASEversion>
        dependency>
        
        <dependency>
            <groupId>javax.servletgroupId>
            <artifactId>servlet-apiartifactId>
            <version>2.5version>
        dependency>
        <dependency>
            <groupId>javax.servletgroupId>
            <artifactId>jsp-apiartifactId>
            <version>2.0version>
        dependency>
        
        <dependency>
            <groupId>log4jgroupId>
            <artifactId>log4jartifactId>
            <version>1.2.17version>
        dependency>

    dependencies>
    
project>

1.2 web.xml配置


<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns="http://java.sun.com/xml/ns/javaee"
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
   version="2.5">

   
   <servlet>
      <servlet-name>DispatcherServletservlet-name>
      <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
      
      <init-param>
         <param-name>contextConfigLocationparam-name>
         <param-value>classpath:springMVC.xmlparam-value>
      init-param>
      <load-on-startup>1load-on-startup>
   servlet>
   
   <servlet-mapping>
      
      <servlet-name>DispatcherServletservlet-name>
      <url-pattern>/url-pattern>
   servlet-mapping>
web-app>

1.3 springMVC.xml


<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 http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    
    <context:component-scan base-package="com.azure">context:component-scan>
    
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/pages/">property>
        <property name="suffix" value=".jsp">property>
    bean>
    
    <mvc:annotation-driven>mvc:annotation-driven>
beans>

1.4 测试页面index.html

由于在web.xml中前端控制器的拦截规则是/,动态资源(jsp)不会被拦截,而静态资源(如html、css、js等)默认不能访问。

1.4.1 拦截路径设为/时静态资源无法访问的原因分析

  • tomcat服务器访问任何资源都是通过servlet把资源返回到浏览器客户端。

  • 而访问静态资源不是使用servlet程序,而是默认通过DefaultServlet(缺省servlet)把静态资源返回到客户端中。该缺省servlet在tomcat服务器启动时默认就建立:

    Java框架-SpringMVC的应用(json数据交互、控制器方法返回值、文件上传)_第1张图片

  • 而我们在项目中配置拦截的路径是/,则所有的资源都会进入我们项目新建的dispatcherServlet,而不会经过DefaultServlet,从而导致静态资源无法被返回。

  • 所以解决方式有两种:修改放行资源路径,重新配置DefaultServlet.

1.4.2 指定放行路径对静态资源放行

  • 将资源放入包中,然后在springMVC.xml中指定放行资源路径
  • 也可以单独指定放行的资源,但是效率差
  • 注意:/pages/*/panges/**两种写法的差别
1.4.2.1 springMVC.xml配置调整

<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 http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    
    <context:component-scan base-package="com.azure">context:component-scan>

    
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/pages/">property>
        <property name="suffix" value=".jsp">property>
    bean>

    
    <mvc:annotation-driven>mvc:annotation-driven>

    
    
    
    <mvc:resources mapping="/index.html" location="/index.html"/>

    
    
    
    <mvc:resources mapping="/pages/**" location="/pages/"/>
    <mvc:resources mapping="/css/**" location="/css/"/>
    <mvc:resources mapping="/js/**" location="/js/"/>
    <mvc:resources mapping="/image/**" location="/image/"/>

beans>

1.4.3 使用tomcat的DefaultServlet处理静态资源

  • 重新配置使用缺省servlet处理静态资源
1.4.3.1 web.xml配置调整

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns="http://java.sun.com/xml/ns/javaee"
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
   version="2.5">

   
   <servlet>
      <servlet-name>DispatcherServletservlet-name>
      <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
      
      <init-param>
         <param-name>contextConfigLocationparam-name>
         <param-value>classpath:springMVC.xmlparam-value>
      init-param>
      <load-on-startup>1load-on-startup>
   servlet>
   
   <servlet-mapping>
      
      <servlet-name>DispatcherServletservlet-name>
      <url-pattern>/url-pattern>
   servlet-mapping>
   
   
   <servlet-mapping>
      <servlet-name>defaultservlet-name>
      <url-pattern>*.htmlurl-pattern>
   servlet-mapping>
   <servlet-mapping>
      <servlet-name>defaultservlet-name>
      <url-pattern>*.jsurl-pattern>
   servlet-mapping>
web-app>

2. 往域中存放数据

2.1 Model和ModelMap类型

  • 作用:作为方法参数时可以将数据存储到request域中
  • 使用方法:Model和ModelMap作为控制器方法的参数

2.1.1 示例代码

2.1.1.1 控制类
@Controller
public class ModelController {

    /*Model作为方法参数*/
    @RequestMapping("/model")
    public String model(Model model) {
        model.addAttribute("JoJo","StarPlatinum" );
        return "success";
    }

    /*ModelMap作为方法参数*/
    @RequestMapping("/modelMap")
    public String modelMap(ModelMap modelMap) {
        modelMap.addAttribute("Dio","TheWorld" );
        return "success";
    }
}
2.1.1.2 success.jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    success


success!!

${requestScope.JoJo}<%--从request域中获取数据--%> ${requestScope.Dio}

2.1.2 Model和ModelMap的异同

相同点:

  • 由于ModelMap的一个子类ExtendedModelMap实现Model接口,所以Model和ModelMap都是通过Model接口的子实现类BindingAwareModelMap实现存储数据到域的功能;使用addAttribute方法时最终都是会调用request.setAttribute()方法;
  • 两者从将数据存储到request域中的角度上来看是一样的。

不同点:

  • Model是接口,而ModelMap是类。它们有各自的功能,只是存储数据到request域的功能上一致

2.2 SessionAttributes注解

  • 作用:自动把Model或ModelMap中的数据存储到session域中,用于多次执行控制器方法间的参数共享。
  • 属性:
    • names:用于存入Model或ModelMap中指定的属性名称的数据;
    • type:用于存入Model或ModelMap中指定类型的数据。该类型的所有数据都会存入session中。如果是基本数据类型,要使用对应包装类的字节码对象

2.2.1 控制类

/**
 * 注解@SessionAttributes
 * 1.自动把Model或者ModelMap中的数据放入session
 * 2.属性:
 *   names = {"JoJo","Dio"}, 把Model或者ModelMap中指定名称的key的数据,自动放入session
 *   types = Integer.class 把Model或者ModelMap中指定类型的数据,自动放入session
 */
@Controller
@SessionAttributes(names = {"JoJo","Dio"},types = Integer.class)
public class SessionAttributesController {
    @RequestMapping("/sessionModel")
    public String sessionModel(Model model) {
        model.addAttribute("JoJo","StarPlatinum");
        model.addAttribute("Dio","TheWorld");
        model.addAttribute("num1",831143);
        model.addAttribute("num2","12345");//不满足存入的条件,该条数据不会存入session
        return "success";
    }
    @RequestMapping("/sessionModelMap")
    public String sessionModelMap(ModelMap modelMap) {
        modelMap.addAttribute("JoJo","StarPlatinum");
        modelMap.addAttribute("Dio","TheWorld");
        return "success";
    }

    /*清除session的数据
    * 1.使用原始的session.setAttribute方法存入的,只能使用原始的方法清除;
    * 2.使用springMVC提供的方法自动存入的(即上面代码),只能使用@SessionAttributes注解清除.
    *   注意:方法的参数是SessionStatus,这个对象提供setComplete()方法清空自动存入session的数据,
    *        而原始方法存入的不会被清除
    */
    @RequestMapping("/del")
    public String del(SessionStatus sessionStatus){
        // 清空通过@SessionAttributes注解自动放入session中的数据
        sessionStatus.setComplete();
        return "success";
    }
}

2.2.2 success.jsp页面


success!!

从request域中获取数据

${requestScope.JoJo} ${requestScope.Dio}

从session域中获取数据

${sessionScope.JoJo} ${sessionScope.Dio} ${sessionScope.num1} ${sessionScope.num2}

3. json数据的交互

3.1 使用的注解

3.1.1 @RequestBody

  • 作用:在处理器方法的形参上使用。把请求的json格式数据转换为java对象

3.1.2 @ResponseBody

  • 在处理器方法返回值上使用,或在方法上使用。需要jackson支持包
  • 作用:将响应的java对象转换为json格式的数据

3.2 添加依赖

  • 需要在pom.xml中导入jackson支持包

<dependency>
  <groupId>com.fasterxml.jackson.coregroupId>
  <artifactId>jackson-annotationsartifactId>
  <version>2.9.0version>
dependency>
<dependency>
  <groupId>com.fasterxml.jackson.coregroupId>
  <artifactId>jackson-coreartifactId>
  <version>2.9.0version>
dependency>
<dependency>
  <groupId>com.fasterxml.jackson.coregroupId>
  <artifactId>jackson-databindartifactId>
  <version>2.9.0version>
dependency>

3.3 引入jquery文件,在springMVC.xml中配置

  • 由于上面已经在springMVC中设置放行/js/**的资源

3.4 在pages目录下新建测试用html页面


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>ajaxtitle>
    <script src="../js/jquery-3.3.1.min.js" type="text/javascript">script>
    <script>
        $(function(){
            $("#ajaxPost").click(function(){
                $.ajax({
                    // 请求类型,这里必须为post,否则无法使用requestBody
                    type : "post",
                    // 请求地址
                    url : "/responseBodyJson",
                    // 发送给后台的ajax请求数据
                    data:'{"id":100,"name":"jack","money":9.9}',
                    dataType:"json",
                    // 请求格式与编码,避免乱码
                    contentType:"application/json;charset=utf-8",
                    success : function(jsn){
                        alert("jsn="+jsn+"; jsn.id="+jsn.id+"; jsn.name="+jsn.name+"; jsn.money="+jsn.money);
                    }
                });
            });
        });
    script>
head>
<body>
<h2>RequestBody获取请求JSON格式数据 & ResponseBody自动把对象转json并响应h2>
<button id="ajaxPost">测试ajax请求json与响应jsonbutton>
body>
html>

3.5 创建Account实体类用来封装数据

public class Account {
    private int id;
    private String name;
    private double money;

3.6 控制器类

@Controller
public class JsonController {

    @RequestMapping("/responseBodyJson")    //注意与页面的ajax中的url保持一致
    @ResponseBody   //表示方法返回json格式(自动把返回对象转json格式)
    public Account json(@RequestBody Account account) { //作用在方法参数中用以获取请求体的数据封装到形参中
        System.out.println("请求的数据为:" + account);
        //返回的数据
        account.setId(11);
        account.setName("JoJo");
        account.setMoney(10086);
        return account;
    }
}

4. Restful风格的url

  • 一种架构样式的设计风格,核心价值在于设计出符合REST风格的网络接口
  • 更加简洁、更有层次,更易于实现缓存等机制。

4.1 优点和特性

  • 优点:结构清晰、符合标准、易于理解、 扩展方便

4.1.1 特性

资源(Resources):URI是每个资源独一无二的标识符;

表现层(Representation) : 把资源具体呈现出来的形式;

状态转化(State Transfer):简单而言:是表现层状态转化,有四种操作。GET:用来获取资源,POST:用来新建资源,PUT:用来更新资源,DELETE:用来删除资源;

4.2 HTTP请求的提交方式

共7种:

  • doGet、doPost、doDelete、doPut、doHead、doOptions、doTrace

而jsp、html仅支持其中的get,post方式。如果要使用其他方式,需要使用特定方法开启。

4.3 Restful风格与非Restful风格的区别

如果使用同一个地址表示crud方法:

  1. 非restful方法:需要在访问路径中表明crud的方法,eg:http://localhost:8080/Order?type=add/update/delete/find

  2. restful方法:不需要在访问路径中表明crud的方法,只需要在提交表单的时候使用不同的提交方式,而不同crud方法可以使用同一个地址,eg:http://localhost:8080/Order

4.4 基于HidderHttpMethodFilter开启请求方式

  • 使用Spring3.0提供的过滤器HidderHttpMethodFilter开启GET、POST、PUT与DELETE请求方式
  • 使用步骤:
    1. web.xml配置过滤器
    2. 请求方式必须使用post请求
    3. 按照要求提供_metheod请求参数,即我们需要的请求方式

4.4.1 web.xml配置过滤器


<filter>
   <filter-name>hiddenHttpMethodFilterfilter-name>
   <filter-class>org.springframework.web.filter.HiddenHttpMethodFilterfilter-class>
filter>
<filter-mapping>
   <filter-name>hiddenHttpMethodFilterfilter-name>
   <url-pattern>/*url-pattern>
filter-mapping>

4.4.2 测试页面restful.html

  • 注意使用隐藏域提交_method参数

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>restful_testtitle>
head>
<body>
<form action="http://localhost:8080/restful/100" method="post">
    
    <input type="hidden" name="_method" value="post">
    <input type="submit" value="post提交(添加)">
form>

<form action="http://localhost:8080/restful/200" method="post">
    
    <input type="hidden" name="_method" value="get">
    <input type="submit" value="get提交(查询)">
form>

<form action="http://localhost:8080/restful/300" method="post">
    
    <input type="hidden" name="_method" value="put">
    <input type="submit" value="put提交(修改)">
form>

<form action="http://localhost:8080/restful/400" method="post">
    
    <input type="hidden" name="_method" value="delete">
    <input type="submit" value="delete提交(删除)">
form>
body>
html>

4.4.3 控制器类

  • 使用@PathVariable获取占位符值
  • 注意:使用put请求或者delete请求时,不能通过返回值跳转页面。解决方法:转为json字符串返回,不过跳转的页面只会显示返回值字符串。
@Controller
public class restfulController {
    /**
     * 1.处理post请求
     * 2.请求地址:http://localhost:8080/restful/100,id不能在代码中写死,需要使用占位符
     *      占位符的写法{占位符名}
     * 3.在控制类的方法参数中使用@PathVariable注解获取占位符的值,并赋值到被注解的参数中
     */
    @RequestMapping(value = "/restful/{id}",method = RequestMethod.POST)
    public String save(@PathVariable("id") int id) {
        System.out.println("save:" + id);
        return "success";
    }

    /**
     * 1.处理get请求
     * 2.请求地址:http://localhost:8080/restful/100,id不能在代码中写死,需要使用占位符
     *      占位符的写法{占位符名}
     */
    @RequestMapping(value = "/restful/{id}",method = RequestMethod.GET)
    public String get(@PathVariable("id") int id) {
        System.out.println("get:" + id);
        return "success";
    }

    /**
     * 1.处理put请求
     * 2.注意:put请求不能使用跳转,需要返回json格式的字符串
     *        否则会报405:JSPs only permit GET POST or HEAD
     *   为何会报错?
     *      因为返回的字符串是以put方式,而返回的页面jsp不支持put方式,导致无法识别而报错
     */
    @RequestMapping(value = "/restful/{id}",method = RequestMethod.POST)

    public String put(@PathVariable("id") int id) {
        System.out.println("put:" + id);
        return "success";   //注意,这里返回的是json字符串,而不会跳转到success.jsp
    }

    /**
     * 1.处理delete请求
     * 2.注意:delete请求不能使用跳转,需要返回json格式的字符串
     */
    @RequestMapping(value = "/restful/{id}",method = RequestMethod.DELETE)
    @ResponseBody   //表示返回值自动转为json格式数据
    public String delete(@PathVariable("id") int id) {
        System.out.println("delete:" + id);
        return "[{\"id\":\"11\",\"name\":\"JoJo\"},{\"id\":\"12\",\"name\":\"Dio\"}]";
    }
}

5. 控制器方法的返回值(重要)

5.1 返回值类型

5.1.1 返回String类型

  • 返回值类型是String类型时,默认会以转发方式跳转到页面;
  • 需要配置springMVC.xml中的视图解析器;

上面的代码的返回值全部是String类型,使用转发方式跳转

5.1.2 返回void

  • 在方法内部通过servletApi自行控制返回结果
  • 注意:文件下载需要使用返回void形式

5.1.3 返回ModelAndView

  • ModelAndView是SpringMVC提供的对象

  • 作用:控制器存储数据的同时完成跳转功能

  • 提供两种方法:

    • addObject:将请求数据封装到对象中存入request域(利用ModelMap)
    • setViewName:设置视图名称,视图解析器根据名称跳转到指定视图

5.1.4 示例代码

@Controller
public class ReturnValueController {

    /**
     * 1. 返回值为String类型
     */
    @RequestMapping("/str")
    public String strReturn(){
        return "success";
    }

    /**
     * 2. 返回void
     */
    @RequestMapping("/void")
    public void voidReturn(HttpServletResponse response){
    }

    /**
     * 3. 返回值为ModelAndView
     *      在存储数据的同时完成跳转操作
     */
    @RequestMapping("/mv")
    public ModelAndView returnmodelAndView(HttpServletResponse response){
        //创建ModelAndView对象
        ModelAndView mv = new ModelAndView();
        //往request域存入数据
        mv.addObject("JoJo","StarPlatinum" );
        //设置跳转页面
        mv.setViewName("success");
        return mv;
    }
}

5.2 转发和重定向

5.2.1 forward转发

  • contrller 方法提供了一个 String 类型返回值之后, 在返回值里使用forward:
  • 它相当于response.getRequestDispatcher(url).forward(..)
/**
 * 使用forward方式转发
 */
@RequestMapping("/forward")
public String forward(){
    return "forward:/pages/success.jsp";    //指定跳转路径
}

5.2.2 重定向

  • contrller 方法提供了一个 String 类型返回值之后, 在返回值里使用redirect:

  • 它相当于response.sendRedirect(url)

  • 注意:重定向到jsp页面时,jsp页面不可放在WEB-INF目录下

/**
 * 使用重定向转发
 */
@RequestMapping("/redirect")
public String redirect(){
    return "redirect:/pages/success.jsp";    //指定跳转路径
}

6. SpringMVC实现文件上传(重要)

  • 3种上传方式:传统文件上传、SpringMVC文件上传、SpringMVC跨服务器方式文件上传。

6.1 传统文件上传

6.1.1 使用传统方式实现文件上传的三大条件

  1. form标签的enctype属性的取值必须是:multipart/form-data,表示表单以文件上传形式提交。(一般表单提交数据不写该属性,默认值是application/x-www-form-urlencoded,表示不以文件上传形式提交)
  2. method属性取值必须为:post
  3. 提供一个文件选择域****
  4. 此外,需要添加Commons-fileupload支持包

6.1.2 添加依赖


<dependency>
  <groupId>Commons-fileuploadgroupId>
  <artifactId>Commons-fileuploadartifactId>
  <version>1.3.1version>
dependency>

6.1.3 文件上传页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    upload



用户名: 证件照:

6.1.4 控制器类

/**
 * 使用传统方式:Apache提供的fileUpload组件实现文件上传
 */
@Controller
public class TraditionalUploadController {

    @RequestMapping("/upload")
    public void upload(HttpServletRequest request) throws Exception {
        /*
        实现文件上传思路:
            1. 获取文件上传目录地址
            2. 根据当前日期创建子目录(方便规整每天用户上传的图片)
            3. 处理文件上传
                3.1 创建文件上传核心工具类ServletFileUpload
                3.2 使用核心工具类将表单数据封装到FileItem对象
                3.3 遍历FileItem对象,获取每个表单元素,如果是普通元素,打印;如果是文件元素
                    3.3.1 获取文件名,并使用UUID规则使文件名唯一化(避免重名)
                    3.3.2 上传文件并删除临时文件
         */
        //1. 获取文件上传目录地址
        String realPath = request.getSession().getServletContext().getRealPath("/upload");
        //文件上传的目标地址:E:/Java_study/JavaprojectsIV/day56project_SpringMVC_day2/target/day56project_SpringMVC_day2-1.0-SNAPSHOT/upload
        System.out.println(realPath);

        //2. 根据当前日期创建子目录(方便规整每天用户上传的图片)
        String date = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        //创建目录
        File file = new File(realPath,date);
        if (!file.exists()) {
            file.mkdirs();
        }

        //3. 处理文件上传
        //创建FileItem工厂
        FileItemFactory factory = new DiskFileItemFactory();
        //3.1 创建文件上传核心工具类ServletFileUpload
        ServletFileUpload upload = new ServletFileUpload(factory);
        //3.2 使用核心工具类将表单数据封装到FileItem对象
        List<FileItem> fileItems = upload.parseRequest(request);
        //3.3 遍历FileItem对象,获取每个表单元素,如果是普通元素,打印;
        for (FileItem fileItem : fileItems) {
            //判断:如果是普通表单元素就获取打印
            if (fileItem.isFormField()) {
                String nameStr = fileItem.getString("UTF-8");
                System.out.println("输入的用户名:" + nameStr);
            } else {
                //文件元素
                //3.3.1 获取文件名,并使用UUID规则使文件名唯一化(避免重名)
                String fileName = fileItem.getName();
                fileName = UUID.randomUUID().toString().replaceAll("-","")+"_" +fileName;
                //3.3.2 上传文件并删除临时文件
                fileItem.write(new File(file,fileName));//父路径加文件名
                fileItem.delete();
            }
        }
    }
}

6.2 SpringMVC文件上传(重点)

  • springmvc框架提供了一个对象MultipartFile,该对象可作为控制器方法的参数。参数的名称必须和表单file元素的name属性取值一致
  • MultipartFile提供了transferTo(file)方法可以直接上传文件

6.2.1 测试上传页面

  • 同传统方式

6.2.2 控制器

@Controller
public class SpringMVCUploadController {
    /**
    实现文件上传思路:
        1. 获取文件上传目录地址
        2. 根据当前日期创建子目录(方便规整每天用户上传的图片)
        3. 处理文件上传
            3.1 使用MultipartFile对象获取文件名,并使用UUID规则使文件名唯一化(避免重名)
            3.2 直接使用MultipartFile对象的方法上传文件
    */
    @RequestMapping("/upload2")
    public String upload(HttpServletRequest request, MultipartFile imgFile) throws IOException {
        //1. 获取文件上传目录地址
        String realPath = request.getSession().getServletContext().getRealPath("/upload");
        //文件上传的目标地址:E:/Java_study/JavaprojectsIV/day56project_SpringMVC_day2/target/day56project_SpringMVC_day2-1.0-SNAPSHOT/upload
        System.out.println(realPath);

        //2. 根据当前日期创建子目录(方便规整每天用户上传的图片)
        String date = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        //创建目录
        File file = new File(realPath,date);
        if (!file.exists()) {
            file.mkdirs();
        }

        //3. 处理文件上传
        //3.1 使用MultipartFile对象获取文件名,并使用UUID规则使文件名唯一化(避免重名)
        String fileName = imgFile.getOriginalFilename();
        fileName = UUID.randomUUID().toString().replaceAll("-","")+"_" +fileName;
        //3.2 直接使用MultipartFile对象的方法上传文件
        imgFile.transferTo(new File(file,fileName));

        //顺便把用户名打印一下吧
        System.out.println(request.getParameter("username"));

        //4. 如果使用返回void,由于没有指定返回的页面,默认返回到控制类方法的映射,即默认返回upload2,而项目没有/pages/upload2.jsp,会找不到返回页面而报错
        //故指定返回的页面
        return "upload";
    }
}

6.2.3 springMVC.xml配置文件上传解析器

  • 使用文件上传解析器:CommonsMultipartResolver

  • 注意事项:文件上传解析器的id是固定的(一定要是multipartResolver),不能起别的名称,否则无法实现请求参数的绑定


<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    
    <property name="maxUploadSize" value="10485760">property>
bean>

6.3 springmvc 跨服务器方式的文件上传

6.3.1 实际开发的分服务器处理

  • 分服务器处理的目的是让不同的服务器处理不同的功能,从而提高我们项目的运行效率
  • 如:
    • 数据库服务器:访问数据库
    • 缓存和消息服务器:负责处理大并发访问的缓存和消息
    • 文件服务器:负责存储用户上传文件的服务器
    • 应用服务器:负责部署应用

6.3.2 pom.xml导入jersey坐标


<dependency>
  <groupId>com.sun.jerseygroupId>
  <artifactId>jersey-coreartifactId>
  <version>1.18.1version>
dependency>
<dependency>
  <groupId>com.sun.jerseygroupId>
  <artifactId>jersey-clientartifactId>
  <version>1.18.1version>
dependency>

6.3.3 控制类

@Controller
public class SToSUploadController {

    @RequestMapping("/upload3")
    public String upload(HttpServletRequest request,MultipartFile imgFile) throws IOException {
        //创建jersey包中提供的client对象
        Client client = new Client();
        //使用client和文件服务器建立联系
        //6080是文件服务器的端口号
        String uploadPath = "http://localhost:6080/fileSystem/upload/" + imgFile.getOriginalFilename();
        WebResource webResource = client.resource(uploadPath);
        //将web资源对象添加到文件服务器上
        webResource.put(String.class,imgFile.getBytes());
        return "success";
    }
}

6.3.4 springMVC.xml配置文件上传解析器

  • 配置方式同6.2.3

6.3.5 测试页面

  • 同上

你可能感兴趣的:(spring)