AOP实战

设计一个数据库来存储和获取店铺下的员工信息,记录登陆日志,和修改操作 涉及几个步骤。以下是一个基本的数据库设计方案,假设你使用的是关系型数据库,如MySQL  

设计一个数据库来存储和获取店铺下的员工信息涉及几个步骤。以下是一个基本的数据库设计方案,假设你使用的是关系型数据库,如MySQL或PostgreSQL。

获取店铺下的员工信息

### 数据库设计

 

1. **店铺表(`stores`)**:

   - `store_id` (主键, 唯一标识店铺)

   - `store_name` (店铺名称)

   - `store_location` (店铺位置等其他信息)

 

   ```sql

   CREATE TABLE stores (

       store_id INT PRIMARY KEY AUTO_INCREMENT,

       store_name VARCHAR(255) NOT NULL,

       store_location VARCHAR(255)

   );

   ```

 

2. **员工表(`employees`)**:

   - `employee_id` (主键, 唯一标识员工)

   - `first_name` (员工名)

   - `last_name` (员工姓)

   - `position` (员工职位)

   - `store_id` (外键, 关联到店铺表)

 

   ```sql

   CREATE TABLE employees (

       employee_id INT PRIMARY KEY AUTO_INCREMENT,

       first_name VARCHAR(255) NOT NULL,

       last_name VARCHAR(255) NOT NULL,

       position VARCHAR(255),

       store_id INT,

       FOREIGN KEY (store_id) REFERENCES stores(store_id)

   );

   ```

 

### 接口设计

 

1. **获取当前店铺下的员工接口**:

   - **HTTP 方法**: GET

   - **URL**: `/api/stores/{store_id}/employees`

   - **参数**: `store_id` (店铺ID)

   - **返回示例**:

     ```json

     {

       "employees": [

         {

           "employee_id": 1,

           "first_name": "John",

           "last_name": "Doe",

           "position": "Manager"

         },

         {

           "employee_id": 2,

           "first_name": "Jane",

           "last_name": "Smith",

           "position": "Sales Associate"

         }

       ]

     }

     ```

 

   - **示例 SQL 查询**:

     ```sql

     SELECT employee_id, first_name, last_name, position

     FROM employees

     WHERE store_id = ?;

     ```

 

### 总结

 

- **`stores` 表** 存储店铺信息。

- **`employees` 表** 存储员工信息,并且通过 `store_id` 外键关联到店铺表。

- **接口** 通过店铺ID来获取所有员工的信息。

aop实战

在数据库中存储登录日志和操作记录通常需要两个表,一个用于记录用户登录信息,另一个用于记录操作日志。下面是如何设计这些表和实现相关功能的示例:

### 1. 数据库表设计

#### 登录日志表(`login_logs`)

```sql
CREATE TABLE login_logs (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(255) NOT NULL,
    login_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    success BOOLEAN NOT NULL,
    ip_address VARCHAR(45)
);
```

- `id`: 主键,自增
- `username`: 用户名
- `login_time`: 登录时间
- `success`: 登录是否成功
- `ip_address`: 登录的IP地址

#### 操作记录表(`operation_logs`)

```sql
CREATE TABLE operation_logs (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(255) NOT NULL,
    operation_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    operation_details TEXT
);
```

- `id`: 主键,自增
- `username`: 用户名
- `operation_time`: 操作时间
- `operation_details`: 操作详细信息

### 2. 创建数据访问层(Repository)

使用Spring Data JPA或MyBatis等工具来处理数据访问。

#### 使用Spring Data JPA

##### 登录日志仓库接口

```java
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface LoginLogRepository extends JpaRepository<LoginLog, Integer> {
}
```

##### 操作记录仓库接口

```java
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface OperationLogRepository extends JpaRepository<OperationLog, Integer> {
}
```

#### 实体类

##### 登录日志实体类

```java
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import java.time.LocalDateTime;

@Entity
public class LoginLog {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    private String username;
    private LocalDateTime loginTime;
    private Boolean success;
    private String ipAddress;

    // Getters and Setters
}
```

##### 操作记录实体类

```java
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import java.time.LocalDateTime;

@Entity
public class OperationLog {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    private String username;
    private LocalDateTime operationTime;
    private String operationDetails;

    // Getters and Setters
}
```

### 3. 修改切面类以记录日志到数据库

在切面类中注入上述仓库,并在日志记录时保存数据到数据库。

#### 登录日志切面

```java
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoginLogAspect {

    @Autowired
    private LoginLogRepository loginLogRepository;

    @AfterReturning(pointcut = "execution(* com.example.yourapp.service.UserService.login(..))", returning = "result")
    public void logLogin(JoinPoint joinPoint, Object result) {
        String username = (String) joinPoint.getArgs()[0];
        boolean success = (result != null); // 判断登录是否成功
        String ipAddress = ""; // 通过其他方式获取IP地址
        
        LoginLog loginLog = new LoginLog();
        loginLog.setUsername(username);
        loginLog.setSuccess(success);
        loginLog.setIpAddress(ipAddress);
        
        loginLogRepository.save(loginLog);
    }
}
```

#### 操作记录切面

```java
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class OperationLogAspect {

    @Autowired
    private OperationLogRepository operationLogRepository;

    @Before("execution(* com.example.yourapp.service.*.*(..))")
    public void logOperation(JoinPoint joinPoint) {
        String username = "someUser"; // 获取当前用户名,例如通过SecurityContextHolder
        String operationDetails = "方法调用: " + joinPoint.getSignature().toShortString();
        
        Object[] args = joinPoint.getArgs();
        for (Object arg : args) {
            operationDetails += ", 参数: " + arg;
        }

        OperationLog operationLog = new OperationLog();
        operationLog.setUsername(username);
        operationLog.setOperationDetails(operationDetails);
        
        operationLogRepository.save(operationLog);
    }
}
```

### 总结

1. **设计数据库表**:为登录日志和操作记录创建适当的表。
2. **创建数据访问层**:使用Spring Data JPA或类似工具来处理数据库操作。
3. **实现切面类**:使用AOP切面在登录和操作时记录日志,并将日志保存到数据库中。

通过这种方式,你可以在数据库中存储详细的登录和操作记录,便于审计和分析。

获取ip地址

 

在Spring Boot应用中获取用户的IP地址可以通过不同的方式实现,具体取决于你的应用架构和环境。以下是一些常见的获取IP地址的方法:

### 1. 从HTTP请求中获取IP地址

如果你的应用是通过HTTP请求接收用户操作,通常可以通过`HttpServletRequest`获取客户端的IP地址。

#### 示例代码:

```java
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class IpAddressUtil {

    @Autowired
    private HttpServletRequest request;

    public String getClientIpAddress() {
        String remoteAddr = request.getRemoteAddr();
        String xForwardedFor = request.getHeader("X-Forwarded-For");
        if (xForwardedFor != null && !xForwardedFor.isEmpty()) {
            // X-Forwarded-For 头部可能包含多个IP地址,取第一个
            return xForwardedFor.split(",")[0];
        }
        return remoteAddr;
    }
}
```

### 2. 在AOP切面中获取IP地址

在AOP切面中获取IP地址,需要依赖`HttpServletRequest`。你可以通过Spring的依赖注入来实现这一点。

#### 示例代码:

```java
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

@Aspect
@Component
public class LoginLogAspect {

    @Autowired
    private LoginLogRepository loginLogRepository;

    @Autowired
    private HttpServletRequest request;

    @AfterReturning(pointcut = "execution(* com.example.yourapp.service.UserService.login(..))", returning = "result")
    public void logLogin(JoinPoint joinPoint, Object result) {
        String username = (String) joinPoint.getArgs()[0];
        boolean success = (result != null); // 判断登录是否成功
        String ipAddress = getClientIpAddress();
        
        LoginLog loginLog = new LoginLog();
        loginLog.setUsername(username);
        loginLog.setSuccess(success);
        loginLog.setIpAddress(ipAddress);
        
        loginLogRepository.save(loginLog);
    }

    private String getClientIpAddress() {
        String remoteAddr = request.getRemoteAddr();
        String xForwardedFor = request.getHeader("X-Forwarded-For");
        if (xForwardedFor != null && !xForwardedFor.isEmpty()) {
            // X-Forwarded-For 头部可能包含多个IP地址,取第一个
            return xForwardedFor.split(",")[0];
        }
        return remoteAddr;
    }
}
```

### 3. 考虑代理和负载均衡器

如果你的应用运行在代理服务器或负载均衡器后面,`X-Forwarded-For` 头部通常会包含客户端的真实IP地址,而 `request.getRemoteAddr()` 可能返回代理服务器的IP地址。因此,你需要优先从 `X-Forwarded-For` 中获取IP地址。

### 4. 配置Spring Boot

确保你的Spring Boot应用允许获取HTTP请求的IP地址:

```properties
server.servlet.context-path=/your-context-path
```

### 总结

- **从HTTP请求中获取IP地址**:通过`HttpServletRequest`的`getRemoteAddr()`方法和`X-Forwarded-For`头部。
- **在AOP切面中获取IP地址**:可以在切面类中注入`HttpServletRequest`,然后使用上述方法获取IP地址。
- **考虑代理和负载均衡器**:优先使用`X-Forwarded-For`头部的IP地址。

这些方法可以帮助你在Spring Boot应用中获取用户的IP地址,并在日志记录等功能中使用。

 

 

  • 9
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值