总结
出现Could not initialize class sun.awt.X11GraphicsEnvironment异常的话,开启headless就好了,开启的方法有好多,我这里总结一下:
可以在catalina.sh脚本中
1.加入CATALINA_OPTS=-Djava.awt.headless=true
2.或者在每处类似:
exec "\$_RUNJDB" "\$LOGGING_CONFIG" \$LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS \
-Djava.endorsed.dirs="\$JAVA_ENDORSED_DIRS" -classpath "\$CLASSPATH" \
-sourcepath "\$CATALINA_HOME"/../../java \
-Djava.security.manager \
-Djava.security.policy=="\$CATALINA_BASE"/conf/catalina.policy \
-Dcatalina.base="\$CATALINA_BASE" \
-Dcatalina.home="\$CATALINA_HOME" \
-Djava.io.tmpdir="\$CATALINA_TMPDIR" \
的后边加入-Djava.awt.headless=true \
(我的tomcat7上共有8处)
3.或者在JAVA_OPTS
后边加入-Djava.awt.headless=true
,我的脚本加入后为:
JAVA_OPTS="$JAVA_OPTS $JSSE_OPTS -Djava.awt.headless=true"
4.或者直接在当前用户的.bash_profile
文件后边加上export JAVA_OPTS=-Djava.awt.headless=true
,然后source .bash_profile使配置生效。
上述方法都是等价的,如果加入后出现异常:
ERROR advice.ControllerAdvice:44 - java.lang.IllegalStateException: Cannot create a session after the response has been committed java.lang.IllegalStateException: Cannot create a session after the response has been committed
at org.apache.catalina.connector.Request.doGetSession(Request.java:3069)
at org.apache.catalina.connector.Request.getSession(Request.java:2441)
at org.apache.catalina.connector.RequestFacade.getSession(RequestFacade.java:897)
at org.apache.catalina.connector.RequestFacade.getSession(RequestFacade.java:909)
at javax.servlet.http.HttpServletRequestWrapper.getSession(HttpServletRequestWrapper.java:238)
at cn.edu.hdu.config.DrawCaptcha.getCode(DrawCaptcha.java:73)
at cn.edu.hdu.controller.PublicController.getCaptcha(PublicController.java:127)
则可以试试在你的代码中 不要使用JFrame
踩坑记录
最近甲方突然提出了一个新需求,web端登录的时候,在用户输入密码错误过多的情况下,需要显示验证码,并输入验证码进行登录,感觉不是很难,从网上随便找了个Java生成验证码的类,并自己加了一些显示和隐藏的逻辑后,功能完成了,在Windows上也使用正常,但是部署到Linux上的时候出现了问题
问题
一开始部署到Linux服务器上之后,验证码显示不出来,于是测试了一下生成验证码的接口,果然报错了:
报错信息如下:
HTTP Status 500 - Handler processing failed; nested exception is java.awt.AWTError: Can't connect to X11 window server using 'localhost:11.0' as the value of the DISPLAY variable.
type Exception report
message Handler processing failed; nested exception is java.awt.AWTError: Can't connect to X11 window server using 'localhost:11.0' as the value of the DISPLAY variable.
description The server encountered an internal error that prevented it from fulfilling this request.
exception
org.springframework.web.util.NestedServletException: Handler processing failed; nested exception is java.awt.AWTError: Can't connect to X11 window server using 'localhost:11.0' as the value of the DISPLAY variable.
org.springframework.web.servlet.DispatcherServlet.triggerAfterCompletionWithError(DispatcherServlet.java:1260)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:939)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:851)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:953)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:844)
javax.servlet.http.HttpServlet.service(HttpServlet.java:624)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:829)
javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:206)
net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:179)
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:106)
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:232)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:106)
net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:163)
网上搜了一下,大部分都是说让开启headless模式,于是按照网上的说法,加上了-Djava.awt.headless=true
这里有的说让在CATALINA_OPTS
后边加-Djava.awt.headless=true
,有的让在多处-java.io.tmpdir="$CATALINA_TMPDIR" \
后边加(大概有7 8处),有的让在JAVA_OPTS
后边加,这里我试了一下,结果是一样的,都是不行。
我开启了headless模式后,请求验证码的接口确实是返回200正常了,但是接口的图片没有返回,并且没有任何返回值,查看tomcat日志后,发现报错:
java.awt.HeadlessException at java.awt.GraphicsEnvironment.checkHeadless(GraphicsEnvironment.java:204)
于是继续网上搜解决方案,发现网上针对这个错误的大部分解决方案都是关闭headless模式,也就是设置-Djava.awt.headless=false
,芭比Q了,死锁了。
解决
在一个外国博主那里找到了答案,他的回答是:
I have resolved this problem by not using JFrame. Instead of JFrame I have used the following: FilteredImageSource myFilteredImageSource = new FilteredImageSource(image.getSource(), new CropImageFilter(x, y, crpHeight, crpWidth));
仔细查看我从网上找到的生成验证码的类,还真是继承了JFrame,于是我把继承JFrame的这部分去掉,发现他生成验证码的代码也没有报错,本地调试了一下发现没有问题,就部署到服务器上去了,本来都已经绝望了,没想到居然成功了,看来以后代码不能乱抄啊!