getWriter() 和Response.getOutputStream冲突

java.lang.IllegalStateException异常:简单分析和简单解决方案

今天写java验证码程序,完成后使用一切正常,但是总抛出java.lang.IllegalStateException异常,虽然并不影响正常使用,但看了总让人觉得很不舒服,检查代码并没有错,最后上网查了不少资料,终于发现原因之所在。
我们在做文件上传或者下载,或者过滤等操作时,可能要用到页面的输出流.
例如在JSP使用:
    response.reset();
    response.setContentType(”application/vnd.ms-excel”);
    OutputStream os = response.getOutputStream();  
抛出异常:
ERROR [Engine] StandardWrapperValve[jsp]: Servlet.service() for servlet jsp threw exception
java.lang.IllegalStateException: getOutputStream() has already been called for this response
从网上找了下资料,综合一下原因分析:
这是web容器生成的servlet代码中有out.write(””),这个和JSP中调用的response.getOutputStream()产生冲突.
即Servlet规范说明,不能既调用 response.getOutputStream(),又调用response.getWriter(),无论先调用哪一个,在调用第二个时候应会抛出 IllegalStateException,因为在jsp中,out变量是通过response.getWriter得到的,在程序中既用了response.getOutputStream,又用了out变量,故出现以上错误。
解决方案:
1.在程序中添加:
out.clear();
out = pageContext.pushBody();
就可以了;
2,不要在%][%之间写内容包括空格和换行符
3,在页面写入图片的时候,需要flush()
 OutputStream output=response.getOutputStream();
 output.flush();
4,在页面确定写入
有人说可能是tomcat的bug,我给她回了封信:
:我看了看这里,http://www.javathinker.org /main.jsp?bc=showessay.jsp+filename=tomcat/tomcat_question_chapter13.htm 这里是你回复别人的一个帖子,里面的观点基本上和我理解的一样,但是你最后写到可能是tomcat的bug,我想解释一下:在jsp中,out是内嵌对象,即已经设置了PrintWriter out=response.getWriter();这样在再次getOutputStream()得到输出流时(比如转发过滤、下载文件时)就出错了 (写排斥锁),我不止一次看到有人的文件下载页面在后台不断打印这个异常。而在servlet中没有默认out内置对象,所以没有出错.你可以在 servlet中添加out对象试试,应该会报异常的.所以正确的处理方式就应该是:在servlet中做控制层,在业务处理以前不要获得out对象,当业务操作失败或出现异常时再生成out对象回显操作结果。


实际案例:
一次在做项目,做一个地图搜索,返回json数据流,由于没有使用flush,造成界面无法显示。
package com.segsec.gisap.servlet;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Enumeration;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ServletUtil {
	@SuppressWarnings("unchecked")
	public static void forward(String url, HttpServletRequest request, HttpServletResponse response) throws IOException{
		forward(url, request, response, "utf-8");
	}
	
	@SuppressWarnings("unchecked")
	public static void forward(String url, HttpServletRequest request, HttpServletResponse response, String encode) throws IOException{
		StringBuilder surl = new StringBuilder(url);
		Enumeration er = request.getParameterNames();
		if(er.hasMoreElements()){
			String name = (String) er.nextElement();
			surl.append("?").append(name).append("=").append(URLEncoder.encode(request.getParameter(name), encode));
		}
		while(er.hasMoreElements()){
			String name = (String) er.nextElement();
			surl.append("&").append(name).append("=").append(URLEncoder.encode(request.getParameter(name), encode));
		}
//		System.out.println("surl:" + surl);
		InputStream is = null;
		ServletOutputStream os = null;
		try {
			os = response.getOutputStream();
			URL u = new URL(surl.toString());
			is = u.openStream();
			byte[] buff = new byte[1024];
			int len;
			while((len = is.read(buff)) != -1){
				os.write(buff, 0, len);
			}
			os.flush();
		} catch (MalformedURLException e) {
			e.printStackTrace();
			throw new IOException(e);
		}finally{
			try{
				if(is != null){
					is.close();
				}
			}catch (IOException e) {
				e.printStackTrace();
			}
			
			try{
				if(os != null){
					os.close();
				}
			}catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

package com.segsec.gisap.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import mapbar.MapbarInterface;
import mapbar.bean.Poi;

import com.general.FormatUtil;
import com.googlecode.jsonplugin.JSONUtil;
import com.segsec.gisap.dao.MenuDAO;
import com.segsec.gisap.util.Config;

/**
 * 通过省份名称和查询条件查找地名
 * @author Administrator
 * 电召的按地址搜索和 地图搜索;
 *
 */
public class SearchAddress extends HttpServlet {

	private static final long serialVersionUID = 1L;

	private boolean searchAddress_use_agent = false;
	private String searchAddress_agent_url = "http://113.106.90.236/searchAddress";
	
	@Override
	public void init() throws ServletException {
		String configPath = Config.getConfigPath();
		String systemConfigFile = configPath + "config/system.properties";
		try {
			Properties properties = com.segsec.gisap.util.Util.loadProperties(systemConfigFile);
			searchAddress_use_agent = Boolean.valueOf(properties.getProperty("searchAddress_use_agent"));
			searchAddress_agent_url = properties.getProperty("searchAddress_agent_url");
			System.out.println("searchAddress_use_agent:" + searchAddress_use_agent);
			System.out.println("searchAddress_agent_url:" + searchAddress_agent_url);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	/**
	 * The doGet method of the servlet. 
* * This method is called when a form has its tag value method equals to get. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } /** * The doPost method of the servlet.
* * This method is called when a form has its tag value method equals to post. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */ @SuppressWarnings("unchecked") public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { if(searchAddress_use_agent){ ServletUtil.forward(searchAddress_agent_url, request, response); return; } /* * 从客户端取得 城市名称,对应省份子表的名称,查询条件 */ request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); response.setContentType("application/x-json;charset=UTF-8"); PrintWriter pw=response.getWriter(); String tablename = request.getParameter("tablename"); String restrict= FormatUtil.isoconversionutf8(request.getParameter("restrict")); String iscity=request.getParameter("iscity"); String cityname=request.getParameter("cityname"); int start=Integer.parseInt(request.getParameter("start")); int end=Integer.parseInt(request.getParameter("limit")); String str = request.getParameter("isMapbar"); int isMapbar = 0; if(str != null) { try { isMapbar = Integer.parseInt(str); }catch(Exception e) {} } //如果是Mapbar if(isMapbar == 1) { int limit = end; List ps = MapbarInterface.getPoiByKeyword(cityname, restrict, 1, limit); int size = ps.size(); Map map = new HashMap(); map.put("pagenumbercount", size); Map obj = null; String tmp = null; String[] lonlat = null; List list = new ArrayList(); for(Poi p : ps) { obj = new HashMap(); obj.put("name", p.getName()); tmp = p.getStrlatlon(); if(tmp != null) { lonlat = tmp.split(","); } if(lonlat != null && lonlat.length > 1) { obj.put("lon", lonlat[0]); obj.put("lat", lonlat[1]); } obj.put("addname", p.getAddress()); obj.put("telephone", p.getPhone()); list.add(obj); } map.put("list", list); try{ String resp = JSONUtil.serialize(map); pw.println(resp); pw.flush(); }catch(Exception ex){ System.out.println("Query SearchAddress to Error"+ex); }finally{ pw.close(); } }else { MenuDAO dao = new MenuDAO(); HashMap hm; if(iscity!=null&&cityname!=null){ if(cityname.equals("全国")){ hm = dao.queryPOINTALL(tablename, restrict,start,start+end); }else if(iscity.equals("true")){ hm = dao.queryPOINTCity(tablename, cityname,restrict,start,start+end); }else{ hm = dao.queryPOINTPro(tablename, restrict,start,start+end); } }else{ hm = dao.queryPOINT(tablename, restrict,start,start+end); } try{ /*AJAX 对象序列化一个Object 对象输出到客户端*/ String obj=JSONUtil.serialize(hm); pw.println(obj); pw.flush(); }catch(Exception ex){ System.out.println("Query SearchAddress to Error"+ex); }finally{ pw.close(); } } } }

win.findAddressStore
														.load({
															method : 'post',
															params : {
																start : 0,
																limit : 20,
																'tablename' : tablename,
																'restrict' : restrict,
																cityname : cityname,
																isMapbar : 1
															// isMapbar || 0
															},
															callback : function(r,opt,success) {
																btn.enable();
																if (!success) {
																	alert("查找失败!:"
																			+ tablename
																			+ "\n restrict:"
																			+ restrict);
																}
															}
														});


你可能感兴趣的:(Eclipse,JBuilder)