文章目录
参考博文,点击这里
1.两者的区别
@responseBody注解的作用是将controller的方法返回的对象通过适当的转换器转换为指定的格式之后,写入到response对象的body区,通常用来返回JSON数据或者是XML
数据,需要注意的呢,在使用此注解之后不会再走视图处理器,而是直接将数据写入到输入流中,他的效果等同于通过response对象输出指定格式的数据。
@RequestMapping("/login")
@ResponseBody
public User login(User user){
return user;
}
User字段:userName pwd
那么在前台接收到的数据为:'{"userName":"xxx","pwd":"xxx"}'
效果等同于如下代码:(由此看出,使用 ResponseBody则比较省事些)
@RequestMapping("/login")
public void login(User user, HttpServletResponse response){
response.getWriter.write(JSONObject.fromObject(user).toString());
}
理解:很多情况我们需要在controller接收请求然后返回一些message。
在springmvc中当返回值是String时,如果不加@ResponseBody的话,返回的字符串就会找这个String对应的页面,如果找不到会报404错误。
如果加上@ResponseBody注解的话,返回的就是json字符串,并且把这个json字符串返回给发送请求的原页面。
当然也有时候不加@ResponseBody注解,那么就需要我们在controller的方法中传入response参数,然后在方法里面获取response.getWriter()赋给PrintWriter。然后通过PrintWriter把这个字符串以流的形式传递给原发送请求的页面。
应用场景:页面或者js异步请求Controller,Controller不需要返回view,而只需要返回数据时,就可以使用@ResponseBody注解。@ResponseBody注解会把return 的结果放到response对象中。
只要在页面或者js中ajax指定dataType,并且在Controller上使用@ResponseBody注解来修饰,SpringMVC就会帮我们把这个Controller返回的对象转为json格式的。
若想返回一段小的字符串到页面上,可以在Controller中使用PrintWriter类,直接 out.print(字符串),此时这个java方法不需要使用@ResponseBody注解修饰,若想用@ResponseBody注解修饰,只需要在ajax中指定dataType为text。
2.http 请求响应媒体类型一览
媒体类型 | 含义 |
---|---|
text/html | HTML 格式 |
text/plain | 纯文本格式 |
text/xml, application/xml | XML 数据格式 |
application/json | JSON 数据格式 |
image/gif | gif 图片格式 |
image/png | png 图片格式 |
application/octet-stream | 二进制流数据 |
application/ x-www-form-urlencoded | form 表单数据 |
multipart/form-data | 含文件的 form 表单 |
web 开发中我们常用的提交表单操作,其默认的媒体类型就是 application/ x-www-form-urlencoded,而当表单中包含文件时,大家估计都踩过坑,需要将 enctype=multipart/form-data 设置在 form 参数中。text/html 也就是常见的网页了,json 与 xml 常用于数据交互,其他不再赘述。
而在 JAVA 中,提供了 MediaType 这样的抽象,来与 http 的媒体类型进行对应。‘/’之前的名词,如 text,application 被称为类型(type),‘/’之后被称为子类型 (subType)。
response.getWriter().write()与out.print()的区别
不同的是response.getOutputStream()向浏览器输出的是二进制数据,是字节流,可以处理任意类型的数据,而response.getWriter()输出的是字符型数据,是字符流。
1、使用OutputStream流和PrintWriter流向客户端浏览器输出中文数据
在服务器端,数据的输出码表要和控制客户端浏览器相应的码表一致,比如:outputStream.write(“中文”.getBytes(“UTF-8”));使用OutputStream流向客户端浏览器输出中文,以UTF-8的编码进行输出,此时就要控制客户端浏览器以UTF-8的编码打开,否则显示的时候就会出现中文乱码。
在服务器端如何控制客户端浏览器以以UTF-8的编码显示数据呢?
可以通过设置响应头控制浏览器的行为,例如:response.setHeader("content-type", "text/html;charset=UTF-8");
通过设置响应头控制浏览器以UTF-8的编码显示数据。
1.1使用OutputStream流向浏览器输出中文
package controller;
import java.io.IOException;
import java.io.OutputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ServletDemo01 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String str="使用OutputStream输出中文:我心自在";
//在服务器设置响应头,告诉浏览器以utf-8的编码显示数据,如果不写会出现中文乱码
response.setHeader("content-type", "text/html;charset=UTF-8");
//获取OutputStream输出流
OutputStream os=response.getOutputStream();
/**
* getBytes的作用是将字符转化为字节数组,如果不带参数,默认根据系统环境来进行转化
* 这里指定以utf-8的编码进行转换
*/
byte[]b=str.getBytes("utf-8");
//想客户端(浏览器)输出数据
os.write(b);
}
}
浏览器中输入:http://localhost:8080/servlet_study/ServletDemo01,运行结果如下:
打开浏览器调试工具,可以看到相关编码信息:
1.2使用PrintWriter流向浏览器输出中文
package controller;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ServletDemo02 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String str="使用PrintWriter输出中文:我心自在";
//设置中文编码格式
response.setCharacterEncoding("utf-8");
//获取流
PrintWriter pw=response.getWriter();
//输出
pw.write(str);
pw.close();
}
}
浏览器中输入:http://localhost:8080/servlet_study/ServletDemo02,运行结果如下:
这里需要注意的是: 在获取PrintWriter输出流之前首先使用"response.setCharacterEncoding(charset)"设置字符以什么样的编码输出到浏览器,如:response.setCharacterEncoding(“UTF-8”);设置将字符以"UTF-8"编码输出到客户端浏览器,然后再使用response.getWriter();获取PrintWriter输出流,这两个步骤不能颠倒.如果颠倒,设置将无效,还是会出现中文乱码!
通过比较可以看出,当需要向浏览器输出字符数据时,使用PrintWriter比较方便,因为不需要将字符转化为字节这一步!
1、使用OutputStream流和PrintWriter流下载文件
最近在做一个项目,涉及到文件的下载,所以特意整理出来做个比较。
文件下载,在实际开发中用到的很多,最近做的项目便是,查看图片的时候,点击图片的时候进行图片下载,这里将这两个下载文件的区别做简要比较。
文件下载,运用的步骤比较固定,大致分为以下几步:
1.获取要下载的文件的绝对路径(注意是绝对路径)
2.获取要下载的文件名(获取文件名要注意中文文件名的问题,需进行编码)
3.设置content-disposition响应头控制浏览器,告诉浏览器以下载的形式打开文件
4.获取要下载的文件输入流
5.创建数据缓冲区
6.通过response对象获取OutputStream流
7.将FileInputStream流写入到buffer缓冲区
8.使用OutputStream将缓冲区的数据输出到客户端浏览器
2.1使用OutputStream流下载中文文件
package controller;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ServletDemo03 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取文件的下载绝对路径
String downloadPath=this.getServletContext().getRealPath("/download/阳光海滩.jpg");
//获取文件名
String fileName=downloadPath.substring(downloadPath.lastIndexOf("\\")+1);
//设置响应头,告诉浏览器以下载的方式打来文件,设置中文编码,如果不设置会出现乱码
response.setHeader("content-disposition", "attachment;filename="+URLEncoder.encode(fileName, "UTF-8"));
//获取文件流
InputStream is=new FileInputStream(downloadPath);
int len=0;
byte[]b=new byte[1024];
OutputStream os=response.getOutputStream();
while((len=is.read(b))!=-1){
//将缓冲区数据输出到浏览器
os.write(b,0,len);
}
is.close();
}
}
浏览器中输入:http://localhost:8080/servlet_study/ServletDemo03可以成功下载图片并且可以顺利打开,
2.1使用PrintWriter流下载中文文件
package controller;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.URLEncoder;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ServletDemo03 extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取文件的下载绝对路径
String downloadPath=this.getServletContext().getRealPath("/download/阳光海滩.jpg");
//获取文件名
String fileName=downloadPath.substring(downloadPath.lastIndexOf("\\")+1);
//设置响应头,告诉浏览器以下载的方式打来文件,设置中文编码,如果不设置会出现乱码
response.setHeader("content-disposition", "attachment;filename="+URLEncoder.encode(fileName, "UTF-8"));
//获取文件流
FileReader fr=new FileReader(downloadPath);
int len=0;
char[] b=new char[1024];
PrintWriter os=response.getWriter();
while((len=fr.read(b))!=-1){
//将缓冲区数据输出到浏览器
os.write(b,0,len);
}
fr.close();
}
}
浏览器中输入:http://localhost:8080/servlet_study/ServletDemo03可以成功下载,但是打开的过程中却出现了一下情况:
这是什么原因造成的呢?
PrintWriter流处理节数据,会导致数据丢失,因此在编写下载文件功能时,要使用OutputStream流,避免使用PrintWriter流,因为OutputStream流是字节流,可以处理任意类型的数据,而PrintWriter流是字符流,只能处理字符数据,如果用字符流处理字节数据,会导致数据丢失。