千家信息网

Java基于JNDI怎么实现读写分离

发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,这篇文章主要介绍"Java基于JNDI怎么实现读写分离",在日常操作中,相信很多人在Java基于JNDI怎么实现读写分离问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"J
千家信息网最后更新 2026年11月02日Java基于JNDI怎么实现读写分离

这篇文章主要介绍"Java基于JNDI怎么实现读写分离",在日常操作中,相信很多人在Java基于JNDI怎么实现读写分离问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"Java基于JNDI怎么实现读写分离"的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

一、JNDI数据源配置

在Tomcat的conf目录下,context.xml在其中标签中添加如下JNDI配置:

二、JNDI数据源使用

1、在普通web项目中

(1)在web.xml文件中添加如下配置(也可以不配置):

 dataSourceMaster javax.sql.DataSource  Container dataSourceSlave javax.sql.DataSource Container

三、web.xml配置

   Archetype Created Web Application         log4jConfigLocation      classpath:log4j.properties              log4jRefreshInterval      60000            CharacterEncodingFilter      org.springframework.web.filter.CharacterEncodingFilter                encoding         utf-8                     forceEncoding         true                  CharacterEncodingFilter      xiyun            xiyun      org.springframework.web.servlet.DispatcherServlet               contextConfigLocation                 classpath:conf/spring/spring-servlet.xml                  1            xiyun      *.do   

四、spring-servlet.xml配置

                                                   

五、spring-db.xml配置

                                                                                                                                                                                                                                                                                                                   classpath:conf/sqlMap/*.xml                                                                                                                              

六、log4j.properties配置

log4j.rootLogger=DEBUG, CATALINA# Define all the appenderslog4j.appender.CATALINA=org.apache.log4j.RollingFileAppenderlog4j.appender.CATALINA.File=${catalina.base}/logs/catalina.loglog4j.appender.CATALINA.Append=truelog4j.appender.CATALINA.MaxFileSize=10MBlog4j.appender.CATALINA.Encoding=UTF-8# Roll-over the log once per daylog4j.appender.CATALINA.layout = org.apache.log4j.PatternLayoutlog4j.appender.CATALINA.layout.ConversionPattern = %d [%t] %-5p %c- %m%nlog4j.appender.LOCALHOST=org.apache.log4j.RollingFileAppenderlog4j.appender.LOCALHOST.File=${catalina.base}/logs/localhost.loglog4j.appender.LOCALHOST.MaxFileSize=10MBlog4j.appender.LOCALHOST.Append=truelog4j.appender.LOCALHOST.Encoding=UTF-8log4j.appender.LOCALHOST.layout = org.apache.log4j.PatternLayoutlog4j.appender.LOCALHOST.layout.ConversionPattern = %d [%t] %-5p %c- %m%nlog4j.appender.MANAGER=org.apache.log4j.RollingFileAppenderlog4j.appender.MANAGER.File=${catalina.base}/logs/manager.loglog4j.appender.MANAGER.MaxFileSize=10MBlog4j.appender.MANAGER.Append=truelog4j.appender.MANAGER.Encoding=UTF-8log4j.appender.MANAGER.DatePattern='.'yyyy-MM-dd'.log'log4j.appender.MANAGER.layout = org.apache.log4j.PatternLayoutlog4j.appender.MANAGER.layout.ConversionPattern = %d [%t] %-5p %c- %m%nlog4j.appender.HOST-MANAGER=org.apache.log4j.RollingFileAppenderlog4j.appender.HOST-MANAGER.File=${catalina.base}/logs/host-manager.loglog4j.appender.HOST-MANAGER.MaxFileSize=10MBlog4j.appender.HOST-MANAGER.Append=truelog4j.appender.HOST-MANAGER.Encoding=UTF-8log4j.appender.HOST-MANAGER.DatePattern='.'yyyy-MM-dd'.log'log4j.appender.HOST-MANAGER.layout = org.apache.log4j.PatternLayoutlog4j.appender.HOST-MANAGER.layout.ConversionPattern = %d [%t] %-5p %c- %m%nlog4j.appender.CONSOLE=org.apache.log4j.ConsoleAppenderlog4j.appender.CONSOLE.Encoding=UTF-8log4j.appender.CONSOLE.layout = org.apache.log4j.PatternLayoutlog4j.appender.CONSOLE.layout.ConversionPattern = %d [%t] %-5p %c- %m%n# Configure which loggers log to which appenderslog4j.logger.org.apache.catalina.core.ContainerBase.[Catalina].[localhost]=INFO, LOCALHOSTlog4j.logger.org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/manager]= INFO, MANAGERlog4j.logger.org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/host-manager]= INFO, HOST-MANAGER

七、相关路由数据源切换逻辑代码

package com.xiaoxi.config;import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;import java.util.Map;public class DynamicRoutingDataSource extends AbstractRoutingDataSource {    @Override    public void setTargetDataSources(Map targetDataSources) {        super.setTargetDataSources(targetDataSources);        super.afterPropertiesSet();    }    @Override    protected Object determineCurrentLookupKey() {        return DataSourceContextHolder.getDbType();    }}
package com.xiaoxi.config;/** * 线程上下文 
* 用于保存线程本地变量DbType(用于切换数据源) * 如果是异步线程操作,需要用InheritableThreadLocal (需要保存父线程的变量) * * @see [相关类/方法](可选) * @since [产品/模块版本](可选) */public class DataSourceContextHolder { private static final ThreadLocal contextHolder = new ThreadLocal<>(); public static ThreadLocal getLocal() { return contextHolder; } private DataSourceContextHolder () {} public static String getDbType() { return contextHolder.get() == null ? DbType.MASTER.dbType : contextHolder.get().dbType; } public static void setDbType(DbType dbType) { contextHolder.set(dbType); } public static void clearDbType() { contextHolder.remove(); } public enum DbType { MASTER("Master"), SLAVE("Slave"); private String dbType; DbType(String dbType) { this.dbType = dbType; } public String getDbType() { return dbType; } }}
package com.xiaoxi.aop;import com.xiaoxi.config.DataSourceContextHolder;import org.apache.log4j.Logger;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.aspectj.lang.annotation.Pointcut;import org.springframework.core.annotation.Order;import org.springframework.stereotype.Component;/** * 数据源切面,用于在执行sql前进行读写数据源切换 
* 〈功能详细描述〉 * * @see [相关类/方法](可选) * @since [产品/模块版本](可选) */@Aspect@Order(-1)@Componentpublic class DataSourceAop { private static Logger logger = Logger.getLogger(DataSourceAop.class); @Before("execution(* com.xiaoxi.dao..*.query*(..))") public void setReadDataSourceType() { DataSourceContextHolder.setDbType(DataSourceContextHolder.DbType.MASTER); logger.debug("[DataSourceAop] DataSource Covert To SLAVE"); } @Before("execution(* com.xiaoxi.dao..*.insert*(..))" + "|| execution(* com.xiaoxi.dao..*.update*(..))" + "|| execution(* com.xiaoxi.dao..*.delete*(..))") public void setWriteDataSourceType() { DataSourceContextHolder.setDbType(DataSourceContextHolder.DbType.SLAVE); logger.debug("[DataSourceAop] DataSource Covert To MASTER"); } /** ☆☆☆☆☆ 也可以获取参数中路由字段进行切换数据源 ☆☆☆☆☆ **/ @Pointcut("execution(* com.xiaoxi.dao..*.*(..))") public void cutPoint() {} @Before(value="cutPoint()") public void setDynamicDataSource(JoinPoint point){ String className = point.getTarget().getClass().getSimpleName(); String methodName = point.getSignature().getName(); String log = "[DataSourceAop] className:%s, methodName:%s"; logger.debug(String.format(log, className, methodName)); }}

八、搭建过程中遇到的问题和解决方案

1、注入数据源dataSourceMaster和dataSourceSlave失败
spring 中jndiName配置的数据源名称和Tomcat配置文件中Resource name存在区别,并非一致,其中java:comp/env为环境,否则会报can not find jndi name …

2、Cannot create JDBC driver of class '' for connect URL 'null'

3、The requested resource is not available(404)
分析了web.xml和servlet.xml发现配置无误,注解驱动和包扫描都配置,但仍然访问不了,后发现
项目启动过程中打印的日志存在问题,如下:
2019-12-17 16:20:41,767 [RMI TCP Connection(3)-127.0.0.1] INFO org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping- Mapped "{[/userInfo],methods=[GET]}" onto public java.lang.String com.xiaoxi.controller.UserInfoController.queryUserInfoById(java.lang.String)
通过分析发现这里的请求映射,通过controller的requestMapping映射到具体方法,却丢失了方法上的requestMapping路径,后发现方法RequestMapping写法如下:

@Controller@RequestMapping("/userInfo")public class UserInfoController {    private static Logger logger =Logger.getLogger(UserInfoController.class);    @Autowired    private UserInfoService userInfoService;    @ResponseBody    @RequestMapping(name= "/queryUserInfoById", method = RequestMethod.GET)    public String queryUserInfoById(@RequestParam("id") String id){        logger.info("UserInfoController.queryUserInfoById.  id:{}" + id);        UserInfo userInfo = userInfoService.queryUserInfoById(id);        return JSON.toJSONString(userInfo);    }}

此处的RequestMapping属性name应该改为value,否则解析为空(可查看注解定义)

到此,关于"Java基于JNDI怎么实现读写分离"的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注网站,小编会继续努力为大家带来更多实用的文章!

配置 数据 数据源 方法 线程 切换 学习 问题 产品 变量 文件 更多 模块 注解 版本 路由 过程 项目 分析 帮助 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网科技公司排名 苏州找大状互联网科技有限公司 高科技互联网 A股互联网金融科技公司 互联网电商科技 鸠鸠互联网科技 互联网金融公司科技 云电互联网科技 伴你行互联网科技有限公司 互联网科技产品 昭通云南众福互联网科技有限公司 深圳市罗太互联网科技有限公司 科技赋能视角下互联网保险发展 区块链结合互联网科技 中天科技中国工业互联网 扫呗互联网科技有限公司 广东鹅鹅鹅互联网科技有限公司 恒生互联网科技趋势 北京瑞云互联网科技有限公司 高科技和互联网的现代国家 百单网互联网科技有限公司怎么样 新华互联网科技学校 互联网和科技创新 中国 科技 互联网 郑州华宇互联网科技 济南和联互联网科技有限公司 互联网科技与大数据专业 艺电能源互联网科技有限公司招聘 三亚科技创新互联网基地 杭州科技互联网公司有哪些
0