【分享】Jfinal+Undertow支持jsp的方法

undertow其实是支持jsp的,从我第一次接触undertow时就知道了。但是波总的jfinal-undertow旨在抛弃jsp,所以之前很多码友在社区询问的时候我还是紧跟波总路线方针,建议使用html。

但是今天我自己遇到了一个问题,不能不用jsp了,至少我还没有想到如何使用html来实现我的需求。事情还是得从这篇帖子说起:【分享】Jfinal+Undertow自定义对静态资源的404错误处理

通过上面那篇文章我已经可以自定义静态资源的404页面,but……问题出现了。由于这个跳转是由undertow直接处理的,并不是jfinal来处理的,所以跳转到目标html页面后,该页面无法被enjoy渲染,那么相关指令就无法使用,我的需求(保存此次404访问记录)就没法实现。所以万般无奈之下,我还是想到了jsp,因为在jsp页面上我能接收到此次会话的request对象,相关信息就能获取到。so,我开始兼容改造。

第一步:pom中添加依赖

<!-- jsp支持 -->
<dependency>
   <groupId>io.undertow.jastow</groupId>
   <artifactId>jastow</artifactId>
   <version>2.1.0.Final</version>
   <exclusions>
      <!-- 以下两个包跟jfinal-undertow依赖冲突 -->
      <exclusion>
         <groupId>io.undertow</groupId>
         <artifactId>undertow-servlet</artifactId>
      </exclusion>
      <exclusion>
         <groupId>org.jboss.logging</groupId>
         <artifactId>jboss-logging</artifactId>
      </exclusion>
   </exclusions>
</dependency>
<dependency>
   <groupId>org.jboss.spec.javax.servlet.jsp</groupId>
   <artifactId>jboss-jsp-api_2.3_spec</artifactId>
   <version>2.0.0.Final</version>
</dependency>

第二步:再次改造com.jfinal.server.undertow.WebBuilder,添加一个方法。(提示:大家只需要把WebBuilder这个类的源代码放到你的项目里,保证包路径跟原项目一致,然后进行修改即可,Jfinal-undertow使用当前maven库最新的版本,不需要自己重新打包。后续波总往maven库发布了新版本,这个类就能删掉了

public WebBuilder setJspDependency() {
   deploymentInfo.addServlet(JspServletBuilder.createServlet("Default Jsp Servlet", "*.jsp"));
   HashMap<String, TagLibraryInfo> tagLibraryInfo = new HashMap<String, TagLibraryInfo>();
   JspServletBuilder.setupDeployment(deploymentInfo, new HashMap<String, JspPropertyGroup>(), tagLibraryInfo,
         new HackInstanceManager());
   return this;
}

第三步:开启jsp支持

UndertowServer.create(Config.class).configWeb(builder -> {
         // jsp支持
         builder.setJspDependency();
        
         // 错误页面(undertow捕获处理,不走enjoy渲染)
         builder.addErrorPage(404, "/error/404.jsp");

}).start();

第四步:由Jfinal控制的404自定义跳转保持不变

me.setError404View("/error/404.html");

这样就ok了,完美实现了我的需求。如果有更好的思路,还请各路大神不吝赐教。

有想体验undertow,但是还想用jsp的小伙伴,现在可以耍起来了。不过新项目的话,还是建议大家用html,Enjoy模板引擎真的很好用。

评论区

JFinal

2019-11-11 10:26

这个分享对于一定要使用 JSP 的同学来说简直是福音,虽然我强烈建议使用 enjoy,但有时候开发者往往做不了主

点赞 + 收藏是必须的,感谢

JFinal

2019-11-11 10:30

提两个建议:
1:jfinal undertow 最新代码已经在 WebBuilder 中开放了一个 getDeploymentInfo() 方法,所以可以不需要改造 WebBuilder 就能扩展各种方法了

2:你碰到的这个需求其实仍然可以使用 enjoy 来做,在你扩展 undertow 的 ErrorPage 类中,大致可以这么使用:
HttpServletRequest request = threadLocal.get();
Engine.use().getTemplate("404.html").render(data, request.getOutputStream());

这里的关键在于 request 对象要通过一个 ThreadLocal 传送过来

希望你通过我的第二条建议尝试用 enjoy 来解决一下,记得回来分享,这种用法从来没人分享过

happyboy

2019-11-11 10:52

@JFinal 对于第一个建议getDeploymentInfo这个方法我有看到,也尝试进行使用,但是在builder -> {}中耍不起来,修改ErrorPage 类,当时也有考虑,没深入研究,我抽空试一下。对于第二个建议,对于action触发的404中的request获取,我就是这么处理的。

happyboy

2019-11-12 10:32

@JFinal 根据第二个建议做了尝试,离成功还有一步之遥,目前遇到一个奇怪问题,就是这种情况下,调用model.save()的时候报空指针,经过跟踪发现DbKit中modelToConfig是{},但是Action触发404的时候就有值。

JFinal

2019-11-12 11:35

@happyboy 在 Handler 中通过 ThreadLocal 将 request 传过来就可以了

俱乐部有位同学通过你给的方案集成了 JSP, 价值已体现

happyboy

2019-11-12 21:06

@JFinal 第一天的时候我已经找到了undertow的最后一个跳转动作,在HttpServletResponseImpl类的doErrorDispatch方法中。这个方法本身就能获取request对象,所以其实不用传递(从handler中传递过过来我也试过了,根本获取不到)。但诡异的就是,在这个地方,engine需要重新addSharedMethod,否则就报找不到。再就是model.save会报空指针。所以现在有点抓狂。撇开这个思路,今天晚上的时候我突然有了另外一个点子,就是在Handler中获取请求的uri,有个这个uri,我能干很多事啊,是不是静态资源我能判断,静态资源是否有效我也能判断,无效的时候我就记录下来。这不也可以吗,也不需要开启jsp支持了。囧

JFinal

2019-11-12 21:23

@happyboy 你说得完全正确, Handler 本来就可以实现,因为 Handler 可以接管所有请示,包括静态资源的请求

其实只要判断是否为静态资源,并且资源是不是存在就可以了

小太阳cm

2019-11-13 09:40

完美解决了我得需求,特意回来感谢下大佬,但是自己改得 Jar 包 不能上传分享比较遗憾,波总现在代码更新了,版本2.0,Maven 仓库 暂时没有

happyboy

2019-11-13 09:57

@小太阳cm 其实不需要处理整个jar包,你只把WebBuilder这个类单独放出来就行,包路径保持不变,你也不需要再重新打包,因为这种情况下会以你外面这个类为准。后续波总正式发布新版本后,这个类就可以删掉了。

小太阳cm

2019-11-13 10:12

@happyboy 嗯呢,没毛病,我去实践下

小太阳cm

2019-11-13 16:04

@happyboy 实践了,可以得!

happyboy

2019-11-13 18:13

@小太阳cm so,直接使用maven库里已有的最新版Jfinal-undertow即可,也不用编译打包波总的最新代码。光把WebBuilder这个类的源码放到你项目里进行小改动就能用了。

JFinal

2019-12-10 17:10

@neo1999 @shanmine @happyboy

jfinal undertow 2.0 已发布到 maven 中心库,以往针对支持 JSP 的代码可以删掉了,用上 jfinal undertow 2.0 ,直接在 configWeb 中添加配置即可

热门分享

扫码入社