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

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地址,并在日志记录等功能中使用。

 

 

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【学习日记】【第五十一章 Linux中断实验】【流程图】——正点原子I.MX6U嵌入式Linux驱动开发
  • centos系统配置转发和iptables使之成为网关
  • 网络安全实训第一天(dami靶场搭建,XSS、CSRF、模板、任意文件删除添加、框架、密码爆破漏洞)
  • 倒排索引 vs 正排索引
  • SSE多服务器部署导致消息推送异常问题的处理
  • 光猫的 Telnet 命令(sidbg或sendcmd)和常用管理操作
  • HAProxy的详解
  • CentOS 7 下载/安装
  • stm32智能颜色送餐小车(红外光管避障)
  • MyBatis首篇-入门第一文
  • js根据指定的【时区、日期时间】获取对应时区的日期时间
  • 【HeadFirst 设计模式】单例模式的C++实现
  • CANoe软件中Trace窗口的筛选栏标题不显示(空白)的解决方法
  • 【MySQL核心】MySQL 数据恢复-ibd2sql
  • 2021年上半年网络工程师考试上午真题
  • dva中组件的懒加载
  • Elasticsearch 参考指南(升级前重新索引)
  • Java 多线程编程之:notify 和 wait 用法
  • Just for fun——迅速写完快速排序
  • node入门
  • 观察者模式实现非直接耦合
  • 用Node EJS写一个爬虫脚本每天定时给心爱的她发一封暖心邮件
  • 怎样选择前端框架
  • MiKTeX could not find the script engine ‘perl.exe‘ which is required to execute ‘latexmk‘.
  • 策略 : 一文教你成为人工智能(AI)领域专家
  • (003)SlickEdit Unity的补全
  • (145)光线追踪距离场柔和阴影
  • (20050108)又读《平凡的世界》
  • (阿里云在线播放)基于SpringBoot+Vue前后端分离的在线教育平台项目
  • (附源码)springboot 基于HTML5的个人网页的网站设计与实现 毕业设计 031623
  • (七)理解angular中的module和injector,即依赖注入
  • (三)mysql_MYSQL(三)
  • (四)activit5.23.0修复跟踪高亮显示BUG
  • (四)鸿鹄云架构一服务注册中心
  • (已解决)Bootstrap精美弹出框模态框modal,实现js向modal传递数据
  • (转)Windows2003安全设置/维护
  • (转)使用VMware vSphere标准交换机设置网络连接
  • (转)自己动手搭建Nginx+memcache+xdebug+php运行环境绿色版 For windows版
  • *++p:p先自+,然后*p,最终为3 ++*p:先*p,即arr[0]=1,然后再++,最终为2 *p++:值为arr[0],即1,该语句执行完毕后,p指向arr[1]
  • *setTimeout实现text输入在用户停顿时才调用事件!*
  • .NET 6 Mysql Canal (CDC 增量同步,捕获变更数据) 案例版
  • .NET C# 配置 Options
  • .net core 3.0 linux,.NET Core 3.0 的新增功能
  • .NET Core中如何集成RabbitMQ
  • .NET Micro Framework 4.2 beta 源码探析
  • .NET 简介:跨平台、开源、高性能的开发平台
  • .NetCore部署微服务(二)
  • @Autowired和@Resource的区别
  • [ HTML + CSS + Javascript ] 复盘尝试制作 2048 小游戏时遇到的问题
  • []AT 指令 收发短信和GPRS上网 SIM508/548
  • [24年新算法]NRBO-XGBoost回归+交叉验证基于牛顿拉夫逊优化算法-XGBoost多变量回归预测
  • [8-27]正则表达式、扩展表达式以及相关实战
  • [AI 大模型] Meta LLaMA-2
  • [ASP]青辰网络考试管理系统NES X3.5
  • [BZOJ1010] [HNOI2008] 玩具装箱toy (斜率优化)