2024-08-28



-- 创建数据库
CREATE DATABASE mydatabase;
 
-- 创建数据库管理员用户
CREATE USER myuser WITH PASSWORD 'mypassword';
 
-- 授予管理员用户对mydatabase的所有权限
GRANT ALL PRIVILEGES ON DATABASE mydatabase TO myuser;
 
-- 为数据库创建只读用户
CREATE USER myreaduser WITH PASSWORD 'myreadpassword';
 
-- 授予只读用户连接和查询权限
GRANT CONNECT ON DATABASE mydatabase TO myreaduser;
GRANT USAGE ON SCHEMA public TO myreaduser;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO myreaduser;

这段代码首先创建了一个新的数据库mydatabase,接着创建了一个数据库管理员用户myuser,并为其设置了密码。然后,授予myusermydatabase的所有权限。最后,创建了一个只读用户myreaduser,并授予其连接数据库和查询public schema中所有表的权限。这样,myreaduser就可以连接到数据库并查询信息,但不能做出修改。

2024-08-28

MongoDB的复制集和分片是两种不同的技术,用于处理不同的数据量和请求负载。

复制集:

复制集是一组维护相同数据副本的MongoDB服务器。提供高可用性和数据冗余,是MongoDB的基础特性之一。




# 启动复制集
mongod --port 27017 --dbpath /srv/mongodb/db0 --replSet rs0
mongod --port 27018 --dbpath /srv/mongodb/db1 --replSet rs0
mongod --port 27019 --dbpath /srv/mongodb/db2 --replSet rs0

# 初始化复制集
mongo --port 27017
> rs.initiate(
  {
    _id: "rs0",
    members: [
      { _id: 0, host: "localhost:27017" },
      { _id: 1, host: "localhost:27018" },
      { _id: 2, host: "localhost:27019" }
    ]
  }
)

分片:

分片是将数据库分散到多个服务器上,用于处理大量数据和高吞吐量的技术。




# 启动分片集群
mongod --port 27017 --dbpath /srv/mongodb/shard0 --shardsvr
mongod --port 27027 --dbpath /srv/mongodb/shard1 --shardsvr
mongod --port 27037 --dbpath /srv/mongodb/shard2 --shardsvr

# 配置复制集
mongo --port 27017
> sh.status()

# 分片配置
sh.enableSharding("mydb")
sh.shardCollection("mydb.mycollection", {"myKey": 1})

复制集用于数据的冗余和高可用性,而分片用于数据的分布和性能优化。根据实际需求选择合适的技术。

2024-08-28



# 导入Django Autocomplete Light的必要组件
from autocomplete_light import shortcuts as autocomplete_light
 
# 注册模型Admin,以支持Autocomplete功能
@autocomplete_light.register('MyModelAdmin')
class MyModelAutocomplete(autocomplete_light.AutocompleteGenericBase):
    # 指定模型
    model = MyModel
    # 指定查询集的过滤器
    search_fields = ['field1__icontains', 'field2__icontains']
    # 指定在Autocomplete结果中显示的字段
    attrs = {'placeholder': 'Search for a mymodel...'}
 
# 注册函数,用于自定义Autocomplete结果列表的外观
@autocomplete_light.register('forward')
class ForwardAutocomplete(autocomplete_light.AutocompleteGenericBase):
    # 定义模型
    model = Forward
    # 定义搜索字段
    search_fields = ['name__icontains']
    # 定义额外的选项
    attrs = {'placeholder': 'Search for a forward...'}
 
# 注册函数,用于自定义Autocomplete结果列表的外观
@autocomplete_light.register('backward')
class BackwardAutocomplete(autocomplete_light.AutocompleteGenericBase):
    model = Backward
    search_fields = ['name__icontains']
    attrs = {'placeholder': 'Search for a backward...'}

这个示例代码展示了如何在Django项目中使用Autocomplete Light库来增强Django Admin的自动完成功能。代码中定义了三个Autocomplete类,每个类对应一个Django模型,并指定了搜索字段和其他选项。这样,在Django Admin界面中使用这些模型时,用户可以通过输入来过滤和自动完成相关记录。

2024-08-28

在Spring Boot中使用Redis实现分布式锁通常涉及到RedisTemplateStringRedisTemplate。以下是一个简单的示例,展示了在Spring Boot应用中如何在事务提交后释放Redis分布式锁:




import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
 
@RestController
public class DistributedLockController {
 
    @Autowired
    private StringRedisTemplate redisTemplate;
 
    private static final String LOCK_KEY = "distributed_lock";
 
    @GetMapping("/acquireLock")
    public String acquireLock() {
        boolean locked = tryLock(LOCK_KEY);
        if (locked) {
            // 模拟业务逻辑处理
            doBusinessLogic();
            // 释放锁
            unlock(LOCK_KEY);
            return "Lock released";
        } else {
            return "Failed to acquire lock";
        }
    }
 
    private boolean tryLock(String key) {
        // 尝试获取锁,使用 SET key value NX PX milliseconds 命令
        Boolean locked = redisTemplate.opsForValue().setIfAbsent(key, "lock_value", 10, TimeUnit.SECONDS);
        return Boolean.TRUE.equals(locked);
    }
 
    private void unlock(String key) {
        // 释放锁,删除键
        redisTemplate.delete(key);
    }
 
    @Transactional
    private void doBusinessLogic() {
        // 事务性业务逻辑
    }
}

在这个例子中,tryLock 方法使用了 StringRedisTemplateopsForValue().setIfAbsent() 方法尝试获取锁,该方法在Redis中对应的是 SET key value NX PX milliseconds 命令,其中 NX 表示只在键不存在时设置值,PX 表示设置键的过期时间。

unlock 方法简单地使用了 StringRedisTemplatedelete() 方法释放锁,即删除键。

acquireLock 方法中,我们首先尝试获取锁,如果成功,则执行业务逻辑,在业务逻辑执行完毕后,无论成功还是回滚,都会释放锁。这里假设了业务逻辑在一个独立的方法 doBusinessLogic() 中,并用 @Transactional 注解标记,以确保业务逻辑在事务的上下文中执行。

请注意,这个例子中锁的过期时间设置为10秒,实际使用时应该根据业务场景适当调整锁的超时时间。同时,在高并发情况下,可能需要使用更复杂的算法来确保锁的安全性和效率。

2024-08-28

在Django中使用JWT(JSON Web Tokens),可以选择djangorestframework-simplejwt库,这是一个基于PyJWT的库,专门用于Django REST框架中提供Token认证服务。

首先,需要安装这个库:




pip install djangorestframework-simplejwt

然后,在Django的settings.py文件中配置:




# settings.py
 
# Simple JWT
import datetime
 
SIMPLE_JWT = {
    'ACCESS_TOKEN_LIFETIME': datetime.timedelta(minutes=5),
    'REFRESH_TOKEN_LIFETIME': datetime.timedelta(days=1),
    'ROTATE_REFRESH_TOKENS': False,
    'BLACKLIST_AFTER_ROTATION': True,
 
    'ALGORITHM': 'HS256',
    'SIGNING_KEY': SECRET_KEY,
    'VERIFYING_KEY': None,
 
    'AUTH_HEADER_TYPES': ('Bearer',),
    'USER_ID_FIELD': 'id',
    'USER_ID_CLAIM': 'user_id',
 
    'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
    'TOKEN_TYPE_CLAIM': 'token_type',
 
    'JTI_CLAIM': 'jti',
 
    'SLIDING_TOKEN_REFRESH_EXP_CLAIM': 'refresh_exp',
    'SLIDING_TOKEN_LIFETIME': datetime.timedelta(minutes=5),
    'SLIDING_TOKEN_REFRESH_LIFETIME': datetime.timedelta(days=1),
}

接下来,在urls.py中添加Token的路由:




# urls.py
 
from django.urls import path, include
from rest_framework_simplejwt.views import (
    TokenObtainPairView,
    TokenRefreshView,
)
 
urlpatterns = [
    # ...
    path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
    path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
]

最后,在需要认证的视图中使用jwt_required装饰器:




# views.py
 
from rest_framework_simplejwt.decorators import jwt_required
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework import status
 
@jwt_required
def get_current_user(request):
    user = request.user
    return Response({'email': user.email, 'id': user.id}, status=status.HTTP_200_OK)

使用TokenObtainPairView.as_view()TokenRefreshView.as_view()可以提供登录和刷新Token的接口。使用jwt_required装饰器可以保护视图,要求请求提供有效的Token。

2024-08-28

在PostgreSQL中,可以使用CAST操作符或者::语法来进行数据类型的转换。

例如,假设你有一个整数类型的列int_column,你想将其转换为文本类型:




SELECT CAST(int_column AS TEXT) FROM your_table;

或者使用::语法:




SELECT int_column::TEXT FROM your_table;

如果你想将文本类型的列text_column转换为整数类型,并且文本列中的值都是可以转换为整数的数字字符串:




SELECT CAST(text_column AS INTEGER) FROM your_table;

或者:




SELECT text_column::INTEGER FROM your_table;

请注意,在进行类型转换时,确保转换是合法的,否则会引发错误。例如,尝试将非数字字符串转换为整数将会失败。

2024-08-28

在Spring Boot项目中整合Druid数据库连接池,首先需要添加Druid的依赖,然后配置Druid数据库连接池。

  1. 添加Druid依赖到pom.xml文件:



<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.2.8</version>
</dependency>
  1. application.propertiesapplication.yml中配置Druid连接池:



# application.properties
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.url=jdbc:mysql://localhost:3306/yourdb
spring.datasource.username=root
spring.datasource.password=yourpassword
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
 
# 初始化大小,最小,最大
spring.datasource.druid.initial-size=5
spring.datasource.druid.min-idle=5
spring.datasource.druid.max-active=20
 
# 配置获取连接等待超时的时间
spring.datasource.druid.max-wait=60000
 
# 配置间隔多久进行一次检测,检测需要关闭的空闲连接,单位是毫秒
spring.datasource.druid.time-between-eviction-runs-millis=60000
 
# 配置一个连接在池中最小生存的时间,单位是毫秒
spring.datasource.druid.min-evictable-idle-time-millis=300000
 
# 用来检测连接是否有效的SQL,必须是一个查询语句
spring.datasource.druid.validation-query=SELECT 1 FROM DUAL
 
# 配置一个连接TestWhileIdle的检测时间间隔,单位是毫秒
spring.datasource.druid.validation-query-timeout=1000
 
# 配置监控统计拦截的filters
spring.datasource.druid.filters=stat,wall
 
# WebStatFilter配置
spring.datasource.druid.web-stat-filter.enabled=true
spring.datasource.druid.web-stat-filter.url-pattern=/*
spring.datasource.druid.web-stat-filter.exclusions=*.js,*.gif,*.jpg,*.bmp,*.css,*.ico,/druid/*
 
# StatViewServlet配置
spring.datasource.druid.stat-view-servlet.enabled=true
spring.datasource.druid.stat-view-servlet.url-pattern=/druid/*
spring.datasource.druid.stat-view-servlet.reset-enable=false
spring.datasource.druid.stat-view-servlet.login-username=admin
spring.datasource.druid.stat-view-servlet.login-password=admin
spring.datasource.druid.stat-view-servlet.allow=127.0.0.1
spring.datasource.druid.stat-view-servlet.deny=192.168.1.1
  1. 确保你的Spring Boot应用中已经开启了Druid的自动配置。

以上步骤完成后,Druid数据库连接池将会被自动配置并启动,你可以通过访问http://localhost:8080/druid/来查看Druid提供的监控信息。

2024-08-28



// 假设我们有一个名为 'myCollection' 的集合,并且我们想要对其中的文档执行 Map-Reduce 操作。
 
// 定义 Map 函数
var map = function() {
  emit(this.category, this.price);
};
 
// 定义 Reduce 函数
var reduce = function(key, values) {
  return values.reduce((total, value) => total + value, 0);
};
 
// 执行 Map-Reduce 操作
db.myCollection.mapReduce(
  function() {
    // Map 函数的代码
    map.apply(this);
  },
  function(key, values) {
    // Reduce 函数的代码
    return reduce(key, values);
  },
  {
    out: 'mapReduceResults' // 输出结果集合的名称
  }
);
 
// 查询 Map-Reduce 的结果
var results = db.mapReduceResults.find();
results.forEach(printjson);

这段代码首先定义了 Map 和 Reduce 函数,然后在集合 myCollection 上调用 mapReduce 方法进行操作,并将结果输出到 mapReduceResults 集合中。最后,遍历并打印这些结果。这个例子假设每个文档有 categoryprice 字段,并且我们想要按 category 字段来汇总 price 的和。

2024-08-28

Spring Boot 支持使用 Undertow 作为服务器,而不是默认的 Tomcat。要使用 Undertow,你需要将 spring-boot-starter-undertow 依赖添加到你的项目中。

以下是如何在 Spring Boot 项目中使用 Undertow 的步骤:

  1. 在你的 pom.xml 文件中添加 spring-boot-starter-undertow 依赖。



<dependencies>
    <!-- 其他依赖 -->
 
    <!-- 添加 Undertow 依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-undertow</artifactId>
    </dependency>
 
    <!-- 其他依赖 -->
</dependencies>
  1. 确保你的 pom.xml 中没有包含 Tomcat 的依赖,比如 spring-boot-starter-web 中的 Tomcat 依赖应该被排除。
  2. 确保你的 application.propertiesapplication.yml 中没有配置与 Tomcat 相关的属性,因为 Undertow 不使用这些属性。
  3. 启动你的 Spring Boot 应用,确保控制台日志输出显示 Undertow 作为服务器正在使用。

以下是一个简单的示例,演示如何在 Spring Boot 项目中包含 Undertow:




<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <exclusions>
            <!-- 排除 Tomcat 依赖 -->
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-tomcat</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
 
    <!-- 添加 Undertow 依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-undertow</artifactId>
    </dependency>
</dependencies>

启动类和其他配置应该保持不变,Spring Boot 会自动配置 Undertow。




import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
 
@SpringBootApplication
public class UndertowApplication {
    public static void main(String[] args) {
        SpringApplication.run(UndertowApplication.class, args);
    }
}

启动应用程序后,你应该看到 Undertow 服务器的启动日志输出。

2024-08-28

在Oracle数据库中,可以使用DBMS\_CRYPTO包来进行加密和解密操作。以下是一个使用DBMS\_CRYPTO进行AES加密和解密的例子:




-- 加密函数
CREATE OR REPLACE FUNCTION encrypt_data(
    p_input RAW,
    p_key RAW
) RETURN RAW IS
BEGIN
    RETURN DBMS_CRYPTO.ENCRYPT(
        src => p_input,
        typ => DBMS_CRYPTO.ENCRYPT_AES256 + DBMS_CRYPTO.CHAIN_CBC + DBMS_CRYPTO.PAD_PKCS5,
        key => p_key
    );
END;
/
 
-- 解密函数
CREATE OR REPLACE FUNCTION decrypt_data(
    p_input RAW,
    p_key RAW
) RETURN VARCHAR2 IS
BEGIN
    RETURN UTL_RAW.CAST_TO_VARCHAR2(
        DBMS_CRYPTO.DECRYPT(
            src => p_input,
            typ => DBMS_CRYPTO.ENCRYPT_AES256 + DBMS_CRYPTO.CHAIN_CBC + DBMS_CRYPTO.PAD_PKCS5,
            key => p_key
        )
    );
END;
/
 
-- 使用示例
DECLARE
    v_key RAW(255) := UTL_RAW.CAST_TO_RAW('your-256-bit-key-here'); -- 替换为你的256位密钥
    v_plaintext VARCHAR2(2000) := 'SensitiveDataToEncrypt';
    v_ciphertext RAW(2000);
    v_decrypted VARCHAR2(2000);
BEGIN
    -- 加密数据
    v_ciphertext := encrypt_data(UTL_RAW.CAST_TO_RAW(v_plaintext), v_key);
    
    -- 解密数据
    v_decrypted := decrypt_data(v_ciphertext, v_key);
    
    -- 输出结果
    DBMS_OUTPUT.PUT_LINE('Plaintext: ' || v_plaintext);
    DBMS_OUTPUT.PUT_LINE('Ciphertext: ' || RAWTOHEX(v_ciphertext));
    DBMS_OUTPUT.PUT_LINE('Decrypted: ' || v_decrypted);
END;
/

在这个例子中,encrypt_data函数用于加密文本,而decrypt_data函数用于解密文本。密钥需要是256位的,并且在加密和解密过程中需要一致使用。

请确保你有适当的权限来创建函数,并且在实际环境中使用时要注意密钥的管理和存储安全。