问题
I need to deploy our web application in tomcat 7.but my application use JNDI data source. how to create jndi DataSource in Tomcat 7
回答1:
Have you tried the Tomcat Manual: http://tomcat.apache.org/tomcat-7.0-doc/jndi-datasource-examples-howto.html
(Hint: Google String was "jndi datasource tomcat 7")
回答2:
I can show how I do it in Tomcat 9. This may or may not work in Tomcat 7. FYI, Tomcat 7 seems to be in maintenance-mode.
In my situation, I want to store settings such as database access info outside my web-app’s WAR file. This gives me flexibility for each of my development, testing, and production servers to have their own settings resident in their file system. Ditto for my customers running my app. No need to edit the WAR file, or produce individualized WAR files, if these settings are kept externally, living on each server separately. And no need to re-edit the WAR file when settings change or when a new version of the WAR file arrives.
In the Tomcat "home" folder, or Tomcat "base" folder if you’ve designated one, go into the conf
folder to create a Catalina
folder. ”Catalina” is the name of the Tomcat engine. Nest within that a new folder named localhost
, the name of your host. Within that create an XML file, named the name of your context.
I find that app-name-goes-here.xml
approach is a simple place to store these settings external to my web-app’s WAR file, yet not having to mess with Tomcat's own files. This approach is rather obtusely documented in the middle bullet beginning "In individual files" in the Defining a context section of The Context Container page of the Tomcat Configuration Reference.
For example, here is a screenshot of my app named TickTock, using a "base" folder outside the Tomcat folder.
In that XML file you can define things like environment variables such as a "DEV" versus "PROD" flag or a feature toggle, and resources such as a JDBC DataSource singleton to be instantiated. These items are managed by Tomcat's own implementation of an LDAP-like server that can be accessed via JNDI.
Here is a nearly-realistic example of my ticktock.xml
file.
Notice the first few attributes of each attribute; these are standard, defined by the Servlet spec and documented here for environment entries, and here for resource entries.
And notice how the Resource
element has additional attributes. These are specific the particular resource. In this case, the particular resource is this Postgres JDBC driver.
<Context>
<!-- Domain: DEV, TEST, PROD -->
<Environment
name = "work.basil.ticktock.deployment-mode"
description = "Signals whether to run this web-app with development, testing, or production settings."
type = "java.lang.String"
value = "DEV"
override = "false"
/>
<Resource
name = "jdbc/ticktockdb"
description = "Database used by the TickTock app."
type = "javax.sql.DataSource"
auth = "Container"
singleton = "true"
driverClassName = "org.postgresql.Driver"
url = "jdbc:postgresql://127.0.0.1:5432/ticktockdb"
username = "TickTockApp"
password = "pw"
maxTotal = "20"
maxIdle = "10"
maxWaitMillis = "-1"
/>
</Context>
How get an object for either this environment entry or this resource entry?
First, get a JNDI "context" from which to access these entries.
Context ctx = new InitialContext ();
You will also need trap for any NamingException, but I'll omit that code.
You can dump all your environment entries with this simple code. I use lambda syntax here, but you can just as well use classic Java syntax.
// Read all properties.
System.out.println ( "INFO - Dumping bindings for environment variables." );
ctx.listBindings ( "java:comp/env" ).asIterator ().forEachRemaining (
( Binding binding ) -> {
String msg = binding.getName () + " : " + binding.getObject ();
System.out.println ( msg );
this.add ( new Paragraph ( msg ) );
} );
Or fetch a specific one.
String deployMode = ( String ) ctx.lookup( "java:comp/env/work.basil.ticktock.deployment-mode" );
To get a DataSource
object, we must cast the Object
returned by JNDI.
DataSource ds = ( DataSource ) ctx.lookup( "java:/comp/env/jdbc/ticktockdb" );
This is all we need!
You will see other discussions about additional configuration for further Servlet or Tomcat features that provide another layer of indirection, so the naming within your code does not need to match the names in the LDAP or other server being accessed by JNDI. While I am not sure, I believe that if the extra layer of indirection is not necessary for our web-app project, our environment or resource request will be provided directly from the naming server if we specify the entire JNDI lookup string as seen here, starting with java:/comp/env
rather than just the ending part jdbc/ticktockdb
. If anyone would like to clarify this, please post a comment or edit this Answer.
JDBC driver
JDBC drivers are problematic in a Servlet container. Long story short, you should not bundle the JDBC driver with your web-app in its WAR file.
Instead, you want to load the JDBC driver on the Common class loader or possibly the Shared class loader. For the Common class loader to auto-detect your JDBC driver, drop its JAR file into Tomcat's lib
folder (or if using a designated "base" folder as seen above, create a lib
folder as seen above, and deposit your driver’s JAR there).
来源:https://stackoverflow.com/questions/28368103/how-to-configure-jndi-datasource-in-tomcat-7