具体看代码的resolveJNDIProps方法。首先在tomcatd的config/context.xml里添加代码
<?xml version='1.0' encoding='utf-8'?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- The contents of this file will be loaded for each web application -->
<Context>
<!-- Default set of monitored resources -->
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<Environment name="redis-0-port" override="false" type="java.lang.Integer" value="6379"/>
<Environment name="redis-0-user" override="false" type="java.lang.String" value="root"/>
<!-- Uncomment this to disable session persistence across Tomcat restarts -->
<!--
<Manager pathname="" />
-->
<!-- Uncomment this to enable Comet connection tacking (provides events
on session expiration as well as webapp lifecycle) -->
<!--
<Valve className="org.apache.catalina.valves.CometConnectionManagerValve" />
-->
</Context>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- The contents of this file will be loaded for each web application -->
<Context>
<!-- Default set of monitored resources -->
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<Environment name="redis-0-port" override="false" type="java.lang.Integer" value="6379"/>
<Environment name="redis-0-user" override="false" type="java.lang.String" value="root"/>
<!-- Uncomment this to disable session persistence across Tomcat restarts -->
<!--
<Manager pathname="" />
-->
<!-- Uncomment this to enable Comet connection tacking (provides events
on session expiration as well as webapp lifecycle) -->
<!--
<Valve className="org.apache.catalina.valves.CometConnectionManagerValve" />
-->
</Context>
具体分析resolveJNDIProps方法,代码如下:
/* * Copyright 2010 LinkedIn, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package azkaban.jobs.builtin; import azkaban.app.JobDescriptor; import azkaban.common.jobs.Job; import azkaban.common.utils.Props; import azkaban.jobs.AbstractProcessJob; import org.apache.log4j.Level; import org.apache.log4j.Logger; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import javax.naming.InitialContext; import javax.naming.NameClassPair; import javax.naming.NamingEnumeration; import javax.naming.NamingException; /** * A job that runs a simple unix command * * @author jkreps * */ public class ProcessJob extends AbstractProcessJob implements Job { private static final Logger log = Logger.getLogger(ProcessJob.class); public static final String COMMAND = "command"; public static final int CLEAN_UP_TIME_MS = 1000; private volatile Process _process; private volatile boolean _isComplete; public ProcessJob(JobDescriptor descriptor) { super(descriptor); } public void resolveJNDIProps(){ log.info("*****************************************"); log.info("resolve JNDI props from InitialContext"); log.info("*****************************************"); //read all settings from jndi context InitialContext ic; try { ic = new InitialContext(); NamingEnumeration<NameClassPair> em = ic.list("java:/comp/env"); while(em.hasMoreElements()){ NameClassPair nPair = em.nextElement(); String sClass = nPair.getClassName(); String sName = nPair.getName(); Object value = ic.lookup("java:/comp/env/"+sName); if(sClass.contains("String")||sClass.contains("Integer")||sClass.contains("Long")||sClass.contains("Double")){ this._env.put("jndi."+sName, value.toString()); log.info("resolve jndi prop. name=" + sName + ", value=" + value); }else{ log.info("skip jndi prop. name=" + sName + ", value=" + value); } } this._env.put("jndi.resolved", Boolean.TRUE.toString()); } catch (NamingException e) { // ignored log.error("exception at resolve all jndi props.", e); this._env.put("jndi.resolved", e.getClass().getCanonicalName()); } } public void run() { resolveProps(); resolveJNDIProps(); // Sets a list of all the commands that need to be run. List<String> commands = getCommandList(); info(commands.size() + " commands to execute."); File[] propFiles =initPropsFiles(); //System.err.println("in process job outputFile=" +propFiles[1]); // For each of the jobs, set up a process and run them. for(String command: commands) { info("Executing command: " + command); String[] cmdPieces = partitionCommandLine(command); ProcessBuilder builder = new ProcessBuilder(cmdPieces); builder.directory(new File(getCwd())); builder.environment().putAll(getEnv()); try { _process = builder.start(); } catch(IOException e) { for (File file: propFiles) if (file != null && file.exists()) file.delete(); throw new RuntimeException(e); } Thread outputGobbler = new LoggingGobbler(new InputStreamReader(_process.getInputStream()), Level.INFO); Thread errorGobbler = new LoggingGobbler(new InputStreamReader(_process.getErrorStream()), Level.ERROR); int processId = getProcessId(); if(processId == 0) { info("Spawned thread. Unknowned processId"); } else { info("Spawned thread with processId " + processId); } outputGobbler.start(); errorGobbler.start(); int exitCode = -999; try { exitCode = _process.waitFor(); } catch(InterruptedException e) { } _isComplete = true; if(exitCode != 0) { for (File file: propFiles) if (file != null && file.exists()) file.delete(); throw new RuntimeException("Processes ended with exit code " + exitCode + "."); } // try to wait for everything to get logged out before exiting try { outputGobbler.join(1000); errorGobbler.join(1000); } catch(InterruptedException e) { } } // Get the output properties from this job. generateProperties(propFiles[1]); for (File file: propFiles) if (file != null && file.exists()) file.delete(); } protected List<String> getCommandList() { List<String> commands = new ArrayList<String>(); commands.add(_props.getString(COMMAND)); for(int i = 1; _props.containsKey(COMMAND + "." + i); i++) commands.add(_props.getString(COMMAND + "." + i)); return commands; } @Override public void cancel() throws Exception { if(_process != null) { int processId = getProcessId(); if(processId != 0) { warn("Attempting to kill the process " + processId); try { Runtime.getRuntime().exec("kill " + processId); synchronized(this) { wait(CLEAN_UP_TIME_MS); } } catch(InterruptedException e) { // Do nothing. We don't really care. } if(!_isComplete) { error("After " + CLEAN_UP_TIME_MS + " ms, the job hasn't terminated. Will force terminate the job."); } } else { info("Cound not get process id"); } if(!_isComplete) { warn("Force kill the process"); _process.destroy(); } } } public int getProcessId() { int processId = 0; try { Field f = _process.getClass().getDeclaredField("pid"); f.setAccessible(true); processId = f.getInt(_process); } catch(Throwable e) {} return processId; } @Override public double getProgress() { return _isComplete ? 1.0 : 0.0; } private class LoggingGobbler extends Thread { private final BufferedReader _inputReader; private final Level _loggingLevel; public LoggingGobbler(InputStreamReader inputReader, Level level) { _inputReader = new BufferedReader(inputReader); _loggingLevel = level; } @Override public void run() { try { while(!Thread.currentThread().isInterrupted()) { String line = _inputReader.readLine(); if(line == null) return; logMessage(line); } } catch(IOException e) { error("Error reading from logging stream:", e); } } private void logMessage(String message) { if(message.startsWith(Level.DEBUG.toString())) { String newMsg = message.substring(Level.DEBUG.toString().length()); getLog().debug(newMsg); } else if(message.startsWith(Level.ERROR.toString())) { String newMsg = message.substring(Level.ERROR.toString().length()); getLog().error(newMsg); } else if(message.startsWith(Level.INFO.toString())) { String newMsg = message.substring(Level.INFO.toString().length()); getLog().info(newMsg); } else if(message.startsWith(Level.WARN.toString())) { String newMsg = message.substring(Level.WARN.toString().length()); getLog().warn(newMsg); } else if(message.startsWith(Level.FATAL.toString())) { String newMsg = message.substring(Level.FATAL.toString().length()); getLog().fatal(newMsg); } else if(message.startsWith(Level.TRACE.toString())) { String newMsg = message.substring(Level.TRACE.toString().length()); getLog().trace(newMsg); } else { getLog().log(_loggingLevel, message); } } } public Props getProps() { return _props; } public String getPath() { return _jobPath; } public String getJobName() { return getId(); } public JobDescriptor getJobDescriptor() { return _descriptor; } /** * Splits the command into a unix like command line structure. Quotes and * single quotes are treated as nested strings. * * @param command * @return */ public static String[] partitionCommandLine(String command) { ArrayList<String> commands = new ArrayList<String>(); int index = 0; StringBuffer buffer = new StringBuffer(command.length()); boolean isApos = false; boolean isQuote = false; while(index < command.length()) { char c = command.charAt(index); switch(c) { case ' ': if(!isQuote && !isApos) { String arg = buffer.toString(); buffer = new StringBuffer(command.length() - index); if(arg.length() > 0) { commands.add(arg); } } else { buffer.append(c); } break; case '\'': if(!isQuote) { isApos = !isApos; } else { buffer.append(c); } break; case '"': if(!isApos) { isQuote = !isQuote; } else { buffer.append(c); } break; default: buffer.append(c); } index++; } if(buffer.length() > 0) { String arg = buffer.toString(); commands.add(arg); } return commands.toArray(new String[commands.size()]); } }
相关推荐
#### 二、JNDI配置方式概述 JNDI在Tomcat中有三种常见的配置方式: 1. **全局配置**:在`context.xml`中进行配置,适用于所有Web应用程序。 2. **局部配置**(第一种):在`server.xml`的`<host>`标签内部进行配置...
除了基本配置,Tomcat还支持热部署、集群、安全管理和JNDI(Java Naming and Directory Interface)等功能。热部署允许开发者在不重启服务器的情况下更新应用,提高了开发效率。集群则能实现负载均衡和故障转移,...
- 在服务器配置文件(如Tomcat的`context.xml`或应用的`web.xml`)中定义JNDI数据源,引用属性文件中的连接信息。 - 在应用代码中,使用`InitialContext`查找JNDI数据源,然后从数据源获取数据库连接。 - 示例...
3. **数据源配置(Resource)**:在`server.xml`或`context.xml`中配置JNDI数据源,便于JDBC连接的管理。数据源的配置包括数据库URL、用户名、密码、驱动类名等。 4. **JDBC驱动配置**:将JDBC驱动的JAR文件放入...
例如,如果需要更改数据库连接字符串,只需要修改JNDI配置即可,而无需更改应用程序代码。 #### 五、在Tomcat中配置JNDI资源 ##### 5.1 创建Context配置文件 要在Tomcat中配置JNDI资源,首先需要创建一个`context...
JNDI配置文档(如`JNDI配置.doc`)可能包含如何在不同应用服务器(如Tomcat、JBoss、WebLogic等)中配置JNDI资源的详细步骤,包括设置应用服务器的配置文件、编写JNDI绑定代码以及处理相关异常等内容。这些配置对于...
### Tomcat配置数据源详解 #### 一、引言 在Java Web开发中,Tomcat作为一款广泛使用的轻量级Web服务器,对于开发者而言是非常重要的工具之一。而在实际的应用部署过程中,经常需要对Tomcat进行各种配置以满足不同...
2. **启动过程分析**:Tomcat的启动过程包括读取配置文件、初始化服务器、加载web应用等步骤。其中,`catalina.sh/bat`是主要的启动脚本,它会读取`conf/server.xml`等配置文件,这些文件定义了服务器的端口、线程池...
JNDI不仅限于文件系统,它也可以是其他类型的服务器,例如LDAP服务器,应用服务器如Tomcat、JBoss等通常都提供了对JNDI的支持。在给定的例子中,我们将看到如何使用JNDI来绑定和查找Oracle数据源。 1. **绑定数据源...
5. **JNDI配置**:`context.xml`中的JNDI配置可能不正确,例如数据源(DataSource)配置可能有误。 解决这个问题的方法包括: 1. **验证配置**:确认`context.xml`的结构和内容是否符合规范,比如数据源配置应该...
9. **JMX监控**:Tomcat提供了JMX接口,可以远程监控和管理Tomcat实例的状态和配置。 10. **插件扩展**:Tomcat的Valve机制允许开发者插入自定义的处理逻辑,实现特定的功能或过滤。 理解Tomcat源码不仅有助于提升...
当我们启动Tomcat时,它首先会读取`conf/server.xml`配置文件,该文件定义了服务器的各个组件和监听的端口。接着,Tomcat会加载`WEB-INF/web.xml`中的应用配置,初始化Servlet和过滤器,并启动连接器、上下文、...
Tomcat提供了多种方式来实现session共享,如使用粘性会话、共享内存、数据库存储以及基于JNDI的会话复制等。 1. **粘性会话(Sticky Sessions)**:这是最简单的session共享方式,通过负载均衡器将特定用户的请求...
7. **配置解析**:Tomcat读取`server.xml`、`context.xml`等配置文件,学习配置解析逻辑能帮助你更好地定制服务器。 8. **JAR依赖**:Tomcat运行需要一系列的库文件,理解这些依赖可以帮助你解决部署问题。 在学习...
启动Tomcat时,`catalina.sh`(或`catalina.bat`)脚本会读取配置并启动服务器。 9. **安全与权限** Tomcat支持角色基的安全模型,通过`tomcat-users.xml`配置用户角色和权限,以及在`web.xml`中定义受保护的URL和...
Tomcat的启动脚本(如bin目录下的Startup.bat)会读取配置文件并启动服务器。一旦运行,开发者可以通过浏览器访问Tomcat的管理界面,如`http://localhost:8080/manager/html`,进行应用部署、监控和管理。 总结来说...
1. **启动**:Tomcat启动时,会读取配置文件(如server.xml和web.xml),解析并加载所有必要的组件和服务。 2. **请求处理**:当HTTP请求到达时,Connector捕获请求,解析请求头和实体,然后将请求转发给Catalina...
1. 加载服务器配置:Tomcat读取`conf/server.xml`文件,这是服务器的主要配置文件,定义了服务器的端口、连接器、上下文等。 2. 初始化:Tomcat初始化各个模块,如JMX注册、JNDI目录等。 3. 加载 Realm:Realm是...