2024-08-29

Redis是一个开源的使用C语言编写的、支持网络交互的、可基于内存也可持久化的Key-Value数据库。

Redis不是传统的关系数据库,而是一个nosql数据库(非关系型数据库),也不是传统的键值存储。Redis支持丰富的数据结构,如字符串(String), 哈希表(Map), 列表(list), 集合(sets),有序集合(sorted sets)等,并且提供了诸如键过期,发布/订阅等功能。

Redis非关系型数据库的特点:

  1. 性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s。
  2. 持久化 – 可以将内存中的数据保存在硬盘中,重启时可以再次加载。
  3. 支持数据类型丰富 – String, List, Hash, Set 和 Sorted Set 等。
  4. 支持复制 – 使用Redis Sentinel 和 Redis Cluster 可以进行自动的复制和故障恢复。
  5. 支持事务 – 通过MULTI和EXEC指令包起来的操作会作为一个整体执行,保证了事务中的命令要么全部执行,要么全部不执行。

解决方案:

  1. 安装Redis



# 使用Ubuntu/Debian系统的安装命令
sudo apt-get install redis-server
 
# 使用CentOS/RHEL系统的安装命令
sudo yum install redis
  1. 启动Redis服务



# 使用Ubuntu/Debian系统的启动命令
sudo service redis-server start
 
# 使用CentOS/RHEL系统的启动命令
sudo systemctl start redis
  1. 连接Redis



# 连接本地Redis服务
redis-cli
 
# 连接远程Redis服务
redis-cli -h host -p port -a password
  1. 使用Redis



# 使用Python连接Redis
import redis
 
r = redis.Redis(host='localhost', port=6379, db=0)
 
# 设置键值对
r.set('foo', 'bar')
 
# 获取键值对
print(r.get('foo'))
  1. 使用Redis的数据结构



# 使用Redis的哈希表
r.hset('hash_key', 'field1', 'value1')
r.hget('hash_key', 'field1')
 
# 使用Redis的列表
r.rpush('list_key', 'item1')
r.lpush('list_key', 'item2')
r.lrange('list_key', 0, -1)
 
# 使用Redis的集合
r.sadd('set_key', 'member1')
r.smembers('set_key')
 
# 使用Redis的有序集合
r.zadd('zset_key', {'member1': 1})
r.zrange('zset_key', 0, -1)
  1. 使用Redis的发布/订阅模式



# 发布消息
r.publish('channel', 'message')
 
# 订阅频道
pubsub = r.pubsub()
pubsub.subscribe('channel')
pubsub.listen()

以上就是Redis非关系型数据库的基本使用方法,包括安装、启动、连接、基本操作、数据结构操作和发布/订阅模式。

2024-08-29

在CentOS 7上安装Redis 5.0,可以按照以下步骤操作:

  1. 首先,更新系统包并安装必要的依赖:



sudo yum update
sudo yum install -y gcc make
  1. 下载Redis 5.0的源代码:



wget http://download.redis.io/releases/redis-5.0.0.tar.gz
  1. 解压源代码并编译安装:



tar xzf redis-5.0.0.tar.gz
cd redis-5.0.0
make
make test # 可选,运行测试
sudo make install
  1. 创建配置文件和目录:



sudo mkdir /etc/redis
sudo cp redis.conf /etc/redis/redis.conf
  1. 修改配置文件(可选,根据需要配置Redis):



sudo vi /etc/redis/redis.conf
  1. 创建一个systemd服务文件:



sudo vi /etc/systemd/system/redis.service

添加以下内容:




[Unit]
Description=Redis In-Memory Data Store
After=network.target
 
[Service]
User=redis
Group=redis
ExecStart=/usr/local/bin/redis-server /etc/redis/redis.conf
ExecStop=/usr/local/bin/redis-cli shutdown
Restart=always
 
[Install]
WantedBy=multi-user.target
  1. 启动Redis服务:



sudo systemctl start redis.service
  1. 设置Redis服务开机自启:



sudo systemctl enable redis.service
  1. 检查Redis服务状态:



sudo systemctl status redis.service
  1. 测试Redis是否正常工作:



redis-cli ping

如果返回PONG,则表示Redis已成功安装并运行。

2024-08-29

@FeignClient是Spring Cloud提供的一个注解,用于声明一个Feign客户端的接口,以便使用Feign来调用远程服务。

以下是@FeignClient的主要属性:

  • name: 指定远程服务的名称,必须指定。
  • url: 直接指定远程服务的URL,不通过服务发现。
  • serviceId: 已废弃,与name属性等同。
  • contextId: 如果需要创建多个Feign客户端,可以通过contextId来区分。
  • decode404: 是否将404响应转换为空对象,而不是抛出异常,默认false
  • configuration: 指定Feign的配置类,可以自定义Feign的Encoder、Decoder和Contract。
  • fallback: 指定一个fallback类,当服务调用失败时,会调用fallback类中的方法。
  • path: 指定服务路径,用于当服务的分组功能。

使用示例:




@FeignClient(name = "service-provider", url = "http://localhost:8080", contextId = "remoteService")
public interface RemoteService {
    @GetMapping("/data")
    String getData();
 
    @PostMapping("/submit")
    void submitData(@RequestBody MyData data);
}

在上面的例子中,RemoteService接口定义了两个方法,用于调用远程服务service-provider/data/submit接口。通过@FeignClient注解指定了服务名称、URL和上下文ID。

若要使用fallback机制,需要定义一个fallback类:




@Component
public class RemoteServiceFallback implements RemoteService {
    @Override
    public String getData() {
        return "Fallback message";
    }
 
    @Override
    public void submitData(MyData data) {
        // Fallback logic
    }
}

然后在@FeignClient注解中指定fallback类:




@FeignClient(name = "service-provider", url = "http://localhost:8080", contextId = "remoteService", fallback = RemoteServiceFallback.class)
public interface RemoteService {
    // ...
}

这样,当service-provider服务不可用时,就会调用RemoteServiceFallback中的方法。

2024-08-29

Spring Boot启动的核心流程如下:

  1. 通过SpringApplication类的run方法启动Spring Boot应用。
  2. SpringApplication类会创建一个ApplicationContext
  3. 根据配置确定应用的类型,并设置相应的ApplicationContext
  4. 应用配置的监听器会被注册。
  5. 通过SpringFactoriesLoader机制加载META-INF/spring.factories文件中的自动配置类。
  6. 进行自动配置,并且注册bean定义到ApplicationContext中。
  7. 调用所有注册的bean生命周期监听器和应用启动监听器。
  8. 启动完成,等待用户请求处理。

以下是一个简化的Spring Boot启动类示例:




import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
 
@SpringBootApplication // 标注这是一个Spring Boot应用
public class MySpringBootApplication {
 
    public static void main(String[] args) {
        // 启动Spring Boot应用
        SpringApplication.run(MySpringBootApplication.class, args);
    }
}

在这个示例中,@SpringBootApplication注解是Spring Boot的核心注解,它是一个组合注解,包含了@EnableAutoConfiguration@ComponentScan@Configuration@EnableAutoConfiguration让Spring Boot根据类路径设置、其他注解和application.propertiesapplication.yml文件来自动配置Spring容器。@ComponentScan告诉Spring Let Boot在这个包下扫描@Components、@Services、@Repositories等Bean。

2024-08-29



#include <graphics.h> // 引入easyx图形库头文件
#include <conio.h>    // 用于getch函数
 
// 初始化图形模式
IMAGE img;
void init_graph(int width, int height, int color) {
    initgraph(width, height);  // 初始化图形窗口
    loadimage(&img, L"example.bmp", L"example.bmp");  // 加载图片
    setbkcolor(color);  // 设置背景颜色
}
 
// 主要的绘图函数
void draw() {
    putimage(0, 0, &img);  // 绘制图片
}
 
// 主函数
int main() {
    init_graph(640, 480, BLACK);  // 初始化图形模式
 
    // 使用双缓冲消除闪屏
    BeginBatchDraw();  // 开始批量绘制
    cleardevice();     // 清除当前屏幕
    draw();            // 调用绘图函数
    FlushBatchDraw();  // 刷新缓冲区内的所有图像到屏幕上
 
    // 等待任意键按下
    _getch();
 
    EndBatchDraw();  // 结束批量绘制
 
    // 关闭图形模式
    closegraph();  // 关闭图形窗口
    return 0;
}

这段代码展示了如何在使用easyx图形库时,通过BeginBatchDraw和EndBatchDraw来消除图形的闪烁(即消除屏幕刷新所导致的视觉不连贯问题)。通过将绘图操作集中在一起,并在所有绘图完成后一次性刷新到屏幕上,可以有效减少闪屏现象。

2024-08-29

在Spring Boot中,接收参数的常见方式有以下几种:

  1. 通过@RequestParam接收查询参数(Query parameter)。
  2. 通过@PathVariable接收路径参数(Path variable)。
  3. 通过@RequestBody接收请求体(Request body)中的JSON或XML数据,通常用于POST或PUT请求。
  4. 通过@ModelAttribute接收表单提交的数据,通常用于POST请求。
  5. 通过@RequestHeader接收请求头(Request header)数据。
  6. 通过@MatrixVariable接收路径段的矩阵变量(Matrix variable)。

以下是各种方式的示例代码:




// 1. 通过@RequestParam接收查询参数
@GetMapping("/users")
public String getUsersByName(@RequestParam String name) {
    // ...
}
 
// 2. 通过@PathVariable接收路径参数
@GetMapping("/users/{id}")
public String getUserById(@PathVariable Integer id) {
    // ...
}
 
// 3. 通过@RequestBody接收请求体数据
@PostMapping("/users")
public User createUser(@RequestBody User user) {
    // ...
}
 
// 4. 通过@ModelAttribute接收表单数据
@PostMapping("/users")
public String submitForm(@ModelAttribute User user) {
    // ...
}
 
// 5. 通过@RequestHeader接收请求头数据
@GetMapping("/users")
public String getUsersByHeader(@RequestHeader("Authorization") String auth) {
    // ...
}
 
// 6. 通过@MatrixVariable接收矩阵变量
@GetMapping("/cars/{brand}")
public String getCarModels(@PathVariable String brand, @MatrixVariable Map<String, String> matrixVars) {
    // ...
}

注意:@ModelAttribute通常与表单提交配合使用,而@MatrixVariable主要用于REST风格的URL设计,在非REST风格的应用中较少使用。

2024-08-29

在Linux中修改Tomcat使用的JDK版本,你需要做的是:

  1. 确定你想要使用的JDK版本的安装路径。
  2. 修改Tomcat的环境配置文件以指向新的JDK路径。

以下是具体步骤和示例:

  1. 找到你的JDK路径。假设你已经安装了JDK 11,它可能位于/usr/lib/jvm/jdk-11
  2. 编辑Tomcat的setenv.sh文件(如果不存在,则创建它)。该文件通常位于$CATALINA_HOME/bin目录中。



cd $CATALINA_HOME/bin
nano setenv.sh

如果你使用的是setenv.sh,添加以下内容来设置JAVA\_HOME:




export JAVA_HOME=/usr/lib/jvm/jdk-11
export JRE_HOME=${JAVA_HOME}/jre

如果你使用的是catalina.sh脚本,可以在其中设置JAVA\_HOME:




JAVA_HOME=/usr/lib/jvm/jdk-11
  1. 保存文件并退出编辑器。
  2. 重启Tomcat以使更改生效。



$CATALINA_HOME/bin/shutdown.sh
$CATALINA_HOME/bin/startup.sh
  1. 验证Tomcat是否使用了新的JDK版本。



ps -ef | grep java

确保在ps的输出中看到的是新JDK路径。

注意:如果你的系统中有多个JDK版本,请确保指定的路径是你想要Tomcat使用的那个版本的路径。

2024-08-29

在Spring Boot中集成WebSocket,你可以使用Spring的@EnableWebSocketMessageBroker注解来配置一个WebSocket消息代理。以下是一个简单的例子:

  1. 添加依赖到你的pom.xml



<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
  1. 配置WebSocketMessageBroker:



import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
 
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
    
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/ws").withSockJS();
    }
 
    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        registry.enableSimpleBroker("/topic");
        registry.setApplicationDestinationPrefixes("/app");
    }
}
  1. 创建一个控制器来处理WebSocket消息:



import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
 
@Controller
public class WebSocketController {
 
    @MessageMapping("/hello")
    @SendTo("/topic/greetings")
    public String greeting(String message) {
        return "Hello, " + message + "!";
    }
}
  1. 前端使用SockJS和STOMP:



<script src="https://cdn.jsdelivr.net/npm/sockjs-client@1.7.0/dist/sockjs.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/stompjs@2.3.3/stomp.min.js"></script>
<script>
    var socket = new WebSocket('ws://localhost:8080/ws');
    var stompClient = Stomp.over(socket);
    stompClient.connect({}, function(frame) {
        console.log('Connected: ' + frame);
        stompClient.subscribe('/topic/greetings', function(greeting){
            console.log(greeting.body);
        });
    });
    
    function sendName() {
        s
2024-08-29

Tomcat中的Session实现主要在org.apache.catalina.session包中。以下是核心类的简化说明:

  1. StandardSession:实现了javax.servlet.http.HttpSession接口,是Tomcat中Session的核心类。它维护Session的状态,包括属性、创建时间、最后访问时间等。
  2. ManagerBase:实现了javax.servlet.http.HttpSessionManager接口,是所有Session管理器的基类。它定义了管理Session的通用方法,包括加载、保存、创建、删除Session等。
  3. PersistentManagerBase:继承自ManagerBase,添加了持久化Session的能力,通过实现Lifecycle接口,可以在Tomcat启动和关闭时进行Session的加载和保存。
  4. DeltaManager:实现了Session的增量保存机制,只保存自上次保存以来有变化的Session属性。

以下是StandardSession的关键方法的简化代码:




public class StandardSession implements HttpSession {
    private long creationTime = System.currentTimeMillis();
    private long lastAccessedTime;
    private boolean isValid = true;
    private Map<String, Object> attributes = new HashMap<>();
 
    public long getCreationTime() {
        return creationTime;
    }
 
    public void setLastAccessedTime(long time) {
        this.lastAccessedTime = time;
    }
 
    public long getLastAccessedTime() {
        return lastAccessedTime;
    }
 
    public boolean isValid() {
        return isValid;
    }
 
    public void invalidate() {
        isValid = false;
    }
 
    public void setAttribute(String name, Object value) {
        attributes.put(name, value);
    }
 
    public Object getAttribute(String name) {
        return attributes.get(name);
    }
 
    // 其他方法...
}

这个简化的例子展示了StandardSession类的基本结构和一些核心方法。实际的Tomcat实现还涉及到更多细节,例如Session的序列化、管理机制、分布式Session支持等。

2024-08-29



-- 创建一个名为example的数据库
ATTACH DATABASE 'example.db' AS example;
 
-- 创建一个名为users的表,包含id和name两个字段
CREATE TABLE example.users (
    id INTEGER PRIMARY KEY,
    name TEXT NOT NULL
);
 
-- 插入一条记录
INSERT INTO example.users (name) VALUES ('Alice');
 
-- 更新记录
UPDATE example.users SET name = 'Bob' WHERE id = 1;
 
-- 删除记录
DELETE FROM example.users WHERE id = 1;
 
-- 查询记录
SELECT * FROM example.users;
 
-- 关闭数据库连接
DETACH DATABASE example;

这个例子展示了如何使用SQLite的基本命令来创建数据库、创建表、插入数据、更新数据、删除数据和查询数据。同时,它也演示了如何使用ATTACH DATABASEDETACH DATABASE来打开和关闭数据库连接。这些操作是数据库编程中基本的操作,对于学习SQLite库的开发者来说具有很好的教育价值。