1.5 jfinal-undertow 常见问题

1、IDEA 下支持热加载

jfinal undertow 是通过监听 target/classes 下面的 .class 文件被修改事件去触发的热加载。

eclipse 拥有自动编译功能,会在 java 源代码文件保存时自动编译并更新 target/classes 下的相关 .class 文件,所以 eclipse 下面默认就支持热加载。注意 eclipse 的自动编译菜单一定要勾选上(默认是勾选的),如下图:

eclipse-auto-compile.png

但 IDEA 默认并不支持自动编译,那么 target/classes 下面的 .class 文件无法及时更新,所以 IDEA 默认不支持热加载。因此需要想办法触发 IDEA 的编译动作,建议去网上找一些开启 IDEA 自动编译的配置方法。 下面的链接给出了一种通过快捷键触发编译的方法供参考:

https://my.oschina.net/fdblog/blog/172229

此外,jfinal 官网很久以前的文档也给出过一种方法:

https://www.jfinal.com/share/1357

最后:别忘了 undertow.devMode 要配置成 true 才支持热加载,具体配置方法见前面两小节的文档。

2、IDEA 下模板文件路径不正确

在 IDEA 下发时,如果是通过打开项目的目录,或者通过打开项目的 pom.xml 文件导入的 maven 项目将会找不到模板文件路径。正确的导入方法如下:

idea-1.png

如下图所示,一定要选择 import project,而不能选择 Open,下一步是选择项目根目录:

idea-2.png

再一步是选择 maven:

idea-3.png

然后再一路点击 next 直到完成即可。

要点:如果第一步选择 Open 将是错误的做法。如果项目已经使用上述方式导入过一次,IDEA 生成了各种配置文件,那么选择 Open 打开项目的方式没有问题。

3、 maven 多模块项目启动报错

如果 maven 的多 module 结构的项目在启动时出现找不到模板的异常,添加如下配置:

  1. undertow.resourcePath=webapp, {修改为自己的项目名}/src/main/webapp, src/main/webapp

这里有相关问题的分享:http://www.jfinal.com/share/1285

4、类型转换异常、子类对象无法赋值到基类变量

如果两个类路径与类名完全一样的两个类出现类型转换异常(java.lang.ClassCastException),或者子类对象无法赋值给基类变量,可以通过配置 hotSwapClassPrefix 来解决。

再补充几个也属于这个问题的异常:java.lang.VerifyError: Bad type on operand stack 以及 java.lang.IncompatibleClassChangeError

假定出现转换异常的类为: "com.abc.UserService",解决办法如下:

  1. UndertowServer.create(MyApp.class)
  2. .addHotSwapClassPrefix("com.abc.")
  3. .start();

如上所示,将出现类型转换异常的类的包前缀通过 addHotSwapClassPrefix(…) 添加进去即可。原因是 jfinal undertow 默认只对 target/classes 以及 jfinal 自身进行热加载,所以当你的类文件在 jar 包并且需要被热加载的时候就需要通过上面的办法添加为被热加载。

一般情况下你项目中 target/classes 下的类文件正好才是需要被热加载的类,所以不会有问题。这个配置仅用于开发环境,部署环境没有热加载机制,所以完全没有影响。

此外,还可以通过配置文件来设置:

  1. undertow.hotSwapClassPrefix=com.abc.

如果要添加多个,可以通过逗号分隔。

最新补充:在少数情况下即便是通过配置 hotSwapClassPrefix 将出现类型转换异常的类处理掉了,但仍然不起作用,这是因为一些第三方软件里头缓存了出问题的 class 或者对象,例如:xstream 这个将 xml 转 object 的工具,需要再追加如下配置:

  1. addHotSwapClassPrefix("com.thoughtworks.")

如上所示,将这类有缓存动作的第三方也配置成 hot swap class 就没问题了,重点要找到这些第三方。

  1. 

用户反馈不断补充要配置的项目还有 j2cache 以及作者 dreamlu 开源的一些项目,需要配置:

  1. addHotSwapClassPrefix("net.oschina.j2cache.")
  2.  
  3. addHotSwapClassPrefix("net.dreamlu.")

这个设计完全是出于热加载的性能优化,本可以默认将这类 class 加载为 hotSwapClass,但性能不如当前的设计好。

5、shiro 热加载问题

jfinal undertow 暂不支持 shiro 热加载,配置 undertow.devMode=false 可以使用,但不支持热加载

6、部署在外网服务器上无法访问问题

出于安全性考虑 jfinal undertow 早期版本的 undertow.host 默认配置为了 localhost,部分外网服务器上无法访问时,使用如下配置:

  1. undertow.host=0.0.0.0

如果添加了上述配置还是无法访问,检查一下阿里云是否开启了相关的端口号(假定你用的阿里云)。

为了便利性,新版本 jfinal undertow 的 undertow.host 默认配置改成了 0.0.0.0,如果不希望在外网直接访问,需要将其配置为 localhost。

注意,这里所谓的外网无法访问,也包括局域网内访问的机器与部署机器并非同一台机器的情况。

7、脚本无法使用问题

jfinal 官方提供的 jfinal.sh、jfinal.bat 脚本文件里面有较为详细的使用说明,只要按照说明去使用一般不会有问题。

这里要提醒一个比较奇葩的问题,假定你自己创建上述脚本文件,虽然是从 jfinal 官方 copy 过去的内容,然后死活就是无法使用,原因是脚本文件的换行符出了问题。 linux、mac 系统之下的脚本换行字符必须是 '\n',而 windows 下必须是 "\r\n"。

查看脚本文件的换行字符的方法是:先用 eclipse 打开一个 java 源代码文件,然后在工具栏点击一下 "Show Whitespace Characters" 这个图标,然后再用 eclipse 打开脚本文件,在每行末尾处会显示出换行字符。显示一个字符的就是 '\n',否则就是 '\r\n'。

注意,此问题与 jfinal 完全无关,是操作系统自己的限制。

重要:最近俱乐部同学发现一类新的脚本无法启动的原因,那就是 pom.xml 中的 jetty 依赖没有删除,从而引发异常:java.lang.NoClassDefFoundError: com/jfinal/config/JFinalConfig,删掉 jetty 依赖即可解决。

8、JSP 支持问题

为提升应用的安全性,jfinal 较新的版本默认不能对 .jsp 文件直接进行访问,也就是在浏览器地址栏中无法输入 .jsp 文件名去访问 jsp 文件,但是可以通过 renderJsp(xxx.jsp) 来访问 jsp 文件。如果确实需要直接访问 jsp 文件,需要添加如下配置:

  1. public void configConstant(Constants me) {
  2. me.setDenyAccessJsp(false);
  3. }

jfinal undertow 支持 jsp 功能需要类似下面的配置:

  1. UndertowServer.create(DemoConfig.class)
  2. .configWeb(wb -> {
  3. wb.getDeploymentInfo().addServlet(JspServletBuilder.createServlet("Default Jsp Servlet", "*.jsp"));
  4.  
  5. HashMaptagLibraryInfo = new HashMap<>();
  6. JspServletBuilder.setupDeployment(wb.getDeploymentInfo(), new HashMap(),
  7. tagLibraryInfo, new HackInstanceManager());
  8. })
  9. .start();

更多信息可以参考如下资源:

https://jfinal.com/share/1890

https://jfinal.com/share/1899

https://github.com/shanmine/undertow-jsp-demo.git