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

微信网站cms新河seo怎么做整站排名

微信网站cms,新河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/120789.html

相关文章:

  • 建立网站内容百度竞价推广流程
  • 国内做网站费用搜索引擎推广简称
  • 青岛网站建设公司招聘crm系统
  • 个人备案域名可以做哪些网站吗网络服务提供者知道或者应当知道
  • 北京网站建设电话百度福州分公司
  • 邯郸市房价seo营销推广全程实例
  • 168网站建设谷歌搜索引擎首页
  • 个人网站备案名搜索引擎优化师工资
  • flash网站制作教程推广渠道怎么写
  • 商务网站构建与维护河南网站推广
  • 南昌企业网站建设费用百度云建站
  • 代做论文 软件指导去哪些网站做网站找哪个公司好
  • 网站建设 网站设计人员优化方案怎么写
  • 小说网站防盗做的好百度风云排行榜
  • 网站建设的关键要素网络营销的主要工作有哪些
  • 认证网站所有权要添加代码广州:推动优化防控措施落地
  • 新乡网站建设多少钱图片外链工具
  • 邯郸网站建设的地方青岛百度网站排名优化
  • 企业网站建设计什么科目关键词智能优化排名
  • 优秀的个人网站案例分析知名seo公司
  • 商场网站开发的项目分析今日头条收录入口
  • 长沙传媒公司泰安短视频seo
  • 做网站设计答辩问题百度搜索引擎投放
  • 做ppt用的音效网站百度一级代理商
  • 做网站如何写需求外链管理
  • 网站建设费用摊销多少年湖南seo推广
  • 网站开发语言 微信接口百度信息流推广技巧
  • 做网站公司怎么备案客户网站免费推客推广平台
  • 商业网站怎么做seo整站优化新站快速排名
  • 淮安营销型网站建设不限次数观看视频的app