首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Spring @Autowired 注入 Servlet 完整方案:從手動配置到代理模式最佳實踐

     編輯:Java 相關知識

問題背景

Spring 管理的 Bean 可直接使用 @Autowired,但 Servlet 與 Filter 由 Servlet 容器實例化,不在 Spring 容器中,無法直接注入。

方案一:手動注入(不推薦)

public class MyServlet extends HttpServlet {
    @Autowired private UserService userService; // 無效!

    @Override
    public void init(ServletConfig config) throws ServletException {
        ServletContext ctx = config.getServletContext();
        WebApplicationContext wac = WebApplicationContextUtils.getWebApplicationContext(ctx);
        AutowireCapableBeanFactory factory = wac.getAutowireCapableBeanFactory();
        factory.autowireBean(this); // 或 factory.configureBean(this, "beanName");
    }
}

缺點:硬編碼 Bean 名稱、侵入式程式碼、非標準 DI 風格。

方案二:DelegatingServletProxy 代理模式(推薦)

步驟 1:建立代理類別

public class DelegatingServletProxy extends GenericServlet {
    private String targetBean;
    private Servlet proxy;

    @Override
    public void init() throws ServletException {
        this.targetBean = getServletName(); // 從 web.xml 取得
        getServletBean();
        proxy.init(getServletConfig());
    }

    private void getServletBean() {
        WebApplicationContext wac = WebApplicationContextUtils
            .getRequiredWebApplicationContext(getServletContext());
        this.proxy = (Servlet) wac.getBean(targetBean);
    }

    @Override
    public void service(ServletRequest req, ServletResponse res)
            throws ServletException, IOException {
        proxy.service(req, res); // 委派給真正的 Servlet
    }
}

步驟 2:真實 Servlet 註冊為 Spring Bean

@Component("userServlet") // Bean 名稱對應 web.xml servlet-name
public class UserServlet extends HttpServlet {
    @Autowired private UserManager userManager; // 正常注入

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        // 業務邏輯
    }
}

步驟 3:web.xml 配置代理

<servlet>
    <servlet-name>userServlet</servlet-name> <!-- 必須與 @Component 值一致 -->
    <servlet-class>com.example.DelegatingServletProxy</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>userServlet</servlet-name>
    <url-pattern>/userServlet</url-pattern>
</servlet-mapping>

原理圖解

請求 → DelegatingServletProxy (容器管理) 
       → Spring 容器查找 "userServlet" Bean 
       → UserServlet (Spring 管理,已注入依賴) 
       → 執行業務邏輯

Filter 的解決方案

Spring 內建 DelegatingFilterProxy,配置方式類似:

<filter>
    <filter-name>securityFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

對應的 Spring Bean 需實作 javax.servlet.Filter 介面。

Spring Boot 時代的簡化

@SpringBootApplication
public class Application {
    @Bean
    public ServletRegistrationBean<UserServlet> userServlet() {
        return new ServletRegistrationBean<>(new UserServlet(), "/userServlet");
    }
}

Spring Boot 自動將 Servlet 註冊為 Bean 並掛載,無需 web.xml、無需代理類別。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved