如何从response里面取出向客户端输出的html流

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何从response里面取出向客户端输出的html流相关的知识,希望对你有一定的参考价值。

1、首先我们来创建一个类名为OutServlet的类,接下来让它继承HttpServelt类,然后重写doGet和doPost的方法。

2、然后我们在web.xml配置OutServlet的相关的信息,比如类的全路径和访问路径。

3、接下来我们在OutServlet的doGet方法中利用response对象调用getOutputStream()获取一个OutputStream的对象。然后我们来调用OutpuStream对象的write()方法输出一个字节数组,这个字节数组由中文字符串转化得来。

4、利用OutputStream这种方式输出中文有可能产生乱码。注意是有可能,而不是一定产生乱码。

5、为了让它实现无论用什么浏览器都不会乱码,我们来设置浏览器打开这个文件的编码方式;然后设置文件的编码方式。让两者的编码方式一致,它就不会乱码了。

参考技术A 项目里需要在把servlet,jsp生成的html代码存储到数据库中。如何解决,比较直接的想法是客户端用xmlhttp,或者直接在客户端js代码里发出请求,然后把得到的html代码在作为提交数据发送给服务器端,由服务器端程序接受并存入数据库中。
但是此方法需要耗费两次网络传输,肯定性能不加,而且处理起来要几块程序同时协作才行。还是想办法从服务器端直接获取。因为从response无法直接得到输出流,得想其他的办法。一种是干脆在服务器端写一个监控socket接口的客户端程序,或者用httpunit帮助完成,就是把客户端程序移到服务器端执行。还是相对比较复杂,能不能从response入手?
答案是肯定的,采用response代理来截获response的几个输出函数,然后存储起来,已备查询。
灵感来自于前一阵一直研究的java动态代理机制(现在应用在spring的aop实现中),此处不用动态代理,就使用静态代理,proxy模式就足够了。
分别实现三个代理类:ServletResponseProxy,ServletOutputStreamProxy,PrintWriterProxy
Responseproxy 主要代码:
public class ServletResponseProxy implements HttpServletResponse
private HttpServletResponse obj;//实际的HttpServletResponse 实例

public ServletResponseProxy(HttpServletResponse obj)
this.obj = obj;
HtmlBuffer.cleanStr(); //情空缓存


//获得outputStreamProxy
public ServletOutputStream getOutputStream() throws IOException
ServletOutputStream so = obj.getOutputStream();
ServletOutputStreamProxy sop = new ServletOutputStreamProxy(so);
return sop;

//获得printWriterProxy
public PrintWriter getWriter() throws IOException
PrintWriter pw = obj.getWriter();
PrintWriterProxy pwp = new PrintWriterProxy(pw);
return (PrintWriter) pwp;



PrintWriterProxy:

public class PrintWriterProxy
extends PrintWriter
private PrintWriter pw = null;

public PrintWriterProxy(PrintWriter pw)
super(pw);
this.pw = pw;

//截获写内容写入buffer
public void write(int c)
char a = (char) c;
String s = new String(new char[] a);
HtmlBuffer.addStr(s);
pw.write(c);



ServletOutputStreamProxy:
public class ServletOutputStreamProxy
extends ServletOutputStream
private ServletOutputStream obj;
public ServletOutputStreamProxy(ServletOutputStream obj)
this.obj = obj;

//截获写内容写入buffer
public void write(int b) throws IOException
Integer it = new Integer(b);
HtmlBuffer.addStr(new String(new byte[]it.byteValue()));
obj.write(b);



由于web Httpserver 是多线程执行服务端程序,所以buffer应该分线程来存取,这样大家才能不互相干扰。所以buffer需要实现TreadLocal接口。
HtmlBuffer代码简单实现如下:
public class HtmlBuffer
private static class HtmlInfo extends ThreadLocal
private Map values = Collections.synchronizedMap(new HashMap());
public Object initialValue()
return new String();

public String getHtmlStr()
return (String) this.get();

public Object get()
Thread curThread = Thread.currentThread();
Object o = values.get(curThread);
if (o == null && !values.containsKey(curThread))
o = initialValue();
values.put(curThread, o);

return o;

public void set(Object newValue)
values.put(Thread.currentThread(), newValue);


private static HtmlInfo htmlInfo = new HtmlInfo();

public static void cleanStr()
htmlInfo.set( "");

public static void addStr(String htmlStr)
String htmlstr = (String)htmlInfo.get();
if(htmlstr == null) htmlstr ="";
htmlstr += htmlStr;
htmlInfo.set( htmlstr);

public static String getStr()
return (String)htmlInfo.get();

本回答被提问者和网友采纳

day09 request 和response

Web服务器收到客户端的http请求,会针对每一次请求,分别创建一个用于代表请求的request对象、和代表响应的response对象。 request和response对象即然代表请求和响应,那我们要获取客户机提交过来的数据,只需要找request对象就行了。要向容器输出数据,只需要找response对象就行了。

HttpServletResponse对象代表服务器的响应。这个对象中封装了向客户端发送数据、发送响应头,发送响应状态码的方法。

response 常用的API

设置编码格式

response. setContentType(“text/html;charset=UTF-8”);

客户端清理缓存

 

response.addHeader("Pragma", "no-cache");

response.setHeader("Cache-Control", "no-cache");

response.setHeader("Expires", "0");

请求重定向指:一个web资源收到客户端请求后,通知客户端去访问另外一个web资源,这称之为请求重定向。 地址栏会变,并发送2次请求,增加服务器负担 实现方式 response.sendRedirect()

在response API中提供sendRedirect() --- 完成302+Location重定向效果
例如:response.sendRedirect("/day06/welcome.html");

状态:

200 请求处理成功
302 客户端重定向
304 客户端访问资源没有被修改,客户端访问本地缓存
404 访问资源不存在
500 服务器内部出错

response.sendRedirect("/day06/welcome.html");

getOutputStream 和getWriter 区别

1)getOutputStream和getWriter不能同时使用
2)必须在getOutputStream喝getWriter之前设置响应编码
3)getOutputStream和getWriter输出内容是HTTP响应体
4)getOutputStream和getWriter存在缓冲区,在service方法结束时,自动关闭流,flush缓冲区内容

例子:

ServletOutputStream sos = response.getOutputStream();
sos.write("你好123".getBytes("UTF-8"));//getBytes默认编码为本地编码(即:gbk)

 

文件下载 

response.setHeader("Content-Disposition","attachment;filename="+filename); ----设置文件以附件形式下载(对于浏览器识别格式文件)

例如:

public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//通过路径得到一个输入流
String path = this.getServletContext().getRealPath("/WEB-INF/classes/美女.jpg");

FileInputStream fis = new FileInputStream(path);
//创建字节输出流
ServletOutputStream sos = response.getOutputStream();

//得到要下载的文件名
String filename = path.substring(path.lastIndexOf("\\\\")+1);

//设置文件名的编码
filename = URLEncoder.encode(filename, "UTF-8");//将不安全的文件名改为UTF-8格式

//告知客户端要下载文件
response.setHeader("content-disposition", "attachment;filename="+filename);
response.setHeader("content-type", "image/jpeg");

//执行输出操作
int len = 1;
byte[] b = new byte[1024];
while((len=fis.read(b))!=-1){
sos.write(b,0,len);
}

sos.close();
fis.close();
}

public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}

}

 刷新网页3秒钟之后重定向
response.setHeader("refresh", "3;url=http://www.baidu.com");

HttpServletRequest

HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,开发人员通过这个对象的方法,可以获得客户这些信息。 查看request的API文档

 

getMethod(); 获得请求方式
// ***getRequestURL();返回客户端发出请求时的完整URL。
// ***getRequestURI(); 返回请求行中的资源名部分。
// *****getContextPath(); 当前应用的虚拟目录 /day09_01_HttpServletRequest
// getQueryString() ; 返回请求行中的参数部分。

例如:

System.out.println(request.getMethod());// GET
System.out.println(request.getRequestURL()); // http://localhost:8080/day09_01_HttpServletRequest/servlet/demo1
System.out.println(request.getRequestURI()); // /day09_01_HttpServletRequest/servlet/demo1
System.out.println(request.getContextPath()); // /day09_01_HttpServletRequest
System.out.println(request.getQueryString()); // username=tom

获得客户机信息 getRequestURL方法返回客户端发出请求时的完整URL。

获得客户机请求头

getHead(name)方法

getHeaders(String name)方法

getHeaderNames方法 获得客户机请求参数(客户端提交的数据)

getParameter(name)方法

getParameterValues(String name)方法

getParameterNames方法 getParameterMap方法 //做框架用,非常实用

 

 

request常用方法2

request对象实现请求转发:请求转发指一个web资源收到客户端请求后,通知服务器去调用另外一个web资源进行处理。 request对象提供了一个getRequestDispatcher方法,该方法返回一个RequestDispatcher对象,调用这个对象的forward方法可以实现请求转发。 request对象同时也是一个域对象,开发人员通过request对象在实现转发时,把数据通过request对象带给其它web资源处理。 setAttribute方法 getAttribute方法 removeAttribute方法 getAttributeNames方法

 

 

RequestDispather

表示请求分发器,它有两个方法: forward():把请求转发给目标组件

public void forward(ServletRequest request,ServletResponse response) throws ServletException,java.io.IOException include():包含目标组件的响应结果

public void include(ServletRequest request,ServletResponse response) throws ServletException,java.io.IOException 得到RequestDispatcher对象

1、ServletContext对象的getRequestDispather(String path1) path1必须用绝对路径,即以”/”开头,若用相对路径会抛出异常IllegalArgumentException

2、ServletRequest对象的getRequestDispatcher(String path2) path2可以用绝对路径也可以用相对路径

请求范围

web应用范围内的共享数据作为ServeltContext对象的属性而存在(setAttribute),只要共享ServletContext对象也就共享了其数据。 请求范围内的共享数据作为ServletRequest对象的属性而存在(setAttribute),只要共享ServletRequest对象也就共享了其数据。

重定向

重定向机制的运作流程 1、用户在浏览器端输入特定URL,请求访问服务器端的某个组件 2、服务器端的组件返回一个状态码为302的响应结果。 3、当浏览器端接收到这种响应结果后,再立即自动请求访问另一个web组件 4、浏览器端接收到来自另一个web组件的响应结果。 HttpServeltResponse的sendRedirect(String location)用于重定向

Servlet源组件生成的响应结果不会被发送到客户端。response.sendRedirect(String location)方法一律返回状态码为302的响应结果。 如果源组件在进行重定向之前,已经提交了响应结果,会抛出IllegalStateException。为了避免异常,不应该在源组件中提交响应结果。 在Servlet源组件重定向语句后面的代码也会执行。 源组件和目标组件不共享同一个ServletRequest对象。 对于sendRedirect(String location)方法的参数,如果以“/”开头,表示相对于当前服务器根路径的URL。以“http"//”开头,表示一个完整路径。 目标组件不必是同一服务器上的同一个web应用的组件,它可以是任意一个有效网页。

例子:

public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

response.setContentType("text/html;charset=UTF-8");
response.getWriter().write("注册成功!3秒钟跳到主页");
//设置3秒钟跳转
response.setHeader("refresh", "3;url=/day09_00_HttpServletResponse/servlet/demo6");
}

public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}

}

 

 

Request 的例子

public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//告诉服务器要使用什么编码,注:浏览器使用的是什么编码传过来的就是什么编码
request.setCharacterEncoding("UTF-8");//只能解决post方式的乱码
test1(request);
}

private void test1(HttpServletRequest request) {
//获取所有的表单name的名子
Enumeration names = request.getParameterNames();
while(names.hasMoreElements()){
String name = (String) names.nextElement();//得到每一个name名
String[] values = request.getParameterValues(name);//根据name名,得到value值
for (int i = 0;values!=null && i < values.length; i++) {
System.out.println(name+"\\t"+values[i]);
}
}
}

//test1 方法

private void test1(HttpServletRequest request) throws UnsupportedEncodingException {
//获取表单数据

//根据表单中name属性的名,获取value属性的值方法
String userName = request.getParameter("userName");
String pwd = request.getParameter("pwd");
String sex = request.getParameter("sex");
String[] hobbys = request.getParameterValues("hobby");

String city = request.getParameter("city");

userName = new String(userName.getBytes("iso-8859-1"),"UTF-8");
System.out.println(userName);
System.out.println(pwd);
System.out.println(sex);

for (int i = 0;hobbys!=null && i < hobbys.length; i++) {
System.out.print(hobbys[i]+"\\t");
}
System.out.println();

System.out.println(city);
}

 

public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);


}

 

 

请求重定向例子:

A:

public class ServletDemo7 extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("A:我要借钱!");
System.out.println("B:我不有,但是我可以告诉你谁有");
/*//告诉客户端要重新定向新的资源
response.setStatus(302);
//告诉浏览器要去访问哪个URL
response.setHeader("location", "/day09_00_HttpServletResponse/servlet/demo8");*/
//请求重定向
response.sendRedirect("/day09_00_HttpServletResponse/servlet/demo8");
System.out.println("A: 我去了");
}

public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}

}

 

B:

public class ServletDemo8 extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("我有钱,我借你!");
}

public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}

}

结果:

A:我要借钱!
B:我不有,但是我可以告诉你谁有
A: 我去了
我有钱,我借你!

 

include 例子:

ServletDemo5 

public class ServletDemo5 extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");

String str = "aaaaa";

System.out.println("A:我想办事");
System.out.println("B:我办不了,但我可以找人帮你办");

//将非表单的数据添加到request的域中
request.setAttribute("s", str);
//将请求转发到demo6中
//request.getRequestDispatcher("/servlet/demo6").forward(request, response);
//注:请求转发不能跳转到其它应用
//使用重定向
//response.sendRedirect(request.getContextPath()+"/servlet/demo6");
System.out.println("B:事办完了");

//请求包含
request.getRequestDispatcher("/servlet/demo6").include(request, response);
}

public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}

}

 

ServletDemo6:

public class ServletDemo6 extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
System.out.println("这个事我能办");
//从request对象中获取s的值
String s = (String) request.getAttribute("s");
System.out.println(s);
}

public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}

}

结果为:

A:我想办事
B:我办不了,但我可以找人帮你办
B:事办完了
这个事我能办
aaaaa

 

 

重定向和转发的区别

区别一:

  重定向时浏览器上的网址改变
  转发是浏览器上的网址不变
区别二:
  重定向实际上产生了两次请求
转发只有一次请求
重定向:
  发送请求 -->服务器运行-->响应请求,返回给浏览器一个新的地址与响应码-->浏览器根据响应码,判定该响应为重定向,自动发送一个新的请求给服务器,请求地址为之前返回的地址-->服务器运行-->响应请求给浏览器
转发:
  发送请求 -->服务器运行-->进行请求的重新设置,例如通过request.setAttribute(name,value)-->根据转发的地址,获取该地址的网页-->响应请求给浏览器
区别三:
  重定向时的网址可以是任何网址
  转发的网址必须是本站点的网址
详解:
  重定向:以前的request中存放的变量全部失效,并进入一个新的request作用域。
转发:以前的request中存放的变量不会失效,就像把两个页面拼到了一起。
正文开始:
  先是看上去不同,他们的调用分别如下:
request.getRequestDispatcher("apage.jsp").forward(request, response);//转发到apage.jsp
response.sendRedirect("apage.jsp");//重定向到apage.jsp

 

以上是关于如何从response里面取出向客户端输出的html流的主要内容,如果未能解决你的问题,请参考以下文章

从SQLServer里面取出数据,去掉头尾的空格

c# winform从数据库里面取出数据放到datatable里

Response对象

response对象

在servlet 中如何向客户端输出页面内容?

response.getwriter()页面的信息如何保存到本地文件