浅析Response对象&&Request对象

xiaoxiao2021-02-28  123

response和request是什么?在开发中,他们又扮演着什么样的角色呢?

web服务器收到客户端的HTTP请求,会针对每一次请求分别创建一个用于代表请求的request对象和代表响应的response对象。

Request和Response对象起到了服务器与客户机之间的信息传递作用。Request对象用于接收客户端浏览器提交的数据,而 Response对象的功能则是将服务器端的数据发送到客户端浏览器。

Response对象

HttpServletResponse对象代表客户端的响应,其中封装了向客户端发送数据、发送响应头、发送状态等信息。

几个常见的应用实例:

1.如何在Servlet中用OutputStream和Writer输出中文和数字?

//-------------------OutputStream---------------------- package com.Cecilia.responseTest; import java.io.IOException; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * 需求:在Servlet中用OutputStream输出中文 * @author 芷若初荨 * @Date 2017.5.4 */ public class responseTest extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub test1(resp);//测试一 test2(resp);//测试二 test3(resp);//测试三 test4(resp);//测试四 } //解决乱码方式1:程序以哪种编码格式输出,就应该控制浏览器以哪种编码格式打开 private void test1(HttpServletResponse resp) throws IOException, UnsupportedEncodingException { resp.setHeader("Content-type", "text/html;charset=UTF-8"); String data="芷若初荨"; OutputStream out=resp.getOutputStream(); out.write(data.getBytes("UTF-8")); } //解决乱码方式2:使用html中标签meta模拟一个http响应头来控制浏览器输出的编码格式 private void test2(HttpServletResponse resp) throws IOException, UnsupportedEncodingException { resp.setHeader("Content-type", "text/html;charset=UTF-8"); String data="芷若初荨"; OutputStream out=resp.getOutputStream(); out.write("<meta http-equiv='content-type' content='text.html;charet=UTF-8'>".getBytes()); out.write(data.getBytes("UTF-8")); } //注意的问题:以下的错误写法会导致文件下载 private void test3(HttpServletResponse resp) throws IOException, UnsupportedEncodingException { resp.setHeader("Content-type", "text/html;charset=UTF-8"); String data="芷若初荨"; OutputStream out=resp.getOutputStream(); out.write(data.getBytes("UTF-8")); } //如果想要输出预想的数字,需要将其以字符串的形式输出(因为首先在程序中通过编码格式查询数字所在文本编码格式,然后在浏览器对应的编码格式表 //中查询对应的编码序号,最后输出的就不是浏览器对应编码格式中数字对应的内容,不是预想的数字结果,所以在这里需要将其转化成数字来输出) private void test4(HttpServletResponse resp) throws IOException, UnsupportedEncodingException { OutputStream out=resp.getOutputStream(); out.write((1+"").getBytes("UTF-8"));//将其转化成字符串输出 } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doGet(req, resp); } } //-------------------PrintWriter--------------- /** * 需求:response的writer流输出的数据的问题 * @author 芷若初荨 * */ public class WriterTest extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub test1(resp); } private void test1(HttpServletResponse resp) throws IOException { //指定浏览器发送数据的编码格式 //resp.setHeader("content-type", "text/html;charset=UTF-8"); resp.setContentType("text/html;charset=UTF-8"); //设置response使用的编码格式,以控制response以哪种码表向浏览器写出数据 resp.setCharacterEncoding("UTF-8"); String data="芷若初荨"; PrintWriter pw=resp.getWriter();//获取writer流——注意:write只能写字符串 pw.write(data); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doGet(req, resp); } }

2.如何实现文件下载?

(PS:resp.setHeader(“content-disposition”,”attachment;filename=”+URLEncoder.encode(filename,”UTF-8”)))

/** * 需求:实现文件下载 * @author 芷若初荨 * */ public class DownloadTest extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub //获取当前资源的文件路径 String path=this.getServletContext().getRealPath("/source/66.jpg"); //获取资源文件名 String filename=path.substring(path.lastIndexOf("\\")+1); //resp.setHeader("content-disposition","attachment;filename="); //在此处只能解决英文文件名资源,如果要解决中文文件资源的问题,如下解决方法 resp.setHeader("content-disposition","attachment;filename="+URLEncoder.encode(filename,"UTF-8")); //读写 //获取输入输出流,并初始化为null InputStream in=null; OutputStream out=null; try{ in=new FileInputStream(path); int len=0; byte buffer[]=new byte[1024]; out=resp.getOutputStream(); while((len=in.read(buffer))>0){ out.write(buffer,0,len); } }finally{ if(in!=null){ try{ in.close();//关闭输入流 }catch(Exception e){ e.printStackTrace(); } } if(out!=null){ try{ out.close();//关闭输出流 }catch(Exception e){ e.printStackTrace(); } } } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doGet(req, resp); } }

3.如何控制浏览器定时刷新?(refresh)

/** * 应用:控制浏览器定时刷新 * @author 芷若初荨 * */ public class SetReflur extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub //test1(resp);//实现每隔3s浏览器刷新一次 test2(resp); } private void test2(HttpServletResponse resp) throws IOException { //假设当前是一个登录注册的servlet //假设运行到此用户登录成功 String message="<meta http-equiv='refresh' content='3;url=/responseTest/index.jsp'>恭喜你,登陆成功,本页面将在3s后跳回首页,如果没有跳,请<a href=''>点击</a>"; resp.setCharacterEncoding("UTF-8");//设置指定浏览器的编码格式 resp.setContentType("text/html;charset=UTF-8");//设置资源的编码格式UTF-8 this.getServletContext().getRequestDispatcher("/responseTest/index.jsp"); this.getServletContext().setAttribute("message",message); } private void test1(HttpServletResponse resp) throws IOException { resp.setHeader("refresh", "3");//每隔3s刷新一次 String data=new Random().nextInt(10000)+""; resp.getWriter().write(data); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doGet(req, resp); } }

4.如何实现浏览器缓存当前数据?(expries)

/** * 需求:控制浏览器缓存当前文件内容 * @author 芷若初荨 * */ public class ControlCacheTest extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub resp.setDateHeader("expries", System.currentTimeMillis()+1000*3600);//缓存的时间:1000*3600 String data="Cecilia"; resp.getWriter().write(data); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doGet(req, resp); } }

5.如何实现输出随机图片(一般场景用在登录界面页面,防止恶意注册)?

/** * 需求:输出随机图片(一般场景用在登录界面页面,防止恶意注册) * BufferImage * @author 芷若初荨 * */ public class RandomPic extends HttpServlet{ public static final int WIDTH=120; public static final int HEIGHT=50; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub //创建一个图片 BufferedImage img=new BufferedImage(WIDTH,HEIGHT,BufferedImage.TYPE_INT_RGB); Graphics g=img.getGraphics(); //1.设置背景色 setBackground(g); //2.设置边框 setBorder(g); //3.画干扰线 drawRandomLine(g); //4.写随机数 drawRandomNum((Graphics2D)g); //5.图形写给浏览器 resp.setContentType("image/ipeg"); ImageIO.write(img, "jpg", resp.getOutputStream()); //此处会出现一个问题:就是未控制浏览器不要缓存,这样会出现图片不能刷新得到全新的图片 //控制浏览器不要缓存(默认条件下,浏览器会缓存) resp.setDateHeader("expires", -1); resp.setHeader("Cache-Control", "no-cache"); resp.setHeader("Pragma", "no-cache"); } private void drawRandomNum(Graphics2D g) { //将其转化成Graphics2D,其中包含旋转的方法 // TODO Auto-generated method stub g.setColor(Color.red); g.setFont(new Font("宋体",Font.BOLD,20));//Font构造函数中包含三个参数:字体样式、字体粗细正斜、字体大小 //字体区间:[\u4e00-\u9fa5],表示所有汉字在Unicode的4e00和9fa5之间 String base="\u7684\u4e00\u4e86\u6765\u4ed6\u6211\u662f";//定义初始文字 for(int i=0;i<4;i++){ int x=5; //实现字体旋转rotate int degree=new Random().nextInt()%30;//-30~30,nextInt()产生的是整数范围,包括正负数 String ch=base.charAt(new Random().nextInt(base.length()))+""; //设置旋转的角度 g.rotate(degree*Math.PI/180,x,20); g.drawString(ch, x, 20); x+=30; } } private void drawRandomLine(Graphics g) { // TODO Auto-generated method stub g.setColor(Color.GREEN); for(int i=0;i<6;i++){ int x1=new Random().nextInt(WIDTH); int y1=new Random().nextInt(HEIGHT); int x2=new Random().nextInt(WIDTH); int y2=new Random().nextInt(HEIGHT); //画线 g.drawLine(x1, y1, x2, y2); } } //设置边框 private void setBorder(Graphics g) { // TODO Auto-generated method stub g.setColor(Color.blue); g.fillRect(1, 1, WIDTH-2, HEIGHT-2); } //设置背景色 private void setBackground(Graphics g) { // TODO Auto-generated method stub g.setColor(Color.WHITE); g.fillRect(0, 0, WIDTH, HEIGHT); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doGet(req, resp); } }

6.如何使用response重定向?(sendRedirect)

/** * 需求:实现请求重定向(一般用在登录页面) **状态码:302 * location *||resp.sendRedirect("/ResponseWebTest/index.jsp") * @author 芷若初荨 *重定向的特点: *1.浏览器会向服务器发送两次,意味着有两个Servlet; *2.用重定向技术,浏览器地址栏会发生变化。 */ public class RedirectTest extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub // //方法一:状态码+location // resp.setStatus(302); // resp.setHeader("location", "/ResponseWebTest/index.jsp"); //方法二:sendRedirect resp.sendRedirect("/ResponseWebTest/index.jsp"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doGet(req, resp); } }

小结response使用的一些细节

1.在转发或者做开发的过程中,不要同时调用OutPutStream和getWriter,否则会出现500错误;但是在重定向时,则不会出现这样的问题,因为重定向时创建了两个servlet;

2.HttpServletRequest对象代表客户端的请求,当客户端通过Http协议访问服务器时,Http请求头中的所有信息都封装在这个对象中,可以通过这个对象获取客户的相关信息。

Request对象

HttpServletRequest对象代表客户端的请求,当客户端通过Http协议访问服务器时,Http请求头中的所有信息都封装在这个对象中,可以通过这个对象获取客户的相关信息。

几个常见的应用实例:

1.HttpServletRequest中一些常用的方法

(PS:其中提供5种获取数据的方法)

public class RequestMethodTest extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub //打印IP System.out.println(req.getRequestURI());//资源部分名 System.out.println(req.getRequestURL());//http名 //返回请求行中带有的参数 System.out.println(req.getQueryString()); //获取当前访问的ip地址 System.out.println(req.getRemoteAddr()); //返回发出请求的客户机的完整主机名(如果在DNS上注册,返回的是主机名,如果没有注册,返回的还是ip) System.out.println(req.getRemoteAddr()); //返回远程的端口号 System.out.println(req.getRemotePort()); //返回客户机的请求方式 System.out.println(req.getMethod()); //获取请求头和请求数据方法 getHeadData(req); //获取数据的方法 try { getDataMethods(req); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } //获取数据的方法(注意:一般获取数据一定要先检查再使用) private void getDataMethods(HttpServletRequest req) throws Exception { //方法一:getParameter String value=req.getParameter("uername"); if(value!=null&&!value.trim().equals("")){ System.out.println(value); } //方法二:getParameterNames Enumeration e=req.getParameterNames(); while(e.hasMoreElements()){ String name=(String) e.nextElement(); String value1=req.getParameter(name); System.out.println(name+"="+value1); } //方法三:getParameterValues——获取所有的用户名数据 String[] values=req.getParameterValues("username"); for(String username:values){ System.out.println(username); } //方法四:getParameterMap——将数据以Map形式返回 Map<String,String[]> map=req.getParameterMap(); User user=new User(); //用map集合的数据填充bean //BeanUtils.populate(user,map);//导入包:commons-beanutils.jar和common-logging.jar //使用bean的拷贝 //BeanUtils.copypropertites(user,map); System.out.println(user); //方法五:getInputStream——以流的形式返回(一般用在文件上传) InputStream in=req.getInputStream(); int len=0; byte buffer[]=new byte[1024]; while((len=in.read(buffer))>0){ System.out.println(len); System.out.println(new String(buffer,0,len)); } } private void getHeadData(HttpServletRequest req) { //获取请求头和请求数据方法 //方法一:getHeader获取头部数据 String headValue=req.getHeader("Accept-Encoding"); System.out.println(headValue); //方法二:获取所有的头部数据——getHeaders Enumeration e=req.getHeaders("Accept-Encoding"); while(e.hasMoreElements()){ String value=(String) e.nextElement();//查找下一个 System.out.println(value); } //方法三:通过获取请求头的名称获取头部内容数据 e=req.getHeaderNames(); while(e.hasMoreElements()){ String name=(String) e.nextElement(); String value=req.getHeader(name); System.out.println(name+"="+value); ; } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doGet(req, resp); } }

2.如何解决request中文乱码问题?(提供2种方法)

/** * 需求:解决request中文乱码问题 * @author 芷若初荨 * */ public class MessyCodeTest extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub //方法一:只对POST提交方式有效的中文乱码解决方法 messyCodeMethodTest(req); //方法二:解决get提交的乱码,需要手工处理username=new String(username.getBytes("iso8859-1"),"UTF-8"); messyCodeMethodTest1(req); //超链接提交的中文乱码问题的解决方式也需要手工处理 } //方法二:解决get提交的乱码,需要手工处理 private void messyCodeMethodTest1(HttpServletRequest req) throws UnsupportedEncodingException { String username=req.getParameter("username"); username=new String(username.getBytes("iso8859-1"),"UTF-8"); System.out.println(username); } private void messyCodeMethodTest(HttpServletRequest req) throws UnsupportedEncodingException { //方法一:setCharacterEncoding指定request发送的数据的编码格式 req.setCharacterEncoding("UTF-8");//这种方式只对提交方式为post有效 String username=req.getParameter("username"); System.out.println(username); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doGet(req, resp); } }

3.如何通过表单收集客户机的数据? (对于数据的处理,一定要先检查再使用)

/** * 需求:通过表单收集客户机的数据 * 准备:需要写一个form表单,上面带有用户名,密码,性别,所在地等信息数据 * !!注意:在获取数据时必须要检查数据是否为空,以防因客户机未填写数据而导致空指针问题,提高代码的健壮性。 * @author 芷若初荨 * */ public class CollectClientData extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub String username=req.getParameter("username"); String password=req.getParameter("password"); String gender=req.getParameter("gender"); String city=req.getParameter("city"); String hobbies[]=req.getParameterValues("hobbies"); for(int i=0;i<hobbies.length;i++){ if(hobbies[i]!=null&&hobbies[i].trim().equals("")){ } System.out.println(hobbies[i]); } if(username!=null&&!username.trim().equals("")){ System.out.println(username); } if(password!=null&&!password.trim().equals("")){ System.out.println(password); } if(gender!=null&&!gender.trim().equals("")){ System.out.println(gender); } if(city!=null&&!city.trim().equals("")){ System.out.println(city); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doGet(req, resp); } }

4.如何实现防盗链?(使用request)

首先说下,何为防盗链?防盗链是指一个内容不在自己服务器上,而通过技术手段,绕过别人放广告有利益的最终页,直接在自己的有广告有利益的页面上向最终用户提供此内容的现象。(常常是一些名不见经传的小网站来盗取一些有实力的大网站的地址(比如一些音乐、图片、软件的下载地址)然后放置在自己的网站中,通过这种方法盗取大网站的空间和流量)。

有时候我们从一个网站,比如腾讯,转载了一篇文章到自己的博客或空间,发现一些图片显示不了,这就是防盗链在起作用。图片是放在腾讯的服务器上的,腾讯拒绝其它网站的页面访问该资源。

一般情况下,当我们浏览一个网页时,并不是一次请求就会把整个页面的内容传到本地浏览器,尤其是当这个页面带有图片或者其它资源。第一次请求会传回该页面的HTML文本,浏览器解析该文本发现还有图片,会发送第二次请求,请求获得图片。盗链问题在于如果一个网站没有页面中所说的资源,它就会把这个图片链接到别的网站,这样没有任何资源的网站利用了别的网站的资源来展示给浏览者,提高了自己的访问量,而大部分浏览者又不会很容易地发现,这样显然,对于那个被利用了资源的网站是不公平的。一些不良网站为了不增加成本而扩充自己站点内容,经常盗用其他网站的链接。一方面损害了原网站的合法利益,另一方面又加重了服务器的负担。

所以一般情况下,我们需要给自己的网站设置一个防盗链的机制。通过referer,网站可以检测目标网页访问的来源网页,如果是资源文件,则可以跟踪到显示它的网页地址。有了referer跟踪来源就好办了,这时就可以通过技术手段来进行处理,一旦检测到来源不是本站即进行阻止或者返回指定的页面。

例如:

/** * 需求:实现referer防盗链的现象 * * @author 芷若初荨 * */ public class FangdaoLian extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub String referer=req.getHeader("referer"); if(referer==null||referer.startsWith("http://localhost")){ //此处采用重定向的原因:重定向会是地址发生变化,这样可以让用户看到页面显示结果,如果使用转发forword,那么地址不会发生变化,那么用户就不会发生变化。 resp.sendRedirect("/ResponseTest/index.jsp"); } String data="芷若初荨"; resp.getWriter().write(data); /* * jsp代码中: * body中: * 1.<a href="Response/servlet/FangdaoLian">查看图书</a> * 2.<br/>广告<br/> * 3.<a href="Response/servlet/MessyCodeTest">中文乱码解决方法</a> * 用户如果看到有兴趣的内容想要查看,那么想要点击链接2,那么会跳转到另一个页面显示 * */ } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doGet(req, resp); } }

5.如何在MVC模式下,实现请求转发,以及使用request域对象把数据带给转发资源?

(PS:req.getRequestDispatcher(“/index.jsp”).forward(req, resp))

/** * 需求:在MVC模式下,实现请求转发,以及使用request域对象把数据带给转发资源 * @author 芷若初荨 * */ public class RequestForwordTest extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub String data="芷若初荨"; req.setAttribute("cc", data); //请求转发 req.getRequestDispatcher("/index.jsp").forward(req, resp);; } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub doGet(req, resp); } }

其中使用到的req.getRequestDispatcher(“/index.jsp”).forward(req, resp)就是转发的核心用法,但是也需要注意下以下细节:

**在请求转发之前,不能将write的流给关掉,否则跳转无效!!!

以下通过一个事例来说明:

eg:String data=""; if(true){ request.getRequestDispatchter("/index.jsp").forword(request,response); return;//如果在请求转发之后没有return,那么就会发生无效跳转状态错误。 } request.getRequestDispatchter("/message.jsp").forword(request,response);

**在每次forword跳转之前,会将response中的数据给清空;但是写入的头信息还是有效的。

**每次forword只会发生一次请求,并且地址栏不会发生改变。

PS:如有错,请指正!

转载请注明原文地址: https://www.6miu.com/read-58971.html

最新回复(0)