【SpringBoot:实现上下文管理】

SpringBoot实现上下文管理

简述

在日常开发中,经常会用到上下文来实现一些变量的托管和程序逻辑的实现(如收集接口调用信息、记录日志等,会通过上下文获取用户信息、业务变量等),本文详细介绍了如何实现和使用上下文。
本文的上下文环境中用户信息的赋值在用户登录验证中实现,可参考文章:
SpringBoot实现登录拦截
上下文管理的实现步骤如下:

  • 定义上下文变量所保存的内容
  • 定义上下文管理工具

原理

SpringBoot在响应一个请求时,会创建一个线程,而实现上下文的管理,可以通过创建线程本地变量来实现,这样的话,多个请求的响应之间就不会发生上下文的冲突。
管理的线程变量的方式有很多,比较常见的有:

  • synchronized(锁)
  • ThreadLocal

这里我们使用的是ThreadLocal,因为synchronized(锁)是采用时间换空间的方式,多个线程(请求响应)之间共用一份变量,当一个线程访问时,其他线程进行等待,这样不仅会造成多线程的效率下降,而且一个线程改变了变量的值,其他线程读取到的就是改变后的值。
而ThreadLocal是为每一个线程提供了变量副本,每个线程使用自己的副本,无论对变量进行什么操作,都不会影响其他线程的变量。
所以我们的上下文管理的实现方式就是,将上下文注册到ThreadLocal中,通过我们的工具类进行赋值和读取。

定义上下文变量

所定义的上下文变量应具有高兼容性,支持存放比较复杂的数据,且方便读取。一般的实现方式是放置一个Map<String, Object>来实现。
本文所实现的上下文,可存放变量,以及用户信息,我所使用的工程为了区分一般变量和业务变量,定义了两个存放变量的Map,一般使用一个Map就可以。
定义上下文管理接口类,具体的管理逻辑在实现类中编写,上下文的具体变量也在实现类中编写。

package com.project.base.context;

import java.io.Serializable;
import java.util.Map;

public interface BaseContext extends Serializable {

	// 项目中定义的用户实体类
    BaseCurrentUser getBaseCurrentUser();

	// 对用户进行赋值的方法
    void setBaseCurrentUser(BaseCurrentUser baseCurrentUser);

	// 获取变量
    Object getProperty(Object var);

	// 添加变量
    void addProperty(Object varKey, Object varValue);

	// 移出变量
    void removeProperty(Object var);

	// 获取所有变量
    Map<Object, Object> getProperties();

	// 初始化变量
    void setProperties(Map<Object, Object> map);

	// 移出所有变量
    void removeAllProperties();

	// 添加业务变量
    void addBusiProperty(Object busiVarKey, Object busiVarValue);

	// 获取业务变量
    Object getBusiProperty(Object busiVarKey);

	// 获取所有业务变量
    Map<Object, Object> getBusiProperties();

	// 初始化业务变量
    void setBusiProperties(Map<Object, Object> map);

}

实现类:

package com.project.base.context.impl;

import com.project.base.context.BaseContext;
import com.project.base.context.BaseCurrentUser;
import lombok.ToString;

import java.util.HashMap;
import java.util.Map;

@ToString
public class BaseContextImpl implements BaseContext {

    private static final long serialVersionUID = 8383356012441014698L;
    // 用户类
    private BaseCurrentUser baseCurrentUser = new BaseCurrentUser();
    // 变量
    private Map<Object, Object> properties = new HashMap<>();
    // 业务变量
    private Map<Object, Object> busiProperties = new HashMap<>();

    public BaseContextImpl() {}

    @Override
    public BaseCurrentUser getBaseCurrentUser() {
        return this.baseCurrentUser;
    }

    @Override
    public void setBaseCurrentUser(BaseCurrentUser baseCurrentUser) {
        this.baseCurrentUser = baseCurrentUser;
    }

    @Override
    public Object getProperty(Object var) {
        return this.properties.get(var);
    }

    @Override
    public void addProperty(Object varKey, Object varValue) {
        this.properties.put(varKey, varValue);
    }

    @Override
    public void removeProperty(Object var) {
        this.properties.remove(var);
    }

    @Override
    public Map<Object, Object> getProperties() {
        return this.properties;
    }

    @Override
    public void setProperties(Map<Object, Object> map) {
        this.properties = map;
    }

    @Override
    public void removeAllProperties() {
        this.properties.clear();
    }

    @Override
    public void addBusiProperty(Object busiVarKey, Object busiVarValue) {
        this.busiProperties.put(busiVarKey, busiVarValue);
    }

    @Override
    public Object getBusiProperty(Object busiVarKey) {
        return this.busiProperties.get(busiVarKey);
    }

    @Override
    public Map<Object, Object> getBusiProperties() {
        return this.busiProperties;
    }

    @Override
    public void setBusiProperties(Map<Object, Object> map) {
        this.busiProperties = map;
    }
}

定义上下文变量管理类

定义一个类,统一管理

package com.project.base.context;

import com.project.base.context.impl.BaseContextImpl;

public class BaseContextHolder {

    // 创建一个线程变量,类型为BaseContext
    private static final ThreadLocal<BaseContext> contextHolder = new ThreadLocal<>();

    public BaseContextHolder() {

    }

    // 设置变量
    public static void setContext(BaseContext baseContext) { contextHolder.set(baseContext); }

    public static BaseContext getContext() {
        BaseContext obj = contextHolder.get();
        if (obj == null) {
            // 如果为空就创建一个新的
            obj = new BaseContextImpl();
            setContext((BaseContext) obj);
        }

        return (BaseContext) obj;
    }

}

这样在程序中就能通过BaseContextHolder来获取和配置上下文变量了,使用的方式如下:

BaseContext baseContext = BaseContextHolder.getContext();
baseContext.getBaseCurrentUser();
baseContext.getProperty(keyName);
baseContext.getProperties();
baseContext.getBusiProperties();
...
// 在BaseContextImpl中实现的方法都可以使用
Spring Boot上下文Spring Boot应用程序的核心部分,它负责管理应用程序的生命周期并提供各种功能。Spring Boot上下文包括应用程序上下文和Web应用程序上下文两个部分。 应用程序上下文Spring框架的核心部分,它负责管理应用程序中的所有bean。它通过读取应用程序中的配置文件来创建bean,并将它们组装成一个完整的应用程序。应用程序上下文还提供了各种功能,例如国际化支持、事件处理、资源加载等。 Web应用程序上下文是应用程序上下文的子集,它负责管理Web应用程序中的所有bean。它还提供了与Web应用程序相关的功能,例如处理HTTP请求、处理静态资源、处理模板等。 以下是一个简单的Spring Boot应用程序示例,它演示了如何创建和使用应用程序上下文和Web应用程序上下文: ```java @SpringBootApplication public class MyApp { public static void main(String[] args) { SpringApplication.run(MyApp.class, args); } } @RestController public class MyController { @Autowired private MyService myService; @GetMapping("/hello") public String hello() { return myService.getMessage(); } } @Service public class MyService { public String getMessage() { return "Hello World!"; } } ``` 在这个示例中,@SpringBootApplication注解表示这是一个Spring Boot应用程序。MyApp类的main方法启动了应用程序,并创建了应用程序上下文和Web应用程序上下文。MyController类是一个REST控制器,它处理HTTP GET请求并返回一个字符串。MyService类是一个简单的服务类,它返回一个字符串。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值