response
本节内容:
- HttpServletResponse概述
- response的运行流程
- 通过抓包工具抓取Http响应
- 通过response设置响应行
- 通过response设置响应头
- 通过response设置响应体
- 示例:文件下载
- 示例:实现验证码功能
一、HttpServletResponse概述
我们在创建Servlet时会覆盖service()方法,或doGet()/doPost(),这些方法都有两个参数,一个为代表请求的request和代表响应response。
service方法中的response的类型是ServletResponse,而doGet/doPost方法的response的类型是HttpServletResponse,HttpServletResponse是ServletResponse的子接口,功能和方法更加强大。
二、response的运行流程
三、通过抓包工具抓取Http响应
在前面的博客中介绍了如何抓取http响应:
因为response代表响应,所以我们可以通过该对象分别设置Http响应的响应行、响应头和响应体。
四、通过response设置响应行
手动设置响应行的状态码,tomcat将不会在帮response设置状态码了。
- setStatus(int sc)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | public class StatusServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //手动设置http响应行中的状态码 response.setStatus( 404 ); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } } |
五、通过response设置响应头
1. 响应头方法
- addHeader(String name, String value)
- addIntHeader(String name, int value) :有些头的值要求设置时是int类型的
- addDateHeader(String name, long date):比如有个头 date: "Thu, 09 Nov 2017 07:32:09 GMT"
- setHeader(String name, String value)
- setDateHeader(String name, long date)
- setIntHeader(String name, int value)
其中,add表示添加,而set表示设置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | public class HeaderServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Date date = new Date(); //设置响应头 response.addHeader( "name" , "zhangsan" ); response.addIntHeader( "age" , 28 ); response.addDateHeader( "birthday" , date.getTime()); response.addHeader( "name" , "lisi" ); //抓包:name:"zhangsan,lisi" response.setHeader( "age" , "28" ); response.setHeader( "age" , "50" ); //抓包:age:"50" } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } } |
【注意】:所有的头到客户端,name和value都是String类型的,只不过程序在设置的时候,有些value不是String类型的。
2. 重定向
假设客户端通过http请求向servlet1请求了一个资源,但是servlet1现在没有这个资源,servlet1会告诉客户端虽然它没这个资源,但是servlet2有这个资源,可以去找servlet2。然后客户端就去请求servlet2了。第二次访问不是人为的,是客户端自动去访问的。客户端能解析这个重定向的请求。
要实现重定向,要借助两个东西:
- 状态码:302
- 响应头:location 代表重定向的地址。
新建两个servlet:
servlet1.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | package com.itheima.header; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class Servlet1 extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //没有响应 告知客户端去重定向到servlet2 //1、设置状态码302 //response.setStatus(302); //2、设置响应头Location //response.setHeader("Location", "/WEB14/servlet2"); //封装成一个重定向的方法sendRedirect(url) response.sendRedirect( "/WEB14/servlet2" ); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } } |
servlet2.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | package com.itheima.header; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class Servlet2 extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.getWriter().write( "hello haohao..." ); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } } |
发布到tomcat中,浏览器访问:http://localhost:8080/WEB14/servlet1,你会发现最终浏览器url显示的是http://localhost:8080/WEB14/servlet2,页面输出的是
hello haohao...
但在实际开发中,重定向的代码都这么写,比较麻烦,于是J2EE工程师将上面设置状态码和响应头的代码封装到了一个方法中,最终代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 | protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //没有响应 告知客户端去重定向到servlet2 //1、设置状态码302 //response.setStatus(302); //2、设置响应头Location //response.setHeader("Location", "/WEB14/servlet2"); //封装成一个重定向的方法sendRedirect(url) response.sendRedirect( "/WEB14/servlet2" ); } |
3. refresh头
定时刷新,也是属于重定向,只不过有时间的延迟。比如下面的例子,5秒后向百度跳。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | public class RefreshServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //设置定时刷新的头 5是秒 response.setHeader( "refresh" , "5;url=http://www.baidu.com" ); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } } |
这个refresh头基本不用。
注册成功后会刷一会儿,然后跳到其他页面,但这不是用这个refresh头实现的,是js代码实现的。
【示例】:js完成页面定时跳转。
js代码实现注册成功,刷5秒钟,跳转到百度。在WebContent目录下写一个html,success.html。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | <! DOCTYPE html> < html > < head > < meta charset="UTF-8"> < title >Insert title here</ title > < script type="text/javascript"> window.onload = function(){ var time = 5; var secondEle = document.getElementById("second"); var timer = setInterval(function(){ secondEle.innerHTML = time; time--; if(time==0){ clearInterval(timer); location.href="http://www.baidu.com"; } },1000); } </ script > </ head > < body > 恭喜你,注册成功,< span style="color:red" id="second">5</ span >秒钟后跳转,如不跳转点击< a href="http://www.baidu.com">这里</ a >! </ body > </ html > |
六、通过response设置响应体
1. 响应体设置文本
PrintWriter getWriter()
获得字符流,通过字符流的write(String s)方法可以将字符串设置到 response 缓冲区中,随后Tomcat会将response缓冲区中的内容组装成Http响应返回给浏览 器端。
1 2 3 4 5 6 7 | protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { PrintWriter writer = response.getWriter(); writer.write( "hello response!!!" ); writer.write( "中国" ); } |
浏览器访问下,发现中文是乱码的。
关于设置中文的乱码问题:
原因:response缓冲区的默认编码是iso8859-1,此码表中没有中文,可以通过 response的setCharacterEncoding(String charset) 设置response的编码。
1 2 3 4 5 6 7 8 9 10 11 12 | protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //设置response查询的码表 response.setCharacterEncoding( "UTF-8" ); PrintWriter writer = response.getWriter(); writer.write( "hello response!!!" ); writer.write( "中国" ); //response将“中国”存到缓冲区内部时,在写的时候不是把“中国”存到内存中,存的是编码后的东西。需要查码表,默认查ISO-8859-1码表。 //该码表是西欧码表,外国人的码表中肯定没有中文。所以要换码表,换成带中文的。 } |
如果我们发现客户端还是不能正常显示文字:
原因:我们将response缓冲区的编码设置成UTF-8,但浏览器的默认编码是本地系统的编码,因为我们都是中文系统,所以客户端浏览器的默认编码是GBK,我们可以 手动修改浏览器的编码是UTF-8。比如Firefox浏览器,点击“查看”—>“文字编码”,改为“Unicode”。但是这种每次手动改显然是不合理的。
我们还可以在代码中指定浏览器解析页面的编码方式,通过response的setContentType(String type)方法指定页面解析时的编码是UTF-8
1 | response.setContentType( "text/html;charset=UTF-8" ); |
上面的代码不仅可以指定浏览器解析页面时的编码,同时也内含 setCharacterEncoding的功能,所以在实际开发中只要编写 response.setContentType("text/html;charset=UTF-8"); 就可以解决页面输出中文乱码问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //设置response查询的码表 //response.setCharacterEncoding("UTF-8"); //通过一个头 Content-Type 告知客户端解码时使用何种码表 //response.setHeader("Content-Type", "text/html;charset=UTF-8"); //当设置这个头的时候,tomcat容器会自动将response缓冲区的编码设置UTF-8。所以只要写这一句就可以了,上面的那句代码可以不写。 //封装后的方法。 response.setContentType( "text/html;charset=UTF-8" ); PrintWriter writer = response.getWriter(); writer.write( "hello response!!!" ); writer.write( "中国" ); //response将“中国”存到缓冲区内部时,在写的时候不是把“中国”存到内存中,存的是编码后的东西。需要查码表,默认查ISO-8859-1码表。 //该码表是西欧码表,外国人的码表中肯定没有中文。所以要换码表,换成带中文的。 } |
2. 响应体设置字节
上面返回客户端的都是文本,都是字符。如果想要往客户端写点图片,使用上面那种方式就不能写了,得使用I/O字节。
ServletOutputStream getOutputStream()
获得字节流,通过该字节流的write(byte[] bytes)可以向response缓冲区中写入字 节,在由Tomcat服务器将字节内容组成Http响应返回给浏览器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //使用response获得字节输出流 ServletOutputStream out = response.getOutputStream(); //获得服务器上的图片 String realPath = this .getServletContext().getRealPath( "a.jpg" ); InputStream in = new FileInputStream(realPath); int len = 0 ; byte [] buffer = new byte [ 1024 ]; //每次写1024bytes while ((len=in.read(buffer))> 0 ){ out.write(buffer, 0 , len); } in.close(); out.close(); } |
七、示例:文件下载
文件下载的实质就是文件拷贝,将文件从服务器端拷贝到浏览器端。所以文件下载需要IO技术将服务器端的文件使用InputStream读取到,在使用 ServletOutputStream写到response缓冲区中。
问题:
(1)什么情况下会文件下载?
浏览器不能解析的文件就下载。
(2)什么情况下需要在服务器端编写文件下载的代码?
理论上,浏览器可以解析的文件类型需要编写文件下载代码。实际上,只要是下载的文件都编写文件下载代码。因为不同浏览器内置的插件都不同,浏览器版本迭代等原因,无法判定哪些类型的文件不需要编写代码,点击就可以下载。
比如上面的例子中,a.jpg直接在浏览器就解析图片显示在页面上,我们得告诉客户端,让它不要解析,下载。我们需要设置两个响应头,告知浏览器文件的类型和文件的打开方 式。
告知浏览器文件的类型:response.setContentType(文件的MIME类型);
告示浏览器文件的打开方式是下载:response.setHeader("Content-Disposition","attachment;filename=文件名称");
【示例】:将文件存放的文件夹download放置于WebContent目录下。
代码如下:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <h1>使用a标签直接指向服务器上的资源</h1> <a href="/WEB14/download/a.flv">a.flv</a><br> <a href="/WEB14/download/a.jpg">a.jpg</a><br> <a href="/WEB14/download/a.mp3">a.mp3</a><br> <a href="/WEB14/download/a.mp4">a.mp4</a><br> <a href="/WEB14/download/a.txt">a.txt</a><br> <a href="/WEB14/download/a.zip">a.zip</a><br> <h1>使用服务器端编码的方式实现文件下载</h1> <a href="/WEB14/downloadServlet?filename=a.flv">a.flv</a><br> <a href="/WEB14/downloadServlet?filename=a.jpg">a.jpg</a><br> <a href="/WEB14/downloadServlet?filename=a.mp3">a.mp3</a><br> <a href="/WEB14/downloadServlet?filename=a.mp4">a.mp4</a><br> <a href="/WEB14/downloadServlet?filename=a.txt">a.txt</a><br> <a href="/WEB14/downloadServlet?filename=a.zip">a.zip</a><br> <a href="/WEB14/downLoadServlet2?filename=美女.jpg">美女.jpg</a><br> </body> </html>
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获得要下载的文件的名称 String filename = request.getParameter("filename");//a.flv //要下载的这个文件的类型-----客户端必须通过文件的MIME类型才能去区分类型。MIME可以去$TOMCAT_HOME/conf/web.xml里看到<mime-mapping>,它将文件的扩展名映射成一个MIME类型。 response.setContentType(this.getServletContext().getMimeType(filename)); //告诉客户端该文件不是直接解析,而是以附件形式打开(下载) response.setHeader("Content-Disposition", "attachment;filename="+filename); //获取该文件的绝对路径 String path = this.getServletContext().getRealPath("download/"+filename); //获得该文件的输入流 InputStream in = new FileInputStream(path); //获得输出流---通过response获得输出流,用于向客户端写内容 ServletOutputStream out = response.getOutputStream(); //文件拷贝的模板代码,后面可以封一个方法 int len = 0; byte[] buffer = new byte[1024]; while((len=in.read(buffer))>0){ out.write(buffer, 0, len); } in.close(); //out.close(); //这个可以不关,这个out是通过response获得的,web容器会帮忙检查到底关没关,没关的话,会帮忙关掉 }
但是,如果下载的文件名字中含有中文,页面在下载时会出现中文乱码或不能显示文件名的情况, 原因是不同的浏览器默认对下载文件的编码方式不同,ie是UTF-8编码方式,而火狐浏览器是Base64编码方式。所里这里需要解决浏览器兼容性问题,解决浏览器兼容性问题的首要任务是要辨别访问者是ie还是火狐(其他),通过Http请求体中的一个属性可以辨别。
解决乱码方法如下(不要记忆--了解):
if (agent.contains("MSIE")) { // IE浏览器 filename = URLEncoder.encode(filename, "utf-8"); filename = filename.replace("+", " "); } else if (agent.contains("Firefox")) { // 火狐浏览器 BASE64Encoder base64Encoder = new BASE64Encoder(); filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?="; } else { // 其它浏览器 filename = URLEncoder.encode(filename, "utf-8"); }
其中agent就是请求头User-Agent的值。
DownLoadServlet2.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | package com.itheima.content; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URLEncoder; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import sun.misc.BASE64Encoder; public class DownLoadServlet2 extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //*******文件名称是中文的下载******* //获得要下载的文件的名称 String filename = request.getParameter( "filename" ); //????.jpg //解决获得中文参数的乱码 filename = new String(filename.getBytes( "ISO8859-1" ), "UTF-8" ); //美女.jpg //获得请求头中的User-Agent String agent = request.getHeader( "User-Agent" ); //根据不同浏览器对文件名进行不同的编码。 String filenameEncoder = "" ; if (agent.contains( "MSIE" )) { // IE浏览器 filenameEncoder = URLEncoder.encode(filename, "utf-8" ); filenameEncoder = filenameEncoder.replace( "+" , " " ); } else if (agent.contains( "Firefox" )) { // 火狐浏览器 BASE64Encoder base64Encoder = new BASE64Encoder(); filenameEncoder = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes( "utf-8" )) + "?=" ; } else { // 其它浏览器 filenameEncoder = URLEncoder.encode(filename, "utf-8" ); } //要下载的这个文件的类型-----客户端通过文件的MIME类型去区分类型 response.setContentType( this .getServletContext().getMimeType(filename)); //告诉客户端该文件不是直接解析 而是以附件形式打开(下载)----filename="+filename,客户端默认对名字进行解码。如果上面不采取编码,传过来的就是“美女.jpg” response.setHeader( "Content-Disposition" , "attachment;filename=" +filenameEncoder); //获取文件的绝对路径 String path = this .getServletContext().getRealPath( "download/" +filename); //获得该文件的输入流 InputStream in = new FileInputStream(path); //获得输出流---通过response获得的输出流 用于向客户端写内容 ServletOutputStream out = response.getOutputStream(); //文件拷贝的模板代码 int len = 0 ; byte [] buffer = new byte [ 1024 ]; while ((len=in.read(buffer))> 0 ){ out.write(buffer, 0 , len); } in.close(); //out.close(); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } } |
注意:
(1)response获得的流不需要手动关闭,web容器(tomcat)会帮助我们关闭。
(2)getWriter和getOutputStream不能同时调用。
1 2 3 4 5 6 | protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.getOutputStream(); response.getWriter(); } |
访问时报错:
(3)response缓冲区默认大小是8KB,可以修改。response.getbufferSize()。
(4)重定向后的代码还是会执行的,所以建议把重定向代码作为终结代码。
1 2 3 4 5 6 | protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.sendRedirect(location); response.getWriter().write( "hello haohao..." ); //重定向后的代码还是会执行的,所以建议把重定向代码作为终结代码 } |
八、实现验证码功能
验证码是图片,java中有生成图片的API。图片中的字符可以在生成图片的时候告诉API。生成的图片通过img标签显示在html中。只是img标签中的src不能在写一个固定的图片地址,因为要动态生成,所以要写一个Servlet地址,这个Servlet负责往客户端写图片。
login.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <! DOCTYPE html> < html > < head > < meta charset="UTF-8"> < title >Insert title here</ title > < script type="text/javascript"> function changeImg(obj){ obj.src="/WEB14/checkImg?time="+new Date().getTime(); //这个src地址必须和原有的地址不一样,否则不会去请求 } </ script > </ head > < body > < form action="/WEB13/login" method="post"> 用户名:< input type="text" name="username">< br /> 密码:< input type="password" name="password">< br /> 验证码:< input type="text" name="username">< img onclick="changeImg(this)" src="/WEB14/checkImg">< br /> < input type="submit" value="登录">< br /> </ form > </ body > </ html > |
CheckImgServlet.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | package com.itheima.checkimg; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Random; import javax.imageio.ImageIO; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * 验证码生成程序 */ public class CheckImgServlet extends HttpServlet { // 集合中保存所有成语 private List<String> words = new ArrayList<String>(); @Override public void init() throws ServletException { // 初始化阶段,读取new_words.txt。文件中是一些4字成语,我这里验证码用的是中文的,当然也可以用随机数。 // web工程中读取文件,必须使用绝对磁盘路径 String path = getServletContext().getRealPath( "/WEB-INF/new_words.txt" ); try { BufferedReader reader = new BufferedReader( new FileReader(path)); String line; while ((line = reader.readLine()) != null ) { //每次读一行,放入集合中。 words.add(line); } reader.close(); } catch (IOException e) { e.printStackTrace(); } } public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 禁止缓存 // response.setHeader("Cache-Control", "no-cache"); // response.setHeader("Pragma", "no-cache"); // response.setDateHeader("Expires", -1); int width = 120 ; int height = 30 ; // 步骤一 绘制一张内存中图片 BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); // 步骤二 图片绘制背景颜色 ---通过绘图对象 Graphics graphics = bufferedImage.getGraphics(); // 得到画图对象 --- 画笔 // 绘制任何图形之前 都必须指定一个颜色 graphics.setColor(getRandColor( 200 , 250 )); graphics.fillRect( 0 , 0 , width, height); // 步骤三 绘制边框 graphics.setColor(Color.WHITE); graphics.drawRect( 0 , 0 , width - 1 , height - 1 ); // 步骤四 四个随机数字 Graphics2D graphics2d = (Graphics2D) graphics; // 设置输出字体 graphics2d.setFont( new Font( "宋体" , Font.BOLD, 18 )); Random random = new Random(); // 生成随机数 int index = random.nextInt(words.size()); String word = words.get(index); // 从集合中随机获得成语 // 定义x坐标 int x = 10 ; for ( int i = 0 ; i < word.length(); i++) { // 随机颜色 graphics2d.setColor( new Color( 20 + random.nextInt( 110 ), 20 + random .nextInt( 110 ), 20 + random.nextInt( 110 ))); // 旋转 -30 --- 30度 int jiaodu = random.nextInt( 60 ) - 30 ; // 换算弧度 double theta = jiaodu * Math.PI / 180 ; // 获得字母数字 char c = word.charAt(i); // 将c 输出到图片 graphics2d.rotate(theta, x, 20 ); graphics2d.drawString(String.valueOf(c), x, 20 ); graphics2d.rotate(-theta, x, 20 ); x += 30 ; } // 将验证码内容保存session request.getSession().setAttribute( "checkcode_session" , word); // 步骤五 绘制干扰线 graphics.setColor(getRandColor( 160 , 200 )); int x1; int x2; int y1; int y2; for ( int i = 0 ; i < 30 ; i++) { x1 = random.nextInt(width); x2 = random.nextInt( 12 ); y1 = random.nextInt(height); y2 = random.nextInt( 12 ); graphics.drawLine(x1, y1, x1 + x2, x2 + y2); } // 将上面图片输出到浏览器 ImageIO graphics.dispose(); // 释放资源 //将图片写到response.getOutputStream()中 ImageIO.write(bufferedImage, "jpg" , response.getOutputStream()); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } /** * 取其某一范围的color * * @param fc * int 范围参数1 * @param bc * int 范围参数2 * @return Color */ private Color getRandColor( int fc, int bc) { // 取其随机颜色 Random random = new Random(); if (fc > 255 ) { fc = 255 ; } if (bc > 255 ) { bc = 255 ; } int r = fc + random.nextInt(bc - fc); int g = fc + random.nextInt(bc - fc); int b = fc + random.nextInt(bc - fc); return new Color(r, g, b); } } |
【注意】:生成图片的代码不需要记,网上一查有很多生成图片的代码。但是图片生成后怎么往客户端写,这个需要会。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
· .NET 9 new features-C#13新的锁类型和语义
· 手把手教你在本地部署DeepSeek R1,搭建web-ui ,建议收藏!
· Spring AI + Ollama 实现 deepseek-r1 的API服务和调用
· 《HelloGitHub》第 106 期
· 数据库服务器 SQL Server 版本升级公告
· C#/.NET/.NET Core技术前沿周刊 | 第 23 期(2025年1.20-1.26)