最近我嘗試了Tomcat 10.0.10,當試圖將連接池作為JNDI資源注入時,發現@Resource注釋不起作用。
然后我試著通過創建一個InitialContext來以編程方式獲得它,結果成功了。最初我認為這只適用于java:comp/env/jdbc,所以我試著用一個簡單的bean,就像下面這樣,并嘗試用@Resource注解來注入它,但它沒有再次作業。當我試圖通過創建一個InitialContext來以編程方式獲得它時,它就作業了。然后我檢查@PostConstruct或@PreDestroy注解是否作業,發現它們也不作業。
package lk.ijse.test.tomcatdbcp;
public class Something {
}
<?xml version="1.0" encoding="UTF-8"? >
<Context>/span>
<Resource name="bean/Something" auth="Container"
type="lk.ijse.test.tomcatdbcp.Something"
factory="org.apache.naming.factory.BeanFactory"。
/>
</Context>
<?xml version="1.0" encoding="UTF-8"? >
<web-app metadata-complete="false"/span> xmlns="https://jakarta.ee/xml/ns/jakartaee"/span>
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"。
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"/span>
version="5.0"/span>>
<resource-env-ref>/span>
<resource-env-ref-name>bean/Something</resource-env-ref-name>
<resource-env-ref-type>l.ijse.test.tomcatdbcp.Something</resource-env-ref-type>/span>
</resource-env-ref>
</web-app>/span>
package lk.ijse.test.tomcatdbcp;
import java.io.*;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource。
import jakarta.servlet.http.*;
import jakarta.servlet.annotation.*;
import javax.naming.InitialContext;
import javax.naming.NamingException;
@WebServlet(name = "helloServlet", value = "/hello", loadOnStartup = 1)
public class HelloServlet extends HttpServlet {
private String message;
@Resource(name="java:comp/env/bean/Something")
private something something。
@PostConstruct
public void doSomething(){
System.out.println("是否有效?")。
}
public void init(){
message = "Hello World!";
try {
InitialContext ctx = new InitialContext() 。
Something lookup = (Something) ctx.lookup("java:comp/env/bean/Something"/span>) 。
System.out.println(lookup)。
System.out.println(something); //null。
} catch (NamingException e) {
e.printStackTrace()。
}
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setContentType("text/html")。
//Hello
PrintWriter out = response.getWriter()。
out.println("<html><body>") 。
out.println("<h1>" message "</h1>") 。
out.println("</body></html>") 。
}
public void destroy() {
}
為了重現同樣的問題,我在這里創建了一個樣本 repo。https://github.com/sura-boy-playground/play-with-tomcat10。 (完整的代碼可以在那里找到)
起初,我使用了javax.annotation.Resource注解,所以我認為這是由于javax.*到jakarta.*命名空間改變的原因。然后我用jakarta.annotation.Resource進行了嘗試,但結果還是一樣。
我用 Tomcat 9.0.41 加上 在 Tomcat 10.0.10 上,我是否需要做一些額外的事情來啟用這些注釋?我挖掘了 Tomcat 10 檔案,但我無法找到與我的問題有關的任何東西。
我發現之前在 Tomcat 7 中也有類似的情況,但我現在不喜歡那種變通的方法。
Tomcat @Resource annotations API注釋在Tomcat 7中停止作業 uj5u.com熱心網友回復: 你應該宣告你的 如果你有兩份 雖然添加 備注:如果您使用 Java 11 或更高版本,您將在 Tomcat 9.0 中遇到同樣的問題。在Java 11之前,
標籤: 上一篇:谷歌應用腳本側邊欄不能正確加載
javax.* 命名空間嘗試了相同的應用程式,它作業得非常好。
jakarta.annotation依賴的范圍為provided:<dependency>
<groupId>Jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
<version>/span>2.0.0</version>
<scope>provided</scope>
</dependency>/span>
jakarta.annotation.Resource(一份在common classloader中,一份在你的應用程式的classloader中),這兩個類是不同的。InstanceManager將尋找被common類加載器的@Resource副本注釋的欄位,而something欄位被您的 webapp 的@Resource副本注釋。
jakarta.annotation的范圍與provided不同肯定是一個錯誤,但這可能是一個常見的錯誤,Tomcat有一個故障安全功能,可以忽略與你的應用程式一起分發的某些類(參照源代碼)。由于jakarta.annotation.*類不在其中,你可以提交一份(愿望)錯誤報告。
javax.annotation.*類包含在JRE中。Servlet 容器需要在 bootstrap/JRE 類加載器中查找,然后再在 webapp 類加載器中查找(覆寫 javax.* 類是違反 Java 許可的),因此 Tomcat 將永遠不會找到這些類的額外副本。
