Spring结合Jboss和Jndi实现数据源外部化配置
jndi官方描述
什么是jndi
JNDI(Java Naming and Directory Interface,Java命名和目录接口)是SUN公司提供的一种标准的Java命名系统接口,JNDI提供统一的客户端API,通过不同的访问提供者接口JNDI服务供应接口(SPI)的实现,由管理者将JNDI API映射为特定的命名服务和目录系统,使得Java应用程序可以和这些命名服务和目录服务之间进行交互。目录服务是命名服务的一种自然扩展。两者之间的关键差别是目录服务中对象不但可以有名称还可以有属性(例如,用户有email地址),而命名服务中对象没有属性。
如何使用jndi创建上下文
JNDI API 定义了一个上下文, 该上下文指定在何处查找对象。初始上下文通常用作起点。在最简单的情况下, 必须使用实现所需的特定实现和额外参数创建初始上下文。初始上下文将用于查找名称。初始上下文类似于文件系统的目录树的根或顶部。
实现方案一
var contextArgs = new Hashtable<String, String>();
// 设置参数,不同的服务提供商有不同的实现
contextArgs.put( Context.INITIAL_CONTEXT_FACTORY, "com.jndiprovider.TheirContextFactory" );
// 设置url明确数据存储位置
contextArgs.put( Context.PROVIDER_URL, "jndiprovider-database" );
// 此处可以实现安全校验 等
// 创建context
Context myCurrentContext = new InitialContext(contextArgs);
// 在上行下文昭寻找对应的beanName
MyBean myBean = (MyBean) myCurrentContext.lookup("com.mydomain.MyBean");
实现方案二
// 还可以通过添加 jndi 来配置上下文对象。类路径中包含初始上下文工厂类名和提供程序 URL 的属性文件
// 仅需要创建上下文context,将会去类路径下读取配置文件
Context myCurrentContext = new InitialContext();
// 从上下文中寻找初始化完成的bean信息
MyBean myBean = (MyBean) myCurrentContext.lookup("com.mydomain.MyBean");
spring结合Jboss实现jndi注入
资源管理器连接工厂引用允许应用程序组件代码使用称为资源管理器连接工厂引用的逻辑名称引用资源工厂。**资源管理器连接工厂引用由标准部署描述符中的资源 ref 元素定义。**部署程序使用 jboss 将资源管理器连接工厂引用绑定到目标操作环境中存在的实际资源管理器连接工厂。**jboss.xml 和 jboss-web.xml **描述符
配置 jndi resource数据源
在 ${jboss_name}/standalone/configuration/standalone.xml
中配置
<datasources>
<!-- jboss 默认的数据库连接配置 -->
<datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS" enabled="true" use-java-context="true">
<connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE</connection-url>
<driver>h2</driver>
<security>
<user-name>sa</user-name>
<password>sa</password>
</security>
</datasource>
<!-- mysql 默认的数据库连接配置 -->
<datasource jndi-name="java:jboss/jdbc/sxsDB" pool-name="mysqlDSPool">
<connection-url>jdbc:mysql://localhost:3306/testdb</connection-url>
<driver>mysql</driver>
<security>
<user-name>root</user-name>
<password>123456</password>
</security>
</datasource>
<drivers>
<!-- mysql 默认的数据库驱动配置 -->
<driver name="mysql" module="com.mysql">
<xa-datasource-class>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</xa-datasource-class>
</driver>
<!-- jboss 默认的数据库驱动配置 -->
<driver name="h2" module="com.h2database.h2">
<xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
</driver>
</drivers>
</datasources>
配置modules
在 ${jboss_name}/modules/system/layers/base/com
中新增目录/mysql/main
在该目录下创建module.xml,并增加对应版本的mysql驱动jar包,如图所示:
module.xml 详细配置
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.1" name="com.mysql">
<resources>
<!-- 此处注意与对应jar版本一致 -->
<resource-root path="mysql-connector-java-5.1.38.jar"/>
</resources>
<dependencies>
<module name="javax.api"/>
<module name="javax.transaction.api"/>
</dependencies>
</module>
配置 jboss-web.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE jboss-web
PUBLIC "-//JBoss//DTD Web Application 2.3V2//EN"
"http://www.jboss.org/j2ee/dtd/jboss-web_3_2.dtd">
<jboss-web>
<context-root>/spring-webmvc-0.0.1-SNAPSHOT</context-root>
<resource-ref>
<res-ref-name>jdbc/sxsDB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<jndi-name>java:jboss/jdbc/sxsDB</jndi-name>
</resource-ref>
</jboss-web>
配置web.xml
<web-app>
<!-- JDBC DataSources (java:comp/env/jdbc) -->
<resource-ref>
<description>The default DS</description>
<res-ref-name>jdbc/sxsDB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
</web-app>
配置 maven 相关依赖
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
<!--Spring java数据库访问包,在本例中主要用于提供数据源 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<!--mysql数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
<!-- mybatis ORM框架 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.1</version>
</dependency>
<!-- fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.30</version>
</dependency>
<!-- druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.6</version>
</dependency>
配置数据库连接
/**
* @ClassName: MybatisConfiguration
* @Description: java类作用描述
* @Author: 尚先生
* @CreateDate: 2019/5/24 16:56
* @Version: 1.0
*/
@Configuration
@MapperScan("com.sxs.web.mapper")
public class MybatisConfiguration {
@Bean
public DataSource dataSource() throws ClassNotFoundException, NamingException {
// 方式一 Tomcat 实现方式
// Context initContext = new InitialContext();
// Context envContext = (Context)initContext.lookup("java:/comp/env");
// DataSource dataSource = (DataSource)envContext.lookup("jdbc/sxsDB");
// 方式一 Jboss 实现方式
// Context initContext = new InitialContext();
// DataSource dataSource = (DataSource)initContext.lookup("java:jboss/jdbc/sxsDB");
// 方式二 Tomcat 实现方式
JndiObjectFactoryBean factoryBean = new JndiObjectFactoryBean();
JndiTemplate jndiTemplate = factoryBean.getJndiTemplate();
DataSource dataSource = jndiTemplate.lookup("java:/comp/env/jdbc/sxsDB", DataSource.class);
// 方式二 Jboss 实现方式
// JndiObjectFactoryBean factoryBean = new JndiObjectFactoryBean();
// JndiTemplate jndiTemplate = factoryBean.getJndiTemplate();
// DataSource dataSource = jndiTemplate.lookup("java:jboss/jdbc/sxsDB", DataSource.class);
return dataSource;
}
@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource());
sqlSessionFactoryBean.setTypeAliasesPackage("com.sxs.web.model");
// "classpath*:sqlmap/*-mapper.xml"
sqlSessionFactoryBean.setMapperLocations(new Resource[]{});
return sqlSessionFactoryBean.getObject();
}
@Bean
public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
配置映射实体
public class Course implements Serializable {
private static final long serialVersionUID = 1848918888438459623L;
private String course_name;
private String stu_name;
private double score;
private String currentThreadName;
@Override
public String toString() {
return "Course{" +
"course_name='" + course_name + '\'' +
", stu_name='" + stu_name + '\'' +
", score=" + score +
", currentThreadName='" + currentThreadName + '\'' +
'}';
}
public String getCourse_name() {
return course_name;
}
public void setCourse_name(String course_name) {
this.course_name = course_name;
}
public String getStu_name() {
return stu_name;
}
public void setStu_name(String stu_name) {
this.stu_name = stu_name;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
public String getCurrentThreadName() {
return currentThreadName;
}
public void setCurrentThreadName(String currentThreadName) {
this.currentThreadName = currentThreadName;
}
}
配置 mapper 映射
@Mapper
@Repository
public interface CourseMapper {
@Select("select * from tb_score limit 2 offset 1")
Collection<Course> findAllCourses();
@Select("select * from tb_score limit 1 offset 1")
Course findSingleCourse();
}
配置控制器
/**
* @ClassName: CourseController
* @Description: Course数据测试
* @Author: 尚先生
* @CreateDate: 2019/5/22 17:29
* @Version: 1.0
*/
@RestController
public class CourseController {
@Autowired
private CourseMapper courseMapper;
// 配置浏览器响应数据编码格式
@GetMapping(value = "/find-all-courses",produces = {"application/json;charset=UTF-8"})
public Collection<Course> findAllCourses(){
Collection<Course> courses1 = courseMapper.findAllCourses();
for (Course course : courses1){
course.setCurrentThreadName(Thread.currentThread().getName());
}
return courses1;
}
@GetMapping(value = "/find-single-course",produces = {"application/json;charset=UTF-8"})// 配置浏览器响应数据编码格式
public String findSingleCourse(){
Course course = courseMapper.findSingleCourse();
course.setCurrentThreadName(Thread.currentThread().getName());
return JSON.toJSONString(course);
}
}
添加SQL脚本
-- 查询所有的数据库
show databases;
-- 使用testdb
use testdb;
-- 查询testdb所有的表
show tables ;
-- 建表前清除
drop table tb_score;
-- 建表语句
create table tb_score(
id bigint primary key auto_increment,
course_name varchar(20),
stu_name varchar(20),
score double
);
-- 插入数据
insert into tb_score (course_name, stu_name, score) values ('高数','尚先生',100.00);
insert into tb_score (course_name, stu_name, score) values ('英语','尚先生',80.00);
insert into tb_score (course_name, stu_name, score) values ('英语','尚小菲',100.00);
insert into tb_score (course_name, stu_name, score) values ('高数','尚小菲',90.00);
-- 查询入库数据
select *
from tb_score;
参考文章
更多优秀文章
java界的小学生
https://blog.csdn.net/shang_xs
更多Tomcat相关
Spring结合Tomcat和Jndi实现数据源外部化配置
深入学习和理解Servlet(一)
https://blog.csdn.net/shang_xs/article/details/90371068
深入学习和理解Servlet(二)
https://blog.csdn.net/shang_xs/article/details/90376489
完整代码和相关依赖请见GitHub
https://github.com/dwyanewede/spring-boot/tree/master/spring-webmvc/src/main