目录

一、新建白板Spring项目

二、搭建spring框架

 三、引入记录操作日志切面

 四、登录

 五、登录日志


一、新建白板Spring项目

1、新建一个Spring项目

2、选择Lombok依赖和Spring Web依赖

3、更换2.1.3.RELEASE版本+刷新(稳定版本)——白板项目新建完成

4、启动(会报一个错,把引入包删掉在启动)

springboot一般用户浏览记录保存在哪里 springboot 操作记录_java

二、搭建spring框架

1、引入mybatis依赖

<dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.1</version>
      </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
      </dependency>

2、引入Mybatis Plus依赖

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.2</version>
</dependency>

3、 resource下面新建一个application.yaml文件,加入数据库连接和mybatis plus配置

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/qcby_db?useUnicode=true&characterEncoding=utf-8&serverTimezone=CTT
    username: root
    password:
    driver-class-name: com.mysql.cj.jdbc.Driver
# mybatis-plus配置
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  typeAliasesPackage: com.qcbt.lxt.byg0417.entity
  mapperLocations: classpath:mapper/*.xml
  # 全局配置id自增  =>
  global-config:
    db-config:
      id-type: auto

 一一对应上

springboot一般用户浏览记录保存在哪里 springboot 操作记录_intellij-idea_02

 4、添加分页插件,在config包下面新建一个MybatisPlusConfig.java类

@MapperScan("com.example.demo2022.mapper")
@Configuration
public class MybatisPlusConfig {
    // 最新版
    @Bean  // <bean id=""/>
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

springboot一般用户浏览记录保存在哪里 springboot 操作记录_intellij-idea_03

5、 在common包下web包下新建一个返回值类WebResultJson.java

/**
 * 通用的返回结果封装
 */
@Data
public class WebResultJson {
    /**
     *  1 返回成功
     *  0 返回失败
     */
    public final static int OK = 1;
    public final static String OK_MSG = "操作成功!";
    public final static int FAIL = 0;
    public final static String FAIL_MSG = "操作失败!";


    private int code;
    private String msg;
    private Object data;


    private WebResultJson(int code, String msg, Object data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    public static WebResultJson ok(){
        return ok(OK_MSG,null);
    }
    public static WebResultJson ok(String msg){
        return new WebResultJson(OK,msg,null);
    }
    public static WebResultJson ok(Object data){
        return new WebResultJson(OK,OK_MSG,data);
    }
    public static WebResultJson ok(String msg,Object data){
        return new WebResultJson(OK,msg,data);
    }


    public static WebResultJson fail(){
        return fail(FAIL_MSG,null);
    }
    public static WebResultJson fail(String msg){
        return new WebResultJson(FAIL,msg,null);
    }
    public static WebResultJson fail(Object data){
        return new WebResultJson(FAIL,FAIL_MSG,data);
    }
    public static WebResultJson fail(String msg,Object data){
        return new WebResultJson(FAIL,msg,data);
    }
}

6、新建一个测试类User.java、UserMapper、IUserService、UserServiceImpl、UserController(全略)

controller中

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private IUserService userService;

    @RequestMapping("/listAll")
    public WebResultJson listAll() {
        return WebResultJson.ok(userService.list());
    }

}

springboot一般用户浏览记录保存在哪里 springboot 操作记录_intellij-idea_04

 7、运行http://localhost:8080/user/listAll 测试成功

 

springboot一般用户浏览记录保存在哪里 springboot 操作记录_java_05

 三、引入记录操作日志切面

1、引入切面依赖

<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.35</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

2、common下面constant包下新建一个全局变量类GlobalConstant.java

public class GlobalConstant {
    /**
     * 请求头中的token的名称
     *
     */
    public final static String HEADER_TOKEN = "token";

}

3、把数据库中的OperatorLog表实现mapper、service、等等

4、在demmo2022下的util包下建立TokenUtil.java

public class TokenUtil {
    /**
     * 创建一个map  用于存储所有的令牌
     *
     *      token  -  User
     */
    private static Map<String, User> tokenMap = new HashMap<>();

    /**
     *  生成token,存储token-user的对应关系
     *  返回token令牌
     * @param user
     * @return
     */
    public static String generateToken(User user){
        // 生成唯一不重复的字符串
        String token = UUID.randomUUID().toString();
        tokenMap.put(token,user);
        return token;
    }

    /**
     *  验证token是否合法
     * @param token
     * @return
     */
    public static boolean verify(String token){
        return tokenMap.containsKey(token);
    }

    /**
     *  根据token获取用户信息
     * @param token
     * @return
     */
     public static User getUser(String token){
         return tokenMap.get(token);
     }

    public static void main(String[] args) {
        for (int i=0; i<20; i++){
            System.out.println(UUID.randomUUID().toString());
        }
    }
}

5、在demmo2022下的aop包下新建OperatorLogAop.java

@Aspect
@Component
@Slf4j
public class OperatorLogAop {
    @Autowired
    private HttpServletRequest request;
    @Autowired
    private IOperatorLogService operatorLogService;

    //定义切点,注解作为切入点
    @Pointcut("execution(public * com.example.demo2022.controller..*.*(..))")
    public void logPoinCut() {

    }


    @Around("logPoinCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        OperatorLog operatorLog = new OperatorLog();
        String token = request.getHeader(GlobalConstant.HEADER_TOKEN);
        if(!StringUtils.isEmpty(token)){
            // 可以从session获取 / token获取
            // 从token中获取到用户ID
            User user = TokenUtil.getUser(token);
            operatorLog.setUserId(user.getId());
        }
        /**
         * 进行业务操作
         */
        //从切面织入点处通过反射机制获取织入点处的方法
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        //获取切入点所在的方法
        Method method = signature.getMethod();
        String clz = joinPoint.getTarget().getClass().toString();
        operatorLog.setMethodName(clz +"."+ method.getName());
        operatorLog.setUrl(request.getRequestURI());
        //获取切入点方法参数
        Object[] objects = joinPoint.getArgs();
        String[] paramNames =  signature.getParameterNames();
        Map<String,Object> map = new HashMap<>();
        for (int i =0;i<paramNames.length;i++){
            map.put(paramNames[i],objects[i]);
        }
        // 入参转化成json
        operatorLog.setInParameter(JSONObject.toJSONString(map));
        // 执行目标方法  获取返回值
        Object r = joinPoint.proceed();
        // 如果我们封装了通用的返回结果可以直接转json
        operatorLog.setOutParameter(JSONObject.toJSONString(r.toString()));
        operatorLog.setCreateTime(LocalDateTime.now());
        // 插入数据库,操作日志:
        operatorLogService.save(operatorLog);
        return r;
    }
}

springboot一般用户浏览记录保存在哪里 springboot 操作记录_java_06

 6、运行成功,看数据库operator_log这个表

springboot一般用户浏览记录保存在哪里 springboot 操作记录_User_07

 四、登录

UserController.java中,引入登录方法

@RequestMapping(value = "/login",method = {RequestMethod.GET,RequestMethod.POST})
    public WebResultJson login(User user){
        if(StringUtils.isEmpty(user.getUsername()) || StringUtils.isEmpty(user.getPassword()) ){
            return WebResultJson.fail("用户或者密码为空!");
        }
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username",user.getUsername())
                .eq("password",user.getPassword());
        User userDb = userService.getOne(queryWrapper);
        if(userDb != null){
            // 获取用户所有的权限信息
//            Set<String> menuUrlList = menuService.listUrlByUserId(userDb.getId());
//            userDb.setMenuUrlList(menuUrlList);
            // 登陆成功了
            String token = TokenUtil.generateToken(userDb);
            userDb.setToken(token);
//            loginLogService.saveLoginLog(userDb.getId());
            return WebResultJson.ok(userDb);
        }else{
            return WebResultJson.fail("用户名或密码错误!");
        }

    }

http://localhost:8080/user/login?username=admin&password=123456

springboot一般用户浏览记录保存在哪里 springboot 操作记录_intellij-idea_08

 

springboot一般用户浏览记录保存在哪里 springboot 操作记录_IP_09

 五、登录日志

1、按数据库login_log表生成实体类,service,mapper,impl

2、在util包下添加一个获取ip,浏览器的名字的类RequestUtil.java

public class RequestUtil {

    public static String getIPAddress(HttpServletRequest request) {
        String ip = null;    //X-Forwarded-For:Squid 服务代理
        String ipAddresses = request.getHeader("X-Forwarded-For");
        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {        //Proxy-Client-IP:apache 服务代理
            ipAddresses = request.getHeader("Proxy-Client-IP");
        }
        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {        //WL-Proxy-Client-IP:weblogic 服务代理
            ipAddresses = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {        //HTTP_CLIENT_IP:有些代理服务器
            ipAddresses = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ipAddresses == null || ipAddresses.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {        //X-Real-IP:nginx服务代理
            ipAddresses = request.getHeader("X-Real-IP");
        }    //有些网络通过多层代理,那么获取到的ip就会有多个,一般都是通过逗号(,)分割开来,并且第一个ip为客户端的真实IP
        if (ipAddresses != null && ipAddresses.length() != 0) {
            ip = ipAddresses.split(",")[0];
        }    //还是不能获取到,最后再通过request.getRemoteAddr();获取
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ipAddresses)) {
            ip = request.getRemoteAddr();
        }
        if("0:0:0:0:0:0:0:1".equals(ip)){
            return "127.0.0.1";
        }
        return ip;
    }


    /**
     * 获取操作系统,浏览器及浏览器版本信息
     * @param request
     * @return
     */
    public static String getOsAndBrowserInfo(HttpServletRequest request){
        String  browserDetails  =   request.getHeader("User-Agent");
        String  userAgent       =   browserDetails;
        String  user            =   userAgent.toLowerCase();

        String os = "";
        String browser = "";

        //=================OS Info=======================
        if (userAgent.toLowerCase().indexOf("windows") >= 0 )
        {
            os = "Windows";
        } else if(userAgent.toLowerCase().indexOf("mac") >= 0)
        {
            os = "Mac";
        } else if(userAgent.toLowerCase().indexOf("x11") >= 0)
        {
            os = "Unix";
        } else if(userAgent.toLowerCase().indexOf("android") >= 0)
        {
            os = "Android";
        } else if(userAgent.toLowerCase().indexOf("iphone") >= 0)
        {
            os = "IPhone";
        }else{
            os = "UnKnown, More-Info: "+userAgent;
        }
        //===============Browser===========================
        if (user.contains("edge"))
        {
            browser=(userAgent.substring(userAgent.indexOf("Edge")).split(" ")[0]).replace("/", "-");
        } else if (user.contains("msie"))
        {
            String substring=userAgent.substring(userAgent.indexOf("MSIE")).split(";")[0];
            browser=substring.split(" ")[0].replace("MSIE", "IE")+"-"+substring.split(" ")[1];
        } else if (user.contains("safari") && user.contains("version"))
        {
            browser=(userAgent.substring(userAgent.indexOf("Safari")).split(" ")[0]).split("/")[0]
                    + "-" +(userAgent.substring(userAgent.indexOf("Version")).split(" ")[0]).split("/")[1];
        } else if ( user.contains("opr") || user.contains("opera"))
        {
            if(user.contains("opera")){
                browser=(userAgent.substring(userAgent.indexOf("Opera")).split(" ")[0]).split("/")[0]
                        +"-"+(userAgent.substring(userAgent.indexOf("Version")).split(" ")[0]).split("/")[1];
            }else if(user.contains("opr")){
                browser=((userAgent.substring(userAgent.indexOf("OPR")).split(" ")[0]).replace("/", "-"))
                        .replace("OPR", "Opera");
            }

        } else if (user.contains("chrome"))
        {
            browser=(userAgent.substring(userAgent.indexOf("Chrome")).split(" ")[0]).replace("/", "-");
        } else if ((user.indexOf("mozilla/7.0") > -1) || (user.indexOf("netscape6") != -1)  ||
                (user.indexOf("mozilla/4.7") != -1) || (user.indexOf("mozilla/4.78") != -1) ||
                (user.indexOf("mozilla/4.08") != -1) || (user.indexOf("mozilla/3") != -1) )
        {
            browser = "Netscape-?";

        } else if (user.contains("firefox"))
        {
            browser=(userAgent.substring(userAgent.indexOf("Firefox")).split(" ")[0]).replace("/", "-");
        } else if(user.contains("rv"))
        {
            String IEVersion = (userAgent.substring(userAgent.indexOf("rv")).split(" ")[0]).replace("rv:", "-");
            browser="IE" + IEVersion.substring(0,IEVersion.length() - 1);
        } else
        {
            browser = "UnKnown, More-Info: "+userAgent;
        }

        return os +" --- "+ browser ;
    }
}

3、在LoginLogServiceImpl.java中实现

@Service
public class LoginLogServiceImpl extends ServiceImpl<LoginLogMapper, LoginLog> implements ILoginLogService {

    @Autowired
    private HttpServletRequest request;

    @Override
    public void saveLoginLog(long userId){
      LoginLog loginLog  =  new LoginLog();
      loginLog.setLoginTime(LocalDateTime.now());
      loginLog.setUserId(userId);

        //获取ip
        loginLog.setIp(RequestUtil.getIPAddress(request));
        //获取浏览器信息
        loginLog.setBrowserName(RequestUtil.getOsAndBrowserInfo(request));
        this.save(loginLog);
    }
}

4、在UserController.java中加入

springboot一般用户浏览记录保存在哪里 springboot 操作记录_java_10

springboot一般用户浏览记录保存在哪里 springboot 操作记录_java_11

 5、浏览器登录http://localhost:8080/user/login?username=admin&password=123456

数据库中会加入字段

springboot一般用户浏览记录保存在哪里 springboot 操作记录_User_12