JFinal使用技巧-javax-to-jakarta 桥接适配器

如题,前两天又看到群友说想JFinal支持Tomcat 10+,历史原因包名从 javax.servlet 变更为 jakarta.servlet 真是个糟糕的决定。所以波大新项目aifei直接无servlet~  老项目不愿意迁移的,还得在JF不是。以前看过一篇文章说Tomcat官方有桥接包,但是实际使用下来,并不方便,咱社区也有社友分享(右上角搜索Tomcat 10可见)。
但是并不是我想要的那种桥接方案,昨晚我把我的“装饰模式”想法给AI说了一遍,它用了2小时完成了编码与测试 并maven中心推送了。(具体时间没统计,中间忙其他的去了,它让我输入GPG密钥卡住了)

算了废话不多说 上 石马 ~

image.png

使用姿势 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>


启动测试:

image.png

没问题~

放下源码地址:
https://gitee.com/bean80/jfinal-javax-to-jakarta

这个是我想要的桥接方案,JFianl 不用改,中间的Request、Response 这些类我自己进行一个转调,以及业务中的依赖,该取Jakarta对象的就用新的。
如果有用到这个项目方案的,当Request中有用到的方法没实现全的,可以直接把项目拉下来,让AI去改就可以了,我用的Qoder CN

评论区

天晴

2026-08-20 17:56

前排支持老杜

热门分享

扫码入社