Spring Boot + vue-element 开发个人博客项目实战教程(十八、操作日志功能实现)2

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
日志服务 SLS,月写入数据量 50GB 1个月
简介: Spring Boot + vue-element 开发个人博客项目实战教程(十八、操作日志功能实现)2

4、添加注解

下面我们写完了注解,接下来我们肯定要使用这个注解,但是在什么地方引用呢,当然在我们程序的入库,那就是Controller层,这个是前端操作第一个进来的入口。例如:我们在分类的Controller中添加分类的方法上添加一个注解。

@OperationLogSys(desc = "添加分类", operationType = OperationType.INSERT)

完整代码:

  /**
     * 添加分类
     * @return
     */
    @ApiOperation(value = "添加分类")
    @PostMapping("/create")
    @OperationLogSys(desc = "添加分类", operationType = OperationType.INSERT)
    public JsonResult<Object> categoryCreate(@RequestBody @Valid Category category) {
        int isStatus = categoryService.saveCategory(category);
        if (isStatus == 0) {
            return JsonResult.error("添加分类失败");
        }
        return JsonResult.success();
    }

我们先测试一下这个注解是否有用,操作数据是否保存到了数据中。

打开postman,因为我们上一篇加了登录验证,所以我们在操作其他接口时,要先登录,重启项目之后也要重新登录。

我们先进行登录:登录成功之后,然后我们打开添加分类的接口,新添加一个分类。

看着添加成功了,我们去看下数据库,操作日志有没有数据。看到有数据,也是我们添加的分类,就说明我们添加成功了。好啦,我只添加一个操作日志,大家把所有的增加、删除、修改都进行添加一下,查询数据比较多可加可不加。

接下来我们写一下操作日志,操作日志就比较简单啦,不用写注解啦,直接添加即可。

四、登录日志

接下来我们写一下登录日志,我们只需要再登录的接口的地方写一个插入登录操作的日志即可,由于我们设计的登录日志和操作日志是两张表,所以我们还得写一套登录日志的CRDU操作,废话不多说,开整。

下面我直接写了,大家应该可以看懂。

1、建表语句

DROP TABLE IF EXISTS `person_login_log`;
CREATE TABLE `person_login_log` (
  `id`                BIGINT(20)         NOT NULL   PRIMARY KEY AUTO_INCREMENT        COMMENT '登录访问id',
  `login_name`        VARCHAR(50)        NULL   DEFAULT ''                    COMMENT '登录账号',
  `ip_address`        VARCHAR(128)       NULL   DEFAULT ''                    COMMENT '登录IP地址',
  `login_location`    VARCHAR(255)       NULL       DEFAULT ''                    COMMENT '登录地点',
  `browser_type`      VARCHAR(50)        NULL       DEFAULT ''                    COMMENT '浏览器类型',
  `os`                VARCHAR(50)        NULL       DEFAULT ''                    COMMENT '操作系统',
  `login_status`      TINYINT            NULL       DEFAULT 0                   COMMENT '登录状态,默认0, 0-成功, 1-失败',
  `create_time`       DATETIME               NULL       DEFAULT CURRENT_TIMESTAMP       COMMENT '创建时间'
) ENGINE = InnoDB
  CHARACTER SET = utf8mb4
  COLLATE = utf8mb4_bin
  ROW_FORMAT = Dynamic
  COMMENT '登录日志表';

2、实体类

新建一个LoginOperationLog.java

package com.blog.personalblog.entity;
import lombok.Data;
import java.time.LocalDateTime;
/**
 * @author: SuperMan
 * @create: 2022-04-05
 **/
@Data
public class LoginOperationLog {
    /**
     * 主键id
     */
    private Integer id;
    /**
     * 登录账号
     */
    private String loginName;
    /**
     * 登录IP地址
     */
    private String ipAddress;
    /**
     * 登录地点
     */
    private String loginLocation;
    /**
     * 浏览器类型
     */
    private String browserType;
    /**
     * 操作系统
     */
    private String os;
    /**
     * 登录状态,默认0, 0-成功, 1-失败
     */
    private Integer loginStatus;
    /**
     * 创建时间
     */
    private LocalDateTime createTime;
}

3、业务类

(1)新建一个LoginOperationLogService.java业务接口类

package com.blog.personalblog.service;
import com.blog.personalblog.config.page.PageRequest;
import com.blog.personalblog.entity.LoginOperationLog;
import java.util.List;
/**
 * @author: SuperMan
 * @create: 2022-04-05
 **/
public interface LoginOperationLogService {
    /**
     * 添加登录日志
     *
     * @param loginOperationLog
     * @return
     */
    void saveOperationLog(LoginOperationLog loginOperationLog);
    /**
     * 登录日志列表(分页)
     *
     * @param pageRequest
     * @return
     */
    List<LoginOperationLog> getLoginOperationLogPage(PageRequest pageRequest);
}

(2)新建一个LoginOperationLogServiceImpl.java业务实现类

package com.blog.personalblog.service.Impl;
import com.blog.personalblog.config.page.PageRequest;
import com.blog.personalblog.entity.LoginOperationLog;
import com.blog.personalblog.mapper.LoginOperationLogMapper;
import com.blog.personalblog.service.LoginOperationLogService;
import com.github.pagehelper.PageHelper;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
/**
 *
 * @author: SuperMan
 * @create: 2022-04-05
 **/
@Service
public class LoginOperationLogServiceImpl implements LoginOperationLogService {
    @Resource
    private LoginOperationLogMapper loginOperationLogMapper;
    @Override
    public void saveOperationLog(LoginOperationLog loginOperationLog) {
        loginOperationLogMapper.createLoginOperationLog(loginOperationLog);
    }
    @Override
    public List<LoginOperationLog> getLoginOperationLogPage(PageRequest pageRequest) {
        int pageNum = pageRequest.getPageNum();
        int pageSize = pageRequest.getPageSize();
        PageHelper.startPage(pageNum,pageSize);
        List<LoginOperationLog> loginOperationLogList = loginOperationLogMapper.getLoginOperationLogPage();
        return loginOperationLogList;
    }
}

4、数据接口Mapper

新建一个LoginOperationLogMapper.java接口

package com.blog.personalblog.mapper;
import com.blog.personalblog.entity.LoginOperationLog;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
 *
 * @author: SuperMan
 * @create: 2022-04-06
 **/
@Repository
public interface LoginOperationLogMapper {
    /**
     * 创建登录日志
     * @param loginOperationLog
     * @return
     */
    int createLoginOperationLog(LoginOperationLog loginOperationLog);
    /**
     * 分类列表(分页)
     * @return
     */
    List<LoginOperationLog> getLoginOperationLogPage();
}

5、xml文件

新建一个登录日志的LoginOperationLogMapper.xml文件,用来写sql语句。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.blog.personalblog.mapper.LoginOperationLogMapper">
    <resultMap id="BaseResultMap" type="com.blog.personalblog.entity.LoginOperationLog">
        <result column="id" jdbcType="INTEGER" property="id"/>
        <result column="login_name" jdbcType="VARCHAR" property="loginName"/>
        <result column="ip_address" jdbcType="VARCHAR" property="ipAddress"/>
        <result column="login_location" jdbcType="VARCHAR" property="loginLocation"/>
        <result column="browser_type" jdbcType="VARCHAR" property="browserType"/>
        <result column="os" jdbcType="VARCHAR" property="os"/>
        <result column="login_status" jdbcType="INTEGER" property="loginStatus"/>
        <result column="create_time" jdbcType="TIMESTAMP" property="createTime"/>
    </resultMap>
    <insert id="createLoginOperationLog" parameterType="com.blog.personalblog.entity.LoginOperationLog" useGeneratedKeys="true" keyProperty="id">
        INSERT INTO person_login_log (login_name, ip_address, login_location, browser_type, os, login_status)
        VALUES(#{loginName}, #{ipAddress}, #{loginLocation}, #{browserType}, #{os}, #{loginStatus})
    </insert>
    <select id="getLoginOperationLogPage" resultMap="BaseResultMap">
        select * from person_login_log
    </select>
</mapper>

6、接口层

新建一个日志的接口,我看了一下上边的操作日志我也没写接口层,所以我们将操作日志和登录日志写在一个Controller层中了。

先建一个OperationLogController.java

package com.blog.personalblog.controller;
import com.blog.personalblog.config.page.PageRequest;
import com.blog.personalblog.config.page.PageResult;
import com.blog.personalblog.entity.LoginOperationLog;
import com.blog.personalblog.entity.OperationLog;
import com.blog.personalblog.service.LoginOperationLogService;
import com.blog.personalblog.service.OperationLogService;
import com.blog.personalblog.util.JsonResult;
import com.blog.personalblog.util.PageUtil;
import com.github.pagehelper.PageInfo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;
/**
 *
 * @author: SuperMan
 * @create: 2022-04-06
 **/
@Api(tags = "操作日志")
@RestController
@RequestMapping("/log")
public class OperationLogController {
    @Resource
    private LoginOperationLogService loginOperationLogService;
    @Resource
    private OperationLogService operationLogService;
    /**
     * 操作日志列表
     * @param pageRequest
     * @return
     */
    @ApiOperation(value = "操作日志列表")
    @PostMapping("list")
    public JsonResult<Object> OperationLogListPage(@RequestBody @Valid PageRequest pageRequest) {
        List<OperationLog> operationLogPage = operationLogService.getOperationLogPage(pageRequest);
        PageInfo pageInfo = new PageInfo(operationLogPage);
        PageResult pageResult = PageUtil.getPageResult(pageRequest, pageInfo);
        return JsonResult.success(pageResult);
    }
    /**
     * 登录日志列表
     * @param pageRequest
     * @return
     */
    @ApiOperation(value = "登录日志列表")
    @PostMapping("list")
    public JsonResult<Object> LoginOperationLogListPage(@RequestBody @Valid PageRequest pageRequest) {
        List<LoginOperationLog> loginOperationLogPage = loginOperationLogService.getLoginOperationLogPage(pageRequest);
        PageInfo pageInfo = new PageInfo(loginOperationLogPage);
        PageResult pageResult = PageUtil.getPageResult(pageRequest, pageInfo);
        return JsonResult.success(pageResult);
    }
}

好啦,准备工作基本上完成了,接下来我们再登录的时候插入我们的登录日志即可。

7、登录日志编写

打开我们的UserController.java类,然后找到我们的登录方法,我们再UserController中新添加一个方法,用来获取登录信息并且将登录的信息插入到登录日志表中。我们设计的表里有要获取浏览器类型和操作系统,所以我们使用了user-agent-utils 是一个用来解析 User-Agent 字符串的 Java 类库。 其能够识别的内容包括: 超过150种不同的浏览器; 7种不同的浏览器类型; 超过60种不同的操作系统; 6种不同的设备类型; 9种不同的渲染引擎; 9种不同的Web应用,如HttpClient、Bot。


1、添加maven

<dependency>
    <groupId>eu.bitwalker</groupId>
    <artifactId>UserAgentUtils</artifactId>
    <version>1.21</version>
 </dependency>

2、客户端工具类

package com.blog.personalblog.util;
import cn.hutool.core.convert.Convert;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
 * 客户端工具类
 *
 */
public class ServletUtils {
    /**
     * 获取String参数
     */
    public static String getParameter(String name)
    {
        return getRequest().getParameter(name);
    }
    /**
     * 获取String参数
     */
    public static String getParameter(String name, String defaultValue)
    {
        return Convert.toStr(getRequest().getParameter(name), defaultValue);
    }
    /**
     * 获取Integer参数
     */
    public static Integer getParameterToInt(String name)
    {
        return Convert.toInt(getRequest().getParameter(name));
    }
    /**
     * 获取Integer参数
     */
    public static Integer getParameterToInt(String name, Integer defaultValue)
    {
        return Convert.toInt(getRequest().getParameter(name), defaultValue);
    }
    /**
     * 获取request
     */
    public static HttpServletRequest getRequest()
    {
        return getRequestAttributes().getRequest();
    }
    /**
     * 获取response
     */
    public static HttpServletResponse getResponse()
    {
        return getRequestAttributes().getResponse();
    }
    /**
     * 获取session
     */
    public static HttpSession getSession()
    {
        return getRequest().getSession();
    }
    public static ServletRequestAttributes getRequestAttributes()
    {
        RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
        return (ServletRequestAttributes) attributes;
    }
}

下面进行解析agent字符串

UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));

其他的也没有什么,下面就是我们添加登录日志的方法

    /**
     * 获取登录日志
     */
    public void getLoginInfoLog(LoginModel loginModel, Integer status) {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = (HttpServletRequest) Objects.requireNonNull(requestAttributes).resolveReference(RequestAttributes.REFERENCE_REQUEST);
        //解析agent字符串
        UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
        //登录账号
        LoginOperationLog loginOperationLog = new LoginOperationLog();
        loginOperationLog.setLoginName(loginModel.getUsername());
        //登录IP地址
        String ipAddr = IpUtil.getIpAddr(request);
        loginOperationLog.setIpAddress(ipAddr);
        //登录地点
        String ipInfo = IpUtil.getIpInfo(ipAddr);
        loginOperationLog.setLoginLocation(ipInfo);
        //浏览器类型
        String browser = userAgent.getBrowser().getName();
        loginOperationLog.setBrowserType(browser);
        //操作系统
        String os = userAgent.getOperatingSystem().getName();
        loginOperationLog.setOs(os);
        //登录状态
        loginOperationLog.setLoginStatus(status);
        loginOperationLogService.saveOperationLog(loginOperationLog);
    }

然后我们在登录的方法中添加这个方法,一共传了两个参数,其中status是登录的状态,成功是0,失败是1。

    /**
     * 登录
     * @param loginModel
     * @return
     */
    @ApiOperation(value = "登录")
    @PostMapping("/login")
    @OperationLogSys(desc = "登录", operationType = OperationType.LOGIN)
    public JsonResult<Object> login(@RequestBody LoginModel loginModel){
        logger.info("{} 在请求登录! ", loginModel.getUsername());
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(loginModel.getUsername(), loginModel.getPassword(), false);
        try {
            subject.login(token);
            Map<String, Object> ret = new HashedMap();
            ret.put("token", subject.getSession().getId());
            logger.info("{} login success", loginModel.getUsername());
            getLoginInfoLog(loginModel, 0);
            return JsonResult.success(ret);
        } catch (IncorrectCredentialsException e) {
            logger.info("login fail {}", e.getMessage());
            return JsonResult.error(ErrorCode.NOT_LOGIN);
        } catch (LockedAccountException e) {
            logger.info("login fail {}", e.getMessage());
            return JsonResult.error(ErrorCode.ERROR_CODE);
        } catch (AuthenticationException e) {
            logger.info("login fail {}", e.getMessage());
            return JsonResult.error(ErrorCode.USER_NOT_EXIST);
        } catch (Exception e) {
            e.printStackTrace();
            getLoginInfoLog(loginModel, 1);
            logger.info("login fail {}", e.getMessage());
            return JsonResult.error(ErrorCode.ERROR_CODE);
        }
    }

下面是UserController的完整代码:(有些地方改了一点,大家可以看一下)

package com.blog.personalblog.controller;
import cn.hutool.core.util.StrUtil;
import com.blog.personalblog.annotation.OperationLogSys;
import com.blog.personalblog.annotation.OperationType;
import com.blog.personalblog.entity.ErrorCode;
import com.blog.personalblog.entity.LoginModel;
import com.blog.personalblog.entity.LoginOperationLog;
import com.blog.personalblog.service.LoginOperationLogService;
import com.blog.personalblog.util.IpUtil;
import com.blog.personalblog.util.JsonResult;
import com.blog.personalblog.entity.User;
import com.blog.personalblog.service.UserService;
import com.blog.personalblog.util.MD5Util;
import com.blog.personalblog.util.PhoneUtil;
import com.blog.personalblog.util.ServletUtils;
import eu.bitwalker.useragentutils.UserAgent;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.collections.map.HashedMap;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
 * @author: SuperMan
 * 欢迎关注我的公众号:码上言
 * @create: 2021-11-03
 */
@Api(tags = "用户管理")
@RestController
@RequestMapping("/user")
public class UserController {
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    @Resource
    private UserService userService;
    @Resource
    private LoginOperationLogService loginOperationLogService;
    /**
     * 用户列表
     * @return
     */
    @ApiOperation(value = "用户列表")
    @PostMapping("/list")
    public JsonResult<Object> list() {
        List<User> userList = userService.findAll();
        return JsonResult.success(userList);
    }
    /**
     * 添加用户
     * @return
     */
    @ApiOperation(value = "添加用户")
    @PostMapping("/create")
    @OperationLogSys(desc = "添加用户", operationType = OperationType.INSERT)
    public JsonResult<Object> userCreate(@RequestBody @Valid User user) {
        if (StrUtil.isEmpty(user.getPassWord())) {
            return JsonResult.error("密码为空,请填写密码!");
        }
        //密码加密存储
        user.setPassWord(MD5Util.MD5(user.getPassWord()));
        //判断手机号,这里用hutool工具类也可以
        if (!PhoneUtil.checkMobile(user.getPhone())) {
            return JsonResult.error("手机号码格式错误!");
        }
        userService.createUser(user);
        return JsonResult.success();
    }
    /**
     *
     * 修改用户
     * @return
     */
    @ApiOperation(value = "修改用户")
    @PostMapping("/update")
    @OperationLogSys(desc = "修改用户", operationType = OperationType.UPDATE)
    public JsonResult<Object> userUpdate(@RequestBody @Valid User user) {
        if (StrUtil.isEmpty(user.getPassWord())) {
            return JsonResult.error("密码为空,请填写密码!");
        }
        //密码加密存储
        user.setPassWord(MD5Util.MD5(user.getPassWord()));
        //判断手机号,这里用hutool工具类也可以
        if (!PhoneUtil.checkMobile(user.getPhone())) {
            return JsonResult.error("手机号码格式错误!");
        }
        userService.updateUser(user);
        return JsonResult.success();
    }
    /**
     * 删除
     * @return
     */
    @ApiOperation(value = "删除用户")
    @PostMapping("/delete/{id}")
    @OperationLogSys(desc = "删除用户", operationType = OperationType.DELETE)
    public JsonResult<Object> userDelete(@PathVariable(value = "id") int id) {
        userService.deleteUser(id);
        return JsonResult.success();
    }
    /**
     * 登录
     * @param loginModel
     * @return
     */
    @ApiOperation(value = "登录")
    @PostMapping("/login")
    @OperationLogSys(desc = "登录", operationType = OperationType.LOGIN)
    public JsonResult<Object> login(@RequestBody LoginModel loginModel){
        logger.info("{} 在请求登录! ", loginModel.getUsername());
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(loginModel.getUsername(), loginModel.getPassword(), false);
        try {
            subject.login(token);
            Map<String, Object> ret = new HashedMap();
            ret.put("token", subject.getSession().getId());
            logger.info("{} login success", loginModel.getUsername());
            getLoginInfoLog(loginModel, 0);
            return JsonResult.success(ret);
        } catch (IncorrectCredentialsException e) {
            logger.info("login fail {}", e.getMessage());
            return JsonResult.error(ErrorCode.NOT_LOGIN);
        } catch (LockedAccountException e) {
            logger.info("login fail {}", e.getMessage());
            return JsonResult.error(ErrorCode.ERROR_CODE);
        } catch (AuthenticationException e) {
            logger.info("login fail {}", e.getMessage());
            return JsonResult.error(ErrorCode.USER_NOT_EXIST);
        } catch (Exception e) {
            e.printStackTrace();
            getLoginInfoLog(loginModel, 1);
            logger.info("login fail {}", e.getMessage());
            return JsonResult.error(ErrorCode.ERROR_CODE);
        }
    }
    /**
     * 登录info信息
     * @return
     */
    @GetMapping("/info")
    public JsonResult<Object> info(){
        Map<String, Object> ret = new HashMap<>(3);
        ret.put("roles", "[admin]");
        ret.put("name", "admin");
        ret.put("avatar","https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif");
        return JsonResult.success(ret);
    }
    /**
     * 获取登录日志
     */
    public void getLoginInfoLog(LoginModel loginModel, Integer status) {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = (HttpServletRequest) Objects.requireNonNull(requestAttributes).resolveReference(RequestAttributes.REFERENCE_REQUEST);
        //解析agent字符串
        UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
        //登录账号
        LoginOperationLog loginOperationLog = new LoginOperationLog();
        loginOperationLog.setLoginName(loginModel.getUsername());
        //登录IP地址
        String ipAddr = IpUtil.getIpAddr(request);
        loginOperationLog.setIpAddress(ipAddr);
        //登录地点
        String ipInfo = IpUtil.getIpInfo(ipAddr);
        loginOperationLog.setLoginLocation(ipInfo);
        //浏览器类型
        String browser = userAgent.getBrowser().getName();
        loginOperationLog.setBrowserType(browser);
        //操作系统
        String os = userAgent.getOperatingSystem().getName();
        loginOperationLog.setOs(os);
        //登录状态
        loginOperationLog.setLoginStatus(status);
        loginOperationLogService.saveOperationLog(loginOperationLog);
    }
}

8、测试

我们在postman中模拟登录,然后我们在sql中查看有没有登录日志,这里要说一下,如果你是用的地址为localhost或者127.0.0.1进行请求,我们在获取ip归属地的时候会获取不到,我们可以使用电脑的ip就可以看到。好啦,到这里我们的操作日志就完成了,到此我们所有的后端功能都开发完了,下面我们就写前端代码,后端提供api即可,我们的项目开发2/3了,即将完成了,大家努力啊。

看到现在的阅读量,着实有点惨不忍睹,希望大家多多点赞、收藏、分享啊,大家帮我宣传一下,感谢感谢!

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
7天前
|
Java 中间件
SpringBoot入门(6)- 添加Logback日志
SpringBoot入门(6)- 添加Logback日志
40 5
|
1月前
|
Cloud Native Java C++
Springboot3新特性:开发第一个 GraalVM 本机应用程序(完整教程)
文章介绍如何在Spring Boot 3中利用GraalVM将Java应用程序编译成独立的本机二进制文件,从而提高启动速度、减少内存占用,并实现不依赖JVM运行。
179 1
Springboot3新特性:开发第一个 GraalVM 本机应用程序(完整教程)
|
1月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,包括版本兼容性、安全性、性能调优等方面。
137 1
|
16天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。首先,创建并配置 Spring Boot 项目,实现后端 API;然后,使用 Ant Design Pro Vue 创建前端项目,配置动态路由和菜单。通过具体案例,展示了如何快速搭建高效、易维护的项目框架。
94 62
|
14天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,帮助开发者提高开发效率和应用的可维护性。
32 2
|
14天前
|
JSON Java 数据库
SpringBoot项目使用AOP及自定义注解保存操作日志
SpringBoot项目使用AOP及自定义注解保存操作日志
30 1
|
16天前
|
JavaScript Java 项目管理
Java毕设学习 基于SpringBoot + Vue 的医院管理系统 持续给大家寻找Java毕设学习项目(附源码)
基于SpringBoot + Vue的医院管理系统,涵盖医院、患者、挂号、药物、检查、病床、排班管理和数据分析等功能。开发工具为IDEA和HBuilder X,环境需配置jdk8、Node.js14、MySQL8。文末提供源码下载链接。
|
1月前
|
Java API Apache
Springboot+shiro,完整教程,带你学会shiro
这篇文章提供了一个完整的Apache Shiro与Spring Boot结合使用的教程,包括Shiro的配置、使用以及在非Web和Web环境中进行身份验证和授权的示例。
64 2
Springboot+shiro,完整教程,带你学会shiro
|
1月前
|
前端开发 Java Apache
Springboot整合shiro,带你学会shiro,入门级别教程,由浅入深,完整代码案例,各位项目想加这个模块的人也可以看这个,又或者不会mybatis-plus的也可以看这个
本文详细讲解了如何整合Apache Shiro与Spring Boot项目,包括数据库准备、项目配置、实体类、Mapper、Service、Controller的创建和配置,以及Shiro的配置和使用。
281 1
Springboot整合shiro,带你学会shiro,入门级别教程,由浅入深,完整代码案例,各位项目想加这个模块的人也可以看这个,又或者不会mybatis-plus的也可以看这个
|
21天前
|
JSON Java Maven
实现Java Spring Boot FCM推送教程
本指南介绍了如何在Spring Boot项目中集成Firebase云消息服务(FCM),包括创建项目、添加依赖、配置服务账户密钥、编写推送服务类以及发送消息等步骤,帮助开发者快速实现推送通知功能。
53 2

热门文章

最新文章