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,在页面确定写入<meta http-equiv=”Content-Type” content=”text/html; charset=gb2312”>
有人说可能是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. <br>
	 *
	 * 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. <br>
	 *
	 * 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<Poi> 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);
																}
															}
														});


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值