如题,前两天又看到群友说想JFinal支持Tomcat 10+,历史原因包名从 javax.servlet 变更为 jakarta.servlet 真是个糟糕的决定。所以波大新项目aifei直接无servlet~ 老项目不愿意迁移的,还得在JF不是。以前看过一篇文章说Tomcat官方有桥接包,但是实际使用下来,并不方便,咱社区也有社友分享(右上角搜索Tomcat 10可见)。
但是并不是我想要的那种桥接方案,昨晚我把我的“装饰模式”想法给AI说了一遍,它用了2小时完成了编码与测试 并maven中心推送了。(具体时间没统计,中间忙其他的去了,它让我输入GPG密钥卡住了)
算了废话不多说 上 石马 ~
使用姿势 jfinal-javax-to-jakarta 的依赖:
<dependencies>
<!-- JFinal 核心 -->
<dependency>
<groupId>com.jfinal</groupId>
<artifactId>jfinal</artifactId>
<version>5.2.7</version>
</dependency>
<!-- javax-to-jakarta 桥接适配器 -->
<dependency>
<groupId>top.myedu.maven</groupId>
<artifactId>jfinal-javax-to-jakarta</artifactId>
<version>1.0.0</version>
</dependency>
<!-- 桥接模块运行时依赖 javax.servlet-api (provided 不传递,需显式声明) -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<!-- Tomcat 10 嵌入式 (Jakarta Servlet 6.0) -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>${tomcat.version}</version>
</dependency>
</dependencies>经典Demo输出 Hello JFinal World
public class HelloController extends Controller {
public void index() {
renderText("Hello JFinal World.");
}
}public class DemoConfig extends JFinalConfig {
@Override
public void configRoute(Routes me) {
me.add("/", HelloController.class);
}
@Override
public void configConstant(Constants me) {
me.setDevMode(true);
}
@Override
public void configInterceptor(Interceptors me) {
}
@Override
public void configHandler(Handlers me) {
}
@Override
public void configPlugin(Plugins me) {
}
@Override
public void configEngine(Engine me) {
}
}这里我使用 嵌入式Tomcat10 方便调试:
/**
* Embedded Tomcat 10 launcher for JFinal via JakartaBridgeFilter.
*
* Tomcat 10 uses jakarta.servlet namespace.
* JakartaBridgeFilter bridges jakarta -> javax, so JFinal works unchanged.
*/
public class TomcatEmbedMain {
public static void main(String[] args) throws Exception {
int port = 8080;
Tomcat tomcat = new Tomcat();
tomcat.setPort(port);
tomcat.getConnector(); // trigger default connector creation
// Create webapp context
String baseDir = System.getProperty("java.io.tmpdir");
Context ctx = tomcat.addContext("", baseDir);
// Use current classloader so Tomcat can find Maven dependencies
ctx.setParentClassLoader(Thread.currentThread().getContextClassLoader());
// Add a default servlet (required for filters to be invoked)
Tomcat.addServlet(ctx, "default", "org.apache.catalina.servlets.DefaultServlet");
ctx.addServletMappingDecoded("/*", "default");
// Register JakartaBridgeFilter using Tomcat internal API
// (ServletContext.addFilter() rejects after context init in Tomcat 10.1)
FilterDef filterDef = new FilterDef();
filterDef.setFilterName("jfinal");
filterDef.setFilterClass("com.jfinal.jakarta.servlet.JakartaBridgeFilter");
filterDef.addInitParameter("configClass", "com.example.DemoConfig");
ctx.addFilterDef(filterDef);
FilterMap filterMap = new FilterMap();
filterMap.setFilterName("jfinal");
filterMap.addURLPattern("/*");
ctx.addFilterMap(filterMap);
System.out.println("========================================");
System.out.println(" JFinal on Tomcat 10 (Jakarta Servlet)");
System.out.println(" http://localhost:" + port + "/");
System.out.println("========================================");
tomcat.start();
tomcat.getServer().await();
}
}注意这里的关键 配置:
com.jfinal.core.JFinalFilter 改为了: com.jfinal.jakarta.servlet.JakartaBridgeFilter
软件版的Tomcat 就是需要改 web.xml 配置了
<filter> <filter-name>jfinal</filter-name> <filter-class>com.jfinal.jakarta.servlet.JakartaBridgeFilter</filter-class> <init-param> <param-name>configClass</param-name> <param-value>com.example.MyJFinalConfig</param-value> </init-param></filter><filter-mapping> <filter-name>jfinal</filter-name> <url-pattern>/*</url-pattern></filter-mapping>
启动测试:

没问题~
放下源码地址:
https://gitee.com/bean80/jfinal-javax-to-jakarta
这个是我想要的桥接方案,JFianl 不用改,中间的Request、Response 这些类我自己进行一个转调,以及业务中的依赖,该取Jakarta对象的就用新的。
如果有用到这个项目方案的,当Request中有用到的方法没实现全的,可以直接把项目拉下来,让AI去改就可以了,我用的Qoder CN
项目:JFinal