Spring 全家桶之 Spring Web MVC(六)- AJAX & Fileupload

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第9天,点击查看活动详情

一、Spring MVC 处理 AJAX 请求

Spring MVC 返回 JSON 格式数据

拷贝spring-mvc-crud项目,重命名为spring-mvc-ajax。Spring MVC 处理 json 格式的数据需要导入jackson相关依赖

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.13.1</version>
</dependency>

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.13.1</version>
</dependency>

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>2.13.1</version>
</dependency>
复制代码

添加依赖之后,要在Project Structure -> Artifacts 目录下把右侧的JAR包全都put到lib文件夹下 新增一个Controller并使用@RestController注解标注在该类上

@RestController
public class AnotherController {

    @Autowired
    private EmployeeDao employeeDao;

    @RequestMapping(value = "/list_by_json")
    public Collection<Employee> listByJson(){
        Collection<Employee> all = employeeDao.getAll();
        return all;
    }
}    
复制代码

重新启动Tomcat,浏览器输入http://localhost:8080/list_by_json

image.png 浏览器中显示了所有员工的数据,并以JSON格式进行展示

@JsonIgnore

@JsonIgnore注解可以将某些属性在转换成JSON格式数据时进行忽略,在Employee实体类的Department属性上增加@JsonIgnore注解

public class Employee {
   // 其余代码保持不变 
   @JsonIgnore
   private Department department;
}   
复制代码

重新启动应用,浏览器输入http://localhost:8080/list_by_json image.png

可以看出浏览器中展示的Employee数据忽略了Department属性,不再展示Department属性信息

@JsonFormat

添加@JsonFormat注解,指定输出的格式

public class Employee{
    // 其余代码保持不变
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date birth = new Date();
}
复制代码

重新启动应用,浏览器输入http://localhost:8080/list_by_json image.png 时间显示的格式即为@JsonFormat注解指定的格式,而不加@JSONFormat注解默认为时间戳戳格式,如下图所示

image.png

Spring MVC 处理 AJAX 请求

在index.jsp同级目录下新增一个页面emps.jsp,使用ajax请求获取所有员工并显示在页面上

<%@page import="java.util.Date"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<!--head标签内容省略-->
<body>
<%=new Date() %>
<a href="${ctp }/list_by_json">ajax获取所有员工</a><br/>

<div>

</div>
<script type="text/javascript">
    $("a:first").click(function(){
        //1、发送ajax获取所有员工
        $.ajax({
            url:"${ctp}/list_by_json",
            type:"GET",
            success:function(data){
                //console.log(data);
                $.each(data,function(){
                    var empInfo = this.lastName+"-->"+this.birth+"--->"+this.gender;
                    $("div").append(empInfo+"<br/>");
                });
            }
        });

        return false;
    });
</script>
</body>
</html>
复制代码

重新启动应用,浏览器输入http://localhost:8080/emps.jsp, 点击页面的超链接,即可获取所有员工的数据 image.png

@RequestBody注解

@RequestBody注解可以直接获得请求体,在AnotherController中增加一个方法postReq,用来处理前端的post请求

@RequestMapping("/post_request")
public String postReq(@RequestBody String user){
    System.out.println("请求体:" + user);
    return "success";
}
复制代码

新增一个页面post.jsp,发送post表单请求到postReq方法

<h2>使用表单发送POST请求</h2>
<div>
    <form action="/post_request" method="post">
        <input name="username" value="stark">
        <input name="password" value="123456">
        <input type="submit">
    </form>
</div>
复制代码

重新启动应用,浏览器进入到http://localhost:8080/post.jsp, 点击提交按钮 image.png 请求提数据被打印在控制台中

在post.jsp页面增加一个ajax的post请求

<h2>使用Ajax发送JSON格式的POST请求</h2>
<a href="/post_request">发送</a>
<script type="text/javascript">
    $("a:first").click(function(){
        var emp = {lastName:"Banner", email:"[email protected]",gender:0};
        var empStr = JSON.stringify(emp);
        //1、发送ajax获取携带JSON格式数据
        $.ajax({
            url:"${ctp}/post_request",
            type:"POST",
            data:empStr,
            contentType: "application/json",
            success:function(data){
                //console.log(data);
                alert(data);
            }
        });

        return false;
    });
</script>
复制代码

浏览器发送http://localhost:8080/post.jsp ,点击发送超链接

image.png 浏览器发送的请求体为JSON格式的数据

image.png @RequestBody注解将JSON格式数据转换成Employee实体类对象

HttpEntity<T>

HttpEntity是指请求和响应的实体类,包含了消息头和消息体,可以从该类中获取请求头请求体以及响应头响应体信息。

在AnotherController中新增一个httpEntity方法,接收一个HttpEntity类为参数

@RequestMapping("/http_entity")
public String httpEntity(HttpEntity<String> str){
    System.out.println(str);
    return "success";
}
复制代码

修改post.jspy页面中的表单的请求地址为/http_entity

<h2>使用表单发送POST请求</h2>
<div>
    <form action="/http_entity" method="post">
        <input name="username" value="stark">
        <input name="password" value="123456">
        <input type="submit">
    </form>
</div>
复制代码

重新启动该应用,浏览器打开post.jsp页面,点击发送按钮发送表单请求

image.png 控制台打印出消息体对象

@ResponseBody、ResponseEntity 与文件下载

该注解会将相应内容放在响应体中

@ResponseBody
@RequestMapping("/hello")
public String hello(){
    return "success";
}
复制代码

访问/ha不会返回success页面,会直接返回字符串success

image.png

还可以自定义响应实体,这要求方法返回ResponseEntity

@RequestMapping("/hallo")
public ResponseEntity<String> hallo(){
    // 定义响应请求头
    MultiValueMap<String, String> headers =new HttpHeaders();
    // 定义响应体
    String body = "<h2>SUCCESS</h2>";
    headers.add("Set-Cookie", "username=stark");
    // 返回响应实体类
    return new ResponseEntity<>(body, headers, HttpStatus.OK);
}
复制代码

重新启动应用,浏览器输入/hallo,页面显示了SUCCESS image.png 自定义的cookie响应码等生效。

ResponseEntity还可以应用到文件下载中,AnotherController方法中新增方法download

@RequestMapping("/download")
public ResponseEntity<byte[]> download(HttpServletRequest request) throws IOException {
    // 1.得到要下载的流
    // 找到要下载文件的真实路径
    ServletContext context = request.getServletContext();
    String realPath = context.getRealPath("/js/jquery-1.9.1.min.js");
    FileInputStream is = new FileInputStream(realPath);
    byte[] tmp = new byte[is.available()];
    is.read(tmp);
    is.close();

    // 2.将要下载的文件返回
    HttpHeaders header = new HttpHeaders();
    header.set("Content-Disposition","attachment;filename="+"jquery-1.9.1.min.js");
    ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(tmp, header, HttpStatus.OK);
    return responseEntity;
}
复制代码

重启tomcat,浏览器输入http://localhost:8080/download, 会自动下载指定的文件

二、文件上传

Spring MVC 为文件上传提供了直接的支持,这种支持是通过即插即用的MultipartResolver实现的,Spring是用Jakarta Commons FileUpload技术实现了一个MultipartResolver的实现类CommonsMultipartResolver

文件上传需要导入commons-fileupload和commons-io两个包,在pom文件中添加依赖

<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.4</version>
</dependency>

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.11.0</version>
</dependency>
复制代码

将导入的包放入 lib 文件夹下 image.png

在index.jsp同级目录下新建一个upload.jsp页面,新建文件上传表单

<h2>文件上传表单</h2>
<div>
  <form action="/upload" method="post" enctype="multipart/form-data">
    用户头像:<input type="file" name="headimg" />
    用户名:<input type="text" name="username" />
    <input type="submit">
  </form>
</div>
复制代码

文件上传表单一定要设置enctype属性且value为multipart/form-data,将请求体中的文件分段发送到服务器端

Spring MVC文件上传需要在Spring MVC配置文件上配置上传解析器CommonsMultpartResolver,否则无法解析文件上传请求,会出现http 400的报错

<!--配置文件上传解析器-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="maxUploadSize" value="#{1024*1024*20}" />
    <property name="defaultEncoding" value="utf-8" />
</bean>
复制代码
  • defaultEncoding:必须和用户的JSP的pageEncoding属性一致,以便正确解析表单内容
  • maxUploadSize:设置文件上传的大小,可以根据上传文件适当设置

新增一个UploadController,用于处理文件上传

@Controller
public class UploadController {

    @RequestMapping("/upload")
    public String upload(@RequestParam(value = "username", required = false) String username,
                         @RequestParam("headimg")MultipartFile file,
                         Model model){
        System.out.println("上传文件表单中文件属性的名称:" + file.getName());
        System.out.println("上传文件请求中文件的名称:" + file.getOriginalFilename());
        System.out.println("上传文件请求中username的值为:" + username);

        // 上传文件
        try {
            file.transferTo(new File("/Users/jingnan/Practice/spring-mvc-ajax/" + file.getOriginalFilename()));
            model.addAttribute("msg", "文件上传成功");
        } catch (IOException e) {
            model.addAttribute("msg","文件上传失败" + e.getMessage());
        }

        return "forward:/upload.jsp";

    }
}
复制代码

使用Spring MVC进行上传文件非常方便,调用transferTo方法即可完成上传文件的操作

在upload.jsp文件中显示文件上传是否成功的提示

<h2>文件上传表单</h2>
${msg}
<div>
    <!--文件上传表单保持不变-->
</div>
复制代码

重新启动应用,浏览器输入http://localhost:8080/upload.jsp, 进入文件上传界面并输入文件上传的表单内容

image.png

点击提交按钮 image.png 页面显示出文件上传成功的消息提示

image.png 并且控制台打印出了文件上传表单的内容以及表单属性信息

多文件上传

修改上传文件表单

<h2>文件上传表单</h2>
${msg}
<div>
    <form action="/uploads" method="post" enctype="multipart/form-data">
        图片:<input type="file" name="headimg" /> <br>
        图片1:<input type="file" name="headimg" /> <br>
        图片2:<input type="file" name="headimg" /> <br>
        图片3:<input type="file" name="headimg" /> <br>
        图片4:<input type="file" name="headimg" /> <br>
        用户名:<input type="text" name="username" />
        <input type="submit">
    </form>
</div>
复制代码

在UploadController中新增一个方法uploads,处理多文件上传 参数中通过Mulpart数组来接收前端的多文件

@RequestMapping("/uploads")
public String uploads(@RequestParam(value = "username", required = false) String username,
                     @RequestParam("headimg")MultipartFile[] files,
                     Model model){

    for (MultipartFile file : files) {
        System.out.println("上传文件表单中文件属性的名称:" + file.getName());
        System.out.println("上传文件请求中文件的名称:" + file.getOriginalFilename());
        // 保存文件
        try {
            file.transferTo(new File("/Users/jingnan/Practice/spring-mvc-ajax/" + file.getOriginalFilename()));
            model.addAttribute("msg", "文件上传成功");
        } catch (IOException e) {
            model.addAttribute("msg","文件上传失败" + e.getMessage());
        }
    }

    System.out.println("上传文件请求中username的值为:" + username);

    return "forward:/upload.jsp";
}
复制代码

重新启动应用,浏览器打开upload.jsp页面

image.png 表单中输入内容,并点击提交 image.png 页面提示文件上传成功

image.png 后端控制台中也打印出了上传文件的信息

猜你喜欢

转载自juejin.im/post/7084964775301644301
今日推荐