如下是代码
第一部分是web.xml的配置
<?xml version="1.0" encoding="UTF-8"?>
s2sh
index.html
index.htm
index.jsp
default.html
default.htm
default.jsp
spring
org.springframework.web.servlet.DispatcherServlet
0
spring
.do
encodingFilter
org.springframework.web.filter.CharacterEncodingFilter
encoding
UTF-8
forceEncoding
true
encodingFilter
/
org.springframework.web.context.ContextLoaderListener
contextConfigLocation
classpath:applicationContext.xml
<!-- 生成验证码配置 servlet-->
Kaptcha
com.google.code.kaptcha.servlet.KaptchaServlet
Kaptcha
/kaptcha.jpg
接下来是页面的代码,我用的是html,这块声明一下这个配置用jsp是没有问题的,只是挪到了html页面中不知怎地就报错了,不影响页面生成验证码图片,但是后台是取不到session中的字符串的,因为session并没有创建,报的错也是session不能在response相应后创建。
<!-- 验证码开始 -->
<div>
<img src="../kaptcha.jpg" id="kaptchaImage" width="300px" height="50px" style="padding-top: 25px; "/>
<input type="text" class="form-control col-xs-4" id="passWord" placeholder="请输入验证码" >
</div>
<!-- 验证码结束 -->
接下来是页面点击图片生成验证码的js代码
$(function(){ $('#kaptchaImage').click(function () { $(this).attr('src', '../kaptcha.jpg?' + Math.floor(Math.random()*100) ); }); });然后以下是报错信息
三月 24, 2017 9:28:41 上午 org.apache.catalina.core.StandardWrapperValve invoke
严重: Servlet.service() for servlet [Kaptcha] in context with path [/webapp] threw exception
java.lang.IllegalStateException: Cannot create a session after the response has been committed
at org.apache.catalina.connector.Request.doGetSession(Request.java:3016)
at org.apache.catalina.connector.Request.getSession(Request.java:2385)
at org.apache.catalina.connector.RequestFacade.getSession(RequestFacade.java:897)
at org.apache.catalina.connector.RequestFacade.getSession(RequestFacade.java:909)
at com.google.code.kaptcha.servlet.KaptchaServlet.doGet(KaptchaServlet.java:91)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:624)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:956)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:423)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1079)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:625)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
*
报错内容有路径错误,有服务器请求错误JSP的页面直接在HTML中有很多都是会出现各种错误的,因为两者有太多不同的问题。
最终解决办法就是不在html中使用该插件,html中使用自定义的插件,因为我也没查到什么插件在这种情况下使用比较好。
遇到相同的问题,页面是 HTML 。
查看源码:KaptchaServlet
/** */
@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
// Set standard HTTP/1.1 no-cache headers.
resp.setHeader("Cache-Control", "no-store, no-cache");
// return a jpeg
resp.setContentType("image/jpeg");
// create the text for the image
String capText = this.kaptchaProducer.createText();
// create the image with the text
BufferedImage bi = this.kaptchaProducer.createImage(capText);
ServletOutputStream out = resp.getOutputStream();
// write the data out
ImageIO.write(bi, "jpg", out);
// fixes issue #69: set the attributes after we write the image in case the image writing fails.
// store the text in the session
req.getSession().setAttribute(this.sessionKeyValue, capText);
// store the date in the session so that it can be compared
// against to make sure someone hasn't taken too long to enter
// their kaptcha
req.getSession().setAttribute(this.sessionKeyDateValue, new Date());
}
ImageIO.write(bi, 'jpg', out) ;
执行之后,response 已经关闭了。
之后的
// fixes issue #69: set the attributes after we write the image in case the image writing fails.
// store the text in the session
req.getSession().setAttribute(this.sessionKeyValue, capText);
// store the date in the session so that it can be compared
// against to make sure someone hasn't taken too long to enter
// their kaptcha
req.getSession().setAttribute(this.sessionKeyDateValue, new Date());
有通过 response 获取 Session,此时就会报错。
解决办法很简单:
创建一个自己的 Servlet
/**
*
* @author TroyLiu
*
*/
@SuppressWarnings("serial")
public class KaptchaHtmlServlet extends HttpServlet implements Servlet{
private Properties props = new Properties();
private Producer kaptchaProducer = null;
private String sessionKeyValue = null;
private String sessionKeyDateValue = null;
/*
* (non-Javadoc)
*
* @see javax.servlet.Servlet#init(javax.servlet.ServletConfig)
*/
@Override
public void init(ServletConfig conf) throws ServletException
{
super.init(conf);
// Switch off disk based caching.
ImageIO.setUseCache(false);
Enumeration<?> initParams = conf.getInitParameterNames();
while (initParams.hasMoreElements())
{
String key = (String) initParams.nextElement();
String value = conf.getInitParameter(key);
this.props.put(key, value);
}
Config config = new Config(this.props);
this.kaptchaProducer = config.getProducerImpl();
this.sessionKeyValue = config.getSessionKey();
this.sessionKeyDateValue = config.getSessionDate();
}
/** */
@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
// Set standard HTTP/1.1 no-cache headers.
resp.setHeader("Cache-Control", "no-store, no-cache");
// return a jpeg
resp.setContentType("image/jpeg");
// create the text for the image
String capText = this.kaptchaProducer.createText();
// create the image with the text
BufferedImage bi = this.kaptchaProducer.createImage(capText);
// store the text in the session
req.getSession().setAttribute(this.sessionKeyValue, capText);
// store the date in the session so that it can be compared
// against to make sure someone hasn't taken too long to enter
// their kaptcha
req.getSession().setAttribute(this.sessionKeyDateValue, new Date());
ServletOutputStream out = resp.getOutputStream();
// write the data out
ImageIO.write(bi, "jpg", out);
// fixes issue #69: set the attributes after we write the image in case the image writing fails.
}
直接先执行 req.getSession() .... 最后执行 ImageIO.write() ;
在 Web.xml 配置拦截器时指定自己的拦截器
<servlet>
<servlet-name>Kaptcha</servlet-name>
<servlet-class>com.troyliu.interceptors.KaptchaHtmlServlet</servlet-class>
<init-param>
<param-name>kaptcha.border</param-name> <!-- 是否有边框 -->
<param-value>no</param-value>
</init-param>
<init-param>
<param-name>kaptcha.textproducer.char.space</param-name> <!--字符之间的间距 -->
<param-value>8</param-value>
</init-param>
<init-param>
<param-name>kaptcha.textproducer.char.length</param-name> <!-- 字符的个数 -->
<param-value>4</param-value>
</init-param>
</servlet>
问题解决。
JSP 可以使用的原因,是因为 JSP 本质上也属于 servlet 的一种,当 ImageIO.write() 执行完后,response 并没有关闭。
而 HTML 不同。