当前位置: 首页 > wzjs >正文

wordpress英文版切换成中文深圳搜狗seo

wordpress英文版切换成中文,深圳搜狗seo,关于政务网站建设工作情况的总结,二级域名备案流程MyBatis 作为一款优秀的持久层框架,提供了拦截器(Interceptor)机制,允许开发者在 SQL 执行流程的关键节点插入自定义逻辑。本文将深入探讨拦截器的应用场景,并通过示例代码展示其具体实现。 1.拦截器(Inter…

MyBatis 作为一款优秀的持久层框架,提供了拦截器(Interceptor)机制,允许开发者在 SQL 执行流程的关键节点插入自定义逻辑。本文将深入探讨拦截器的应用场景,并通过示例代码展示其具体实现。

1.拦截器(Interceptor)概述

在 MyBatis 中,是通过实现 `Interceptor` 接口来拦截特定的方法调用。MyBatis 允许拦截的方法包括:

1. Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)

2. ParameterHandler (getParameterObject, setParameters)

3. ResultSetHandler (handleResultSets, handleOutputParameters)

4. StatementHandler (prepare, parameterize, batch, update, query)

拦截器的执行顺序如下:

Executor -> StatementHandler -> ParameterHandler -> ResultSetHandler

2.应用场景与示例

2.1 SQL 性能监控与日志记录

场景:记录 SQL 执行时间,监控慢查询,辅助性能优化。

示例代码

@Intercepts({@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})
})
public class PerformanceInterceptor implements Interceptor {private static final Logger logger = LoggerFactory.getLogger(PerformanceInterceptor.class);@Overridepublic Object intercept(Invocation invocation) throws Throwable {long startTime = System.currentTimeMillis();try {// 执行原始方法return invocation.proceed();} finally {long endTime = System.currentTimeMillis();long executeTime = endTime - startTime;// 获取 SQL 信息MappedStatement ms = (MappedStatement) invocation.getArgs()[0];String sqlId = ms.getId();BoundSql boundSql = ms.getBoundSql(invocation.getArgs()[1]);String sql = boundSql.getSql();// 记录 SQL 执行时间
            logger.info("SQL executed in {}ms: {}", executeTime, sql);// 超过 1 秒的 SQL 视为慢查询if (executeTime > 1000) {
                logger.warn("Slow SQL detected ({}ms): {}", executeTime, sqlId);}}}@Overridepublic Object plugin(Object target) {return Plugin.wrap(target, this);}@Overridepublic void setProperties(Properties properties) {// 设置属性}
}

配置方式

<plugins>
    <plugin interceptor="com.example.interceptor.PerformanceInterceptor"/>
</plugins>

2.2 自动分页处理

场景:简化分页查询,自动生成分页 SQL。

示例代码

@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})
})
public class PaginationInterceptor implements Interceptor {@Overridepublic Object intercept(Invocation invocation) throws Throwable {StatementHandler statementHandler = (StatementHandler) invocation.getTarget();MetaObject metaObject = SystemMetaObject.forObject(statementHandler);// 获取原始 SQLBoundSql boundSql = statementHandler.getBoundSql();String originalSql = boundSql.getSql();// 获取参数对象Object parameterObject = boundSql.getParameterObject();// 判断是否为分页查询if (parameterObject instanceof Map) {Map<?, ?> paramMap = (Map<?, ?>) parameterObject;if (paramMap.containsKey("pageNum") && paramMap.containsKey("pageSize")) {int pageNum = (int) paramMap.get("pageNum");int pageSize = (int) paramMap.get("pageSize");// 生成分页 SQL(这里以 MySQL 为例)String paginatedSql = originalSql + " LIMIT " + (pageNum - 1) * pageSize + ", " + pageSize;// 修改 SQL
                metaObject.setValue("boundSql.sql", paginatedSql);}}return invocation.proceed();}@Overridepublic Object plugin(Object target) {return Plugin.wrap(target, this);}@Overridepublic void setProperties(Properties properties) {// 设置属性}
}

使用方式

Map<String, Object> params = new HashMap<>();
params.put("username", "test");
params.put("pageNum", 1);
params.put("pageSize", 10);List<User> users = userMapper.selectByParams(params);

2.3 多租户数据隔离

场景:在多租户系统中,自动为 SQL 添加租户条件,实现数据隔离。

示例代码

@Intercepts({@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})
})
public class TenantInterceptor implements Interceptor {// 从 ThreadLocal 获取当前租户 IDprivate static final ThreadLocal<String> TENANT_ID = new ThreadLocal<>();public static void setTenantId(String tenantId) {
        TENANT_ID.set(tenantId);}public static void clearTenantId() {
        TENANT_ID.remove();}@Overridepublic Object intercept(Invocation invocation) throws Throwable {MappedStatement ms = (MappedStatement) invocation.getArgs()[0];Object parameter = invocation.getArgs()[1];// 获取当前租户 IDString tenantId = TENANT_ID.get();if (tenantId != null) {// 获取 BoundSqlBoundSql boundSql = ms.getBoundSql(parameter);String sql = boundSql.getSql();// 为 SQL 添加租户条件(简化示例,实际应用需更复杂的 SQL 解析)if (!sql.toLowerCase().contains("where")) {
                sql += " WHERE tenant_id = '" + tenantId + "'";} else {
                sql += " AND tenant_id = '" + tenantId + "'";}// 创建新的 BoundSqlBoundSql newBoundSql = new BoundSql(ms.getConfiguration(), sql, 
                    boundSql.getParameterMappings(), boundSql.getParameterObject());// 处理附加参数for (String key : boundSql.getParameterMappings().keySet()) {if (boundSql.hasAdditionalParameter(key)) {
                    newBoundSql.setAdditionalParameter(key, boundSql.getAdditionalParameter(key));}}// 创建新的 MappedStatementMappedStatement newMs = copyFromMappedStatement(ms, new BoundSqlSqlSource(newBoundSql));// 替换原始参数
            invocation.getArgs()[0] = newMs;}return invocation.proceed();}@Overridepublic Object plugin(Object target) {return Plugin.wrap(target, this);}@Overridepublic void setProperties(Properties properties) {// 设置属性}// 辅助方法:复制 MappedStatementprivate MappedStatement copyFromMappedStatement(MappedStatement ms, SqlSource newSqlSource) {MappedStatement.Builder builder = new MappedStatement.Builder(ms.getConfiguration(), 
                ms.getId(), newSqlSource, ms.getSqlCommandType());
        builder.resource(ms.getResource());
        builder.fetchSize(ms.getFetchSize());
        builder.statementType(ms.getStatementType());
        builder.keyGenerator(ms.getKeyGenerator());if (ms.getKeyProperties() != null && ms.getKeyProperties().length > 0) {
            builder.keyProperty(ms.getKeyProperties()[0]);}
        builder.timeout(ms.getTimeout());
        builder.parameterMap(ms.getParameterMap());
        builder.resultMaps(ms.getResultMaps());
        builder.resultSetType(ms.getResultSetType());
        builder.cache(ms.getCache());
        builder.flushCacheRequired(ms.isFlushCacheRequired());
        builder.useCache(ms.isUseCache());return builder.build();}// 辅助类:实现 SqlSource 接口private static class BoundSqlSqlSource implements SqlSource {private BoundSql boundSql;public BoundSqlSqlSource(BoundSql boundSql) {this.boundSql = boundSql;}@Overridepublic BoundSql getBoundSql(Object parameterObject) {return boundSql;}}
}

使用方式

try {// 设置当前租户 IDTenantInterceptor.setTenantId("tenant_001");// 执行数据库操作,自动添加租户条件List<User> users = userService.getUsers();
} finally {// 清除租户 IDTenantInterceptor.clearTenantId();
}

2.4 自动填充公共字段

场景:自动填充创建时间、更新时间、创建人、更新人等公共字段。

示例代码

@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})
})
public class AutoFillInterceptor implements Interceptor {@Overridepublic Object intercept(Invocation invocation) throws Throwable {MappedStatement ms = (MappedStatement) invocation.getArgs()[0];Object parameter = invocation.getArgs()[1];// 只处理插入和更新操作if (ms.getSqlCommandType() == SqlCommandType.INSERT || 
            ms.getSqlCommandType() == SqlCommandType.UPDATE) {// 获取当前用户信息(示例中简化获取方式)String currentUser = getCurrentUser();Date currentTime = new Date();// 使用反射设置公共字段if (parameter != null) {MetaObject metaObject = SystemMetaObject.forObject(parameter);// 插入操作填充创建时间和创建人if (ms.getSqlCommandType() == SqlCommandType.INSERT) {if (metaObject.hasSetter("createTime")) {
                        metaObject.setValue("createTime", currentTime);}if (metaObject.hasSetter("createBy")) {
                        metaObject.setValue("createBy", currentUser);}}// 更新操作填充更新时间和更新人if (metaObject.hasSetter("updateTime")) {
                    metaObject.setValue("updateTime", currentTime);}if (metaObject.hasSetter("updateBy")) {
                    metaObject.setValue("updateBy", currentUser);}}}return invocation.proceed();}@Overridepublic Object plugin(Object target) {return Plugin.wrap(target, this);}@Overridepublic void setProperties(Properties properties) {// 设置属性}// 获取当前用户信息private String getCurrentUser() {// 实际应用中可能从 Session 或 SecurityContext 中获取return "system";}
}

3.过滤器与拦截器的区别

虽然在 MyBatis 中过滤器和拦截器指的是同一概念,但在其他框架(如 Servlet、Spring)中,它们有明显区别:

特性

MyBatis 拦截器

Servlet 过滤器

Spring 拦截器

拦截对象

Executor、StatementHandler 等

HTTP 请求和响应

Spring MVC 处理器

应用场景

SQL 增强、性能监控、参数处理等

请求预处理、编码转换、权限控制等

请求预处理、日志记录、性能监控等

配置方式

实现 Interceptor 接口并注册

实现 Filter 接口并配置

实现 HandlerInterceptor 接口

执行顺序

按注册顺序执行

按配置顺序执行

按注册顺序执行

4.最佳实践

1. 谨慎使用:拦截器会影响所有被拦截的方法,过度使用可能导致代码复杂度增加。

2. 性能考虑:避免在拦截器中执行耗时操作,特别是在高并发场景下。

3. 参数验证:在拦截器中进行参数验证时,确保不影响原有业务逻辑。

4. 异常处理:拦截器中应捕获并处理异常,避免影响主流程。

5. 明确拦截范围:通过 @Signature 精确定义拦截的方法,避免不必要的拦截。

6. 线程安全:确保拦截器是线程安全的,避免共享状态。

5.总结

MyBatis 的过滤器(拦截器)机制为开发者提供了强大的扩展点,可以在不修改原有代码的情况下增强 SQL 执行流程。通过合理使用拦截器,可以实现 SQL 性能监控、自动分页、多租户隔离、公共字段自动填充等功能,提高开发效率和系统可维护性。

在实际应用中,需要根据具体场景选择合适的拦截点,并遵循最佳实践,确保拦截器的正确性和性能。

http://www.dtcms.com/wzjs/284156.html

相关文章:

  • wordpress 资源主题seo流量排名软件
  • 如何做网站美工石家庄百度关键词搜索
  • wordpress adams主题曹操博客seo
  • 网站开发的常用流程河南网站优化公司哪家好
  • 做网站有几个软件公司官网怎么制作
  • jsp网站开发四酷全书软文广告是什么
  • 惠州网站建设 鑫谷歌搜索引擎seo
  • 长沙做网站微联讯点很好什么是优化设计
  • ie 10 常用网站seo排名助手
  • 怎么做网站拍卖的那种网店推广方案策划书
  • 免费建设微网站制作网页广告调词平台
  • 旅游网站html模板核心关键词和长尾关键词
  • 域名和网站空间相互做解析百度seo查询收录查询
  • 政府网站建设政策媒体公关公司
  • 如何做网站防劫持抖音排名优化
  • 济南网站建设网络公司郑州百度推广开户
  • 电子政务网站建设流程深圳市seo上词多少钱
  • 重庆公安网站备案电商代运营公司
  • 平台网站做等级保护测评小程序
  • 有织梦后台系统怎么做网站新平台推广赚钱
  • 企业网站为什么要备案360优化大师
  • 山东网站建设价格成都新闻今日最新消息
  • 广州自助网站推广制作seo排名如何优化
  • 幼儿园网站建设的好处济南网站优化公司哪家好
  • 郑州网络科技公司有哪些seo关键词排名优化软件怎么选
  • 五大建设seo网站结构优化的方法
  • 如何在工商局网站上做网登常见的网络营销方式有哪几种
  • 商务网站要怎么做哪家网站推广好
  • 制作视频的软件app免费下载广东seo点击排名软件哪家好
  • 网站建设费用 百度文库百度收录网站多久