¡Acostúmbrate a escribir juntos! Este es el noveno día de mi participación en el "Nuggets Daily New Plan · April Update Challenge", haz clic para ver los detalles del evento .
1. Spring MVC maneja las solicitudes AJAX
Spring MVC devuelve datos con formato JSON
Copie el proyecto spring-mvc-crud y cámbiele el nombre a spring-mvc-ajax. Spring MVC necesita importar dependencias relacionadas con jackson para procesar datos en formato json
<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>
复制代码
Después de agregar dependencias, coloque todos los paquetes JAR a la derecha de la carpeta lib en el directorio Project Structure -> Artifacts y agregue un nuevo controlador y use la anotación @RestController en la clase.
@RestController
public class AnotherController {
@Autowired
private EmployeeDao employeeDao;
@RequestMapping(value = "/list_by_json")
public Collection<Employee> listByJson(){
Collection<Employee> all = employeeDao.getAll();
return all;
}
}
复制代码
Reinicie Tomcat e ingrese http://localhost:8080/list_by_json en el navegador
Todos los datos de los empleados se muestran en el navegador en formato JSON
@JsonIgnorar
La anotación @JsonIgnore puede ignorar ciertos atributos al convertir datos en formato JSON Agregue la anotación @JsonIgnore al atributo Departamento de la clase de entidad Empleado
public class Employee {
// 其余代码保持不变
@JsonIgnore
private Department department;
}
复制代码
Reinicie la aplicación e ingrese http://localhost:8080/list_by_json en el navegador
Se puede ver que los datos del empleado que se muestran en el navegador ignoran el atributo del departamento y ya no muestran la información del atributo del departamento.
@JsonFormat
Agregue la anotación @JsonFormat para especificar el formato de la salida
public class Employee{
// 其余代码保持不变
@JsonFormat(pattern = "yyyy-MM-dd")
private Date birth = new Date();
}
复制代码
Reinicie la aplicación, la entrada del navegador http://localhost:8080/list_by_json El formato que muestra la hora es el formato especificado por la anotación @JsonFormat, y el formato predeterminado es el formato de marca de tiempo sin la anotación @JSONFormat, como se muestra a continuación figura
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, 点击页面的超链接,即可获取所有员工的数据
@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, 点击提交按钮 请求提数据被打印在控制台中
在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 ,点击发送超链接
浏览器发送的请求体为JSON格式的数据
@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页面,点击发送按钮发送表单请求
控制台打印出消息体对象
@ResponseBody、ResponseEntity 与文件下载
该注解会将相应内容放在响应体中
@ResponseBody
@RequestMapping("/hello")
public String hello(){
return "success";
}
复制代码
访问/ha不会返回success页面,会直接返回字符串success
还可以自定义响应实体,这要求方法返回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 自定义的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 文件夹下
在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>
复制代码
Reinicie la aplicación, ingrese http://localhost:8080/upload.jsp en el navegador, ingrese a la interfaz de carga de archivos e ingrese el contenido del formulario de carga de archivos
Haga clic en el botón Enviar y la página muestra un mensaje que indica que el archivo se cargó correctamente
Y la consola imprime el contenido del formulario de carga de archivos y la información del atributo del formulario
Carga de varios archivos
Modificar el formulario de subida de archivos
<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>
复制代码
Se agrega un nuevo método de carga en UploadController, que maneja múltiples parámetros de carga de archivos para recibir múltiples archivos desde el front-end a través de la matriz 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";
}
复制代码
Reinicie la aplicación y el navegador abre la página upload.jsp
Ingrese el contenido en el formulario y haga clic en enviar. La página indica que el archivo se cargó correctamente.
La información sobre el archivo cargado también se imprime en la consola de back-end