`
hiphunter921
  • 浏览: 68743 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

对tomcat admin中的datasource管理的扩展(一)

阅读更多

目的是要实现一个可以通过前台网页,来对tomcat中的jndi数据源行进配置的应用。

 

一下想到了tomcat admin,可惜这东西只在5.5下有支持,6.0后还没支持,说是要下个大版本才会可能有支持。

 

所以自己下载的5.5下的admin,并且build了起来,看看还挺好用,差不多就是我需要的那些。

 

在来看看源码,发现使用的struts1写的mvc,页面上好多的struts1标签,然后对tomcat内部的操作,全部使用了MBean的方式。

 

我只需要对jndi数据源的配置部分,那就着重看这块的代码吧。

关键就是org.apache.webapp.admin.resources包下的SaveDataSourceAction类中的:

 

 objectName = (String) mserver.invoke(oname, "addResource", params, signature);

 

 这句调用了tomcat内部mbean中实现的addResource方法,我需要使用自己的com.elite.aps.dbservice.http.APSDataSourceFactory类作为数据源工厂类,别且对其中自己扩展的属性进行配置,因此在jsp页面与相关的action中添加了对应的代码,SaveDataSourceAction中也同样,在调用完addResource后,对返回的ObjectName调用其设置属性的方法,类似:

 

 if(StringUtil.isNotNull(dataSourceForm.getDbtype()))
            	mserver.setAttribute(oname, new Attribute("dbtype",dataSourceForm.getDbtype()));
 if(StringUtil.isNotNull(dataSourceForm.getInitialSize()))
            	mserver.setAttribute(oname, new Attribute("initialSize",dataSourceForm.getInitialSize()));

 

界面上操作完了穿件数据源后,发现并没有保存到对应的server.xml或者context.xml中,发现还有一步commit change的操作,而tomcat6.0中这部操作对应的MBean并没有实现,那就自己实现以下吧。

按照MBean的规则,定义一个StoreServerConfigMBean的接口,其中一个方法void storeConfig(),并且提供对应的实现类:

 

public class StoreServerConfig implements StoreServerConfigMBean {
	private static Log log = LogFactory.getLog(StoreServerConfig.class);
	
	private String serverFilename = "conf/server.xml";
	private String contextFilename = "conf/context.xml";

  
    public String getServerFilename() {
        return serverFilename;
    }
    public void setServerFilename(String string) {
        serverFilename = string;
    }
	public String getContextFilename() {
		return contextFilename;
	}
	public void setContextFilename(String contextFilename) {
		this.contextFilename = contextFilename;
	}
	
	public synchronized void storeConfig() {
		try{
			storeServerFile();//save to server.xml
			storeContextFile();//save to context.xml
		}catch(Exception e){
			log.error("",e);
		}
	}
	
	private void storeContextFile(){
		StoreFileUtil sfContext = new StoreFileUtil(System.getProperty("catalina.base"), getContextFilename(),"utf-8");
		try {
            PrintWriter writer = sfContext.getWriter();
            SAXReader reader = new SAXReader();   
            Document doc = reader.read(sfContext.getReader());
            Element contextElement=(Element)doc.selectSingleNode("/Context");
            List<Element> resourceList=contextElement.selectNodes("ResourceLink[@type='"+ResourceUtils.DATASOURCE_CLASS+"']");
            if(resourceList!=null && resourceList.size()>0){
            	for(Element resource : resourceList){
            		contextElement.remove(resource);
            	}
            }
            MBeanServer mserver = CatalinaUtils.getServer();
            DataSourcesForm dsf=ResourceUtils.getDataSourcesForm(mserver, "Global", null, null, "Catalina");
            String[] dataSources=dsf.getDataSources();
            for(int i=0;i<dataSources.length;i++){
            	ObjectName oname = new ObjectName(dataSources[i]);
            	String name=(String)mserver.getAttribute(oname, "name");
            	
            	Element resourceLinkEle=contextElement.addElement("ResourceLink");
            	resourceLinkEle.addAttribute("name", name);
            	resourceLinkEle.addAttribute("type", ResourceUtils.DATASOURCE_CLASS);
            	resourceLinkEle.addAttribute("global", name);
            	
            }
            writeOut(writer,doc);
            sfContext.move();
            
		} catch (Exception e) {
            log.error("",e);
        }
	}

	private void storeServerFile(){
		StoreFileUtil sfServer = new StoreFileUtil(System.getProperty("catalina.base"), getServerFilename(),"utf-8");
		try {
            PrintWriter writer = sfServer.getWriter();
            SAXReader reader = new SAXReader();   
            Document doc = reader.read(sfServer.getReader());
            Element gnrElement=(Element)doc.selectSingleNode("/Server/GlobalNamingResources");
            List<Element> resourceList=gnrElement.selectNodes("Resource[@type='"+ResourceUtils.DATASOURCE_CLASS+"']");
            if(resourceList!=null && resourceList.size()>0){
            	for(Element resource : resourceList){
            		gnrElement.remove(resource);
            		CatalinaUtils.removeResourceLinkFromNamingContextListener(resource.attributeValue("name"));
            	}
            }
            
            MBeanServer mserver = CatalinaUtils.getServer();
            DataSourcesForm dsf=ResourceUtils.getDataSourcesForm(mserver, "Global", null, null, "Catalina");
            String[] dataSources=dsf.getDataSources();
            for(int i=0;i<dataSources.length;i++){
            	ObjectName oname = new ObjectName(dataSources[i]);
            	String name=(String)mserver.getAttribute(oname, "name");
            	String type=(String)mserver.getAttribute(oname, "type");
            	String factory=(String)mserver.getAttribute(oname, "factory");
            	String url=(String)mserver.getAttribute(oname, "url");
            	String driverClassName=(String)mserver.getAttribute(oname, "driverClassName");
            	String username=(String)mserver.getAttribute(oname, "username");
            	String password=(String)mserver.getAttribute(oname, "password");
            	String maxActive=(String)mserver.getAttribute(oname, "maxActive");
            	String maxIdle=(String)mserver.getAttribute(oname, "maxIdle");
            	String maxWait=(String)mserver.getAttribute(oname, "maxWait");
            	
            	Element resourceEle=gnrElement.addElement("Resource");
            	resourceEle.addAttribute("name", name);
            	resourceEle.addAttribute("type", type);
            	resourceEle.addAttribute("factory", factory);
            	resourceEle.addAttribute("url", url);
            	resourceEle.addAttribute("driverClassName", driverClassName);
            	resourceEle.addAttribute("username", username);
            	resourceEle.addAttribute("password", password);
            	resourceEle.addAttribute("maxActive", maxActive);
            	resourceEle.addAttribute("maxIdle", maxIdle);
            	resourceEle.addAttribute("maxWait", maxWait);
            	
            	CatalinaUtils.addResourceLinkFromNamingContextListener(resourceEle.attributeValue("name"));
            }
            writeOut(writer,doc);
            sfServer.move();
        } catch (Exception e) {
            log.error("",e);
        }
	
	}

	private void writeOut(PrintWriter writer,Document doc) throws Exception{
		try {
        	OutputFormat format = OutputFormat.createPrettyPrint();
        	format.setEncoding("utf-8");
        	format.setLineSeparator(System.getProperty("line.separator"));
        	XMLWriter xmlWriter = new NotepadXMLWriter(writer, format);
        	xmlWriter.write(doc);
        	xmlWriter.flush();
        } finally {
            try {
                writer.flush();
            } catch (Exception e) {
                log.error(e);
            }
            try {
                writer.close();
            } catch (Exception e) {
                throw (e);
            }
        }
	}
	
}

 

这个类中,主要是去做了把当前jmx中的datasource写到响应的配置文件中,server.xml中写入Resource到GlobalNamingResources标签下,context.xml中写入对应的ResourceLink。这样应用就可以直接使用到了,看似不错。

这里需要提到的,写出xml到文本时候,默认格式会不好看,使用OutputFormat format = OutputFormat.createPrettyPrint();后,会好看很多。

但是,不论怎么设置格式,windows上用notepad打开,总会出现黑色方块这样的难看的符号,

原因其实是,虽然标签结束或者有子标签的情况下,使用的format会根据操作系统来替换成对应的换行符号,windows下是\n\r。

但是,在注释里面的换行,dom4j里面是被看做一整段text,不受到format的影响的,因此就扩展了一下XMLWriter,重写了writeComment方法,把难看的\n都替换了,这下好看多了。

 

@Override
	protected void writeComment(String text) throws IOException {
		text=text.replaceAll("\\n", System.getProperty("line.separator"));
		super.writeComment(text);
	}

 

至此,到我自己的tomcat admin中,去创建删除修改datasource,然后commit change后,能保存到tomcat的配置文件中,如果重启tomcat,就可以看到效果了。

 

 

但是,能不能不重启tomcat就有效果呢?

 

分享到:
评论

相关推荐

    apache-tomcat-6.0.18.rar

    Apache Tomcat 6.0.18 是一个广泛使用的开源软件,它是一个符合Java Servlet和JavaServer Pages(JSP)规范的应用服务器,主要用于部署和运行Java Web应用程序。这个版本是解压缩版,意味着用户下载后无需进行编译,...

    Tomcat JDNI数据源配置详解

    在现代Web应用开发中,数据库连接管理是一项至关重要的任务。为了提高应用程序的性能和可维护性,通常会采用连接池技术来管理和复用数据库连接。Apache Tomcat作为一款广泛使用的Java应用服务器,提供了丰富的配置...

    tomcat 配置宝典

    以上是对“tomcat配置宝典”中提到的关键知识点的详细解析,涵盖了Tomcat的基本配置、集群配置、Nginx和HAProxy的使用、Memcached Session共享以及Tomcat的优化等方面。这些内容对于搭建高效稳定的Web应用环境具有...

    详解SpringBoot配置连接池

    spring.datasource.password=admin spring.datasource.driver-class-name=com.mysql.jdbc.Driver ``` Druid是一个功能丰富的JDBC组件,它的特点包括: 1. **监控性能**:Druid内置了StatFilter插件,能够详细...

    springboot+mysql+oracle+druid 双数据库进行数据同步

    首先,`SpringBoot`是一个基于Spring框架的高度模块化和简化开发的工具,它内置了Tomcat服务器和一系列默认配置,使得开发者可以快速地创建独立运行的、生产级别的基于Spring的应用。 **双数据源**:在SpringBoot中...

    AlwaysInMySelf-SpringBoot-master.zip

    - 数据库设计:包括新闻分类、新闻详情、用户管理等多个表,可能需要涉及的关系有分类与新闻的一对多关系,用户与新闻的多对多关系等。 - RESTful API设计:为前后端分离,需要设计一套清晰、符合REST原则的API...

    springboot整合mybatis+activemq(activemq可以去官网下载 )

    本文将深入探讨如何将这三个技术整合到一个项目中,以便构建高效、可扩展的微服务架构。 首先,Spring Boot是Spring框架的一个扩展,它提供了快速开发新Spring应用的能力。通过内嵌Tomcat或Jetty服务器,自动配置...

    使用lucenesolr搭建Oracle数据库全文搜索服务.docx

    - **Oracle数据库**: 是一款关系型数据库管理系统,广泛应用于企业级应用中。 #### 二、环境准备 根据文档描述,本案例涉及的环境配置包括: - **Solr版本**: 3.6.1 (考虑到项目服务器使用的JDK版本为1.5) - **...

    基于SpringBoot + Mybatis + MySQL实现文件系统

    【SpringBoot + Mybatis + MySQL实现文件系统】 在IT领域,构建一个文件系统通常涉及到后端服务、数据库管理和...在实际开发中,还需要考虑性能优化、错误处理、日志记录等多个方面,以确保系统的稳定性和可扩展性。

    Spring-Boot1.52 SpringSecurity4 Spring Data Jpa 整合例子

    **Spring Data JPA** 是 Spring 家族中的一个重要成员,用于简化基于 Java Persistence API (JPA) 的数据访问层(DAO)的开发工作。它提供了一种简单的方法来定义和实现 CRUD 操作,而无需编写复杂的 SQL 语句或手动...

    hibernate配置数据库连接池的三种方法

    在软件开发中,数据库连接池是一种重要的资源管理工具,它能显著提高数据库操作的效率和性能。连接池通过预先创建并维护一定数量的数据库连接,使得应用程序在需要时可以直接获取,而不是每次都进行数据库连接的建立...

    中文 Spring Boot 参考指南

    2. **Spring Boot Admin**:一个独立的应用,可以用来可视化管理和监控 Spring Boot 应用。 **九、持续集成与部署** 1. **Maven 插件**:Spring Boot 提供了 Maven 插件,可以打包成可执行的 JAR 或 WAR 文件。 2. ...

    MyEclipse 搭建SSH框架 笔记

    - 输入数据源在Spring配置文件中的Bean ID,例如`dataSource`。 - 选择刚刚配置好的MySQL驱动,MyEclipse会自动填充其他信息。 - 取消CreateSessionFactory class选项,点击Finish。 #### 四、进一步操作 - **逆向...

    Spring Boot使用和配置Druid

    Druid作为一款高性能的数据库连接池,被广泛应用于各种项目中,它提供了丰富的监控和扩展能力。本篇将详细介绍如何在Spring Boot中集成和配置Druid。 首先,我们需要在项目的`pom.xml`文件中引入Druid的依赖包。...

    springbootmybatisplus.zip

    MyBatisPlus是对MyBatis的轻量级扩展,提供了诸如插入、更新、删除、查询等基本操作,还支持条件构造、分页、自定义SQL、关联查询等功能,极大地减少了开发者编写SQL的负担。它简化了MyBatis的使用,使得数据库操作...

    web.xml详细说明

    - **作用**:定义Web应用的名称,通常用于在开发工具或管理控制台中展示。 - **示例**: ```xml &lt;display-name&gt;TomcatExample ``` 2. **`&lt;description&gt;`** - **作用**:提供关于Web应用的描述信息,便于管理...

    ssh(三大框架)集成

    SSH框架,即Struts2、Spring以及Hibernate三个框架的集成,是Java Web开发中非常流行的一种解决方案。它结合了MVC架构的优势,通过Struts2进行前端控制、Spring管理业务逻辑及事务处理、Hibernate实现持久层数据存取...

    最详细的servlet配置文件说明书

    `servlet`配置文件是Java Web应用程序中的核心组成部分之一,主要用于配置应用程序的各种属性与行为。本文档旨在深入解析`web.xml`文件中的各个元素及其作用,帮助初学者更好地理解并掌握如何进行有效的配置。 ####...

    boot-spring-boot:“启动Spring Boot:스프링기”

    3. Spring Boot Admin - 第三方扩展,可以可视化地管理和监控 Spring Boot 应用。 以上就是关于启动 Spring Boot 及其相关知识点的详细介绍,包括它的核心特性、项目构建、HTML 整合、数据访问以及测试和监控等方面...

Global site tag (gtag.js) - Google Analytics