当前的项目中存在下面一种场景:web应用的某个功能中,jsp中加载的某个插件需要将数据提交给web服务端。插件中通过ObjectOutputStream向web端传输数据,但springmvc的拦截器会提前读取该流对象,那么配置指定的Action就无法再读取到该Stream的内容,会导致如下异常:
java.io.EOFException
at java.io.ObjectInputStream$BlockDataInputStream.peekByte(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
由于整个项目的controler层用的springmvc框架,所以目前的解决办法是编写一个独立的servlet来单独针对该数据的接收。
因为采用注解的方式将配置service并交给spring管理,而需要编写的servlet需要注入这些service,所以这边采用代理的方式实现:
第一步:编写代理类HttpServletProxy
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jxl.common.Logger;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
/**
* @description
* @author minux
* @date 2013-9-2 下午2:16:22
*/
public class HttpServletProxy extends HttpServlet {
private static final long serialVersionUID = -2934353313384038254L;
public static Logger logger = Logger.getLogger(HttpServletProxy.class);
private String targetServlet;
private HttpServlet proxy;
public void init() throws ServletException {
this.targetServlet = getInitParameter("targetServlet");
getServletBean();
proxy.init(getServletConfig());
logger.info(targetServlet
+ " was inited by HttpServletProxy successfully......");
}
private void getServletBean() {
WebApplicationContext wac = WebApplicationContextUtils
.getRequiredWebApplicationContext(getServletContext());
this.proxy = (HttpServlet) wac.getBean(targetServlet);
}
public void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException, RuntimeException {
proxy.service(request, response);
}
}
第二步:在web.xml中配置改代理servlet
<servlet>
<servlet-name>ComplexWebLoadTestServletProxy</servlet-name>
<servlet-class>cn.hxcomm.web.controller.HttpServletProxy</servlet-class>
<init-param>
<param-name>targetServlet</param-name>
<param-value>complexWebLoadTestServlet</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>ComplexWebLoadTestServletProxy</servlet-name>
<url-pattern>/complexWebLoadTestServlet.do</url-pattern>
</servlet-mapping>
第三步:编写真正实现功能的ComplexWebLoadTestServlet并注解注入
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.sql.Timestamp;
import java.util.Calendar;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jxl.common.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import cn.hxcomm.common.domain.ComplexWebLoadTestDetail;
import cn.hxcomm.web.service.ComplexWebLoadTestService;
/**
* @description
* @author minux
* @date 2013-8-30 下午3:44:02
*/
@Service("complexWebLoadTestServlet")
public class ComplexWebLoadTestServlet extends HttpServlet {
private static final long serialVersionUID = -371252886055302137L;
public static Logger logger = Logger
.getLogger(ComplexWebLoadTestServlet.class);
@Autowired
private ComplexWebLoadTestService complexWebLoadTestService;
public ComplexWebLoadTestServlet() {
super();
}
public void init() throws ServletException {
super.init();
}
public void service(HttpServletRequest requeset,
HttpServletResponse response) throws ServletException, IOException,
RuntimeException {
this.doWork(requeset, response);
}
private void doWork(HttpServletRequest request, HttpServletResponse response) {
}
}
这样基本就可以实现绕开拦截器提前读取stream的情况。
当然servlet注入service的也有其他的实现方式,比如可以直接不需要代理servlet,直接编写servlet读取需要的配置文件,然后取出需要的service的bean对象。
但是个人感觉代理的方式更方便扩展和管理。