【Spring练习项目】博客系统

目录

  • 1.项目展示
  • 2.项目结构设计
  • 3.项目功能设计
  • 4 数据库准备
    • 4.1 建表
    • 4.2 DB相关数据
  • 5.项目模块
  • 6.添加项目公共模块
    • 6.1 common
    • 6.2 实现前端界面
  • 7.功能实现
    • 7.1实现博客列表
      • 约定前后端交互接口
      • 实现服务器代码
      • 实现客户端代码
    • 7.2实现博客详情
      • 约定前后端交互接口
      • 实现服务器代码
      • 实现客户端代码
    • 7.3实现登录
      • 约定前后端交互接口
      • 实现服务器代码
      • 实现客户端代码
    • 7.4实现强制要求登录
      • 添加拦截器
      • 实现客户端代码
    • 7.5实现显示用户信息
      • 约定前后端交互接口
      • 实现服务器代码
    • 7.6实现用户退出
      • 约定前后端交互接口
      • 实现服务器代码
      • 实现客户端代码
    • 7.7实现发布博客
      • 约定前后端交互接口
      • 实现服务器代码
      • 实现客户端代码
    • 7.8实现删除/编辑博客
      • 约定前后端交互接口
      • 实现服务器代码
      • 实现客户端代码
    • 7.9实现加密加盐
      • 加密工具类
      • 使用
      • 修改数据库密码

1.项目展示

项目已经发布到云服务器上,想要使用的小伙伴可以点击下面这个链接:

博客项目

由于目前没有实现注册功能,所以这里直接提供一个账号,用以登录:

账号:lisi
密码:123456

2.项目结构设计

后端框架:SpringBoot
数据库:mybatis
前后端交互:ajax

3.项目功能设计

主要功能如下图所示:

在这里插入图片描述

一共四个页面:
在这里插入图片描述
登录页面:

在这里插入图片描述

博客列表页面:

在这里插入图片描述
博客详情页:
在这里插入图片描述

写博客页面:

在这里插入图片描述

4 数据库准备

4.1 建表

一共两张表:

  • user(用户表)

  • blog(博客表)

在这里插入图片描述

创建数据库:

create database if not exists `java_blog_spring` charset utf8mb4;

创建user表:

drop table if exists `java_blog_spring`.`user`;
CREATE TABLE `java_blog_spring`.`user` (
 `id` INT NOT NULL AUTO_INCREMENT,
 `user_name` VARCHAR(128) NOT NULL,
 `password` VARCHAR(128) NOT NULL,
 `github_url` VARCHAR(128) NULL,
 `delete_flag` TINYINT(4) NULL DEFAULT 0,
 `create_time` TIMESTAMP NULL DEFAULT current_timestamp(),
 PRIMARY KEY (`id`),
 UNIQUE INDEX `user_name_UNIQUE` (`user_name` ASC))
ENGINE = InnoDB DEFAULT CHARACTER SET = utf8mb4 COMMENT = '⽤户表';

创建blog表:

drop table if exists `java_blog_spring`.`blog`;
CREATE TABLE `java_blog_spring`.`blog` (
 `id` INT NOT NULL AUTO_INCREMENT,
 `title` VARCHAR(200) NULL,
 `content` TEXT NULL,
 `user_id` INT(11) NULL,
 `delete_flag` TINYINT(4) NULL DEFAULT 0,
 `create_time` TIMESTAMP NULL DEFAULT current_timestamp(),
 PRIMARY KEY (`id`))
ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT = '博客表';

增加一些测试数据:

insert into `java_blog_spring`.`user` (`user_name`, `password`,`github_url
`)values("zhangsan","123456","https://gitee.com/bubble-fish666/class-java4
5");
insert into `java_blog_spring`.`user` (`user_name`, `password`,`github_url
`)values("lisi","123456","https://gitee.com/bubble-fish666/class-java45");
insert into `java_blog_spring`.`blog` (`title`,`content`,`user_id`) values
("第⼀篇博客","111我是博客正⽂我是博客正⽂我是博客正⽂",1);
insert into `java_blog_spring`.`blog` (`title`,`content`,`user_id`) values
("第⼆篇博客","222我是博客正⽂我是博客正⽂我是博客正⽂",2);

4.2 DB相关数据

DB相关查询:

  1. 获取所有博客列表
  2. 根据博客Id获取博客详情
  3. 插⼊博客
  4. 更新博客
  5. 根据id查询user信息
  6. 根据name查询user信息

User类:

@Data
public class User {
    private Integer id;
    private String userName;
    private String password;
    private String githubUrl;
    private Byte deleteFlag;
    private Date createTime;
}

Blog类:

@Data
public class Blog {
    private Integer id;
    private String title;
    private String content;
    private Integer userId;
    private Integer deleteFlag;
    private Date createTime;
    //是否为登录用户,1表示为登录用户
    private Integer loginUser;

    public String getCreateTime() {
        //对时间进行格式化
        return DateUtils.formatDate(createTime);
    }
}

UserMapper类:

@Mapper
public interface UserMapper {
    @Select("select id,user_name,password,github_url,delete_flag,create_time from user where delete_flag=0 and id=#{id}")
    User selectById(Integer id);

    @Select("select id,user_name,password,github_url,delete_flag,create_time from user where delete_flag=0 and user_name=#{name}")
    User selectByName(String name);
}

BlogMapper类:

@Mapper
public interface BlogMapper {

    @Select("select * from blog where delete_flag=0")
    List<Blog> selectAllBlog();

    @Select("select * from blog where delete_flag=0 and id=#{blogId}")
    Blog selectBlogById(Integer blogId);

    Integer updateBlog(Blog blog);

    @Insert("insert into blog(title,content,user_id) values (#{title},#{content},#{userId})")
    Integer insertBlog(Blog blog);
}

BlogMapper.xml:

<mapper namespace="com.example.springblog.mapper.BlogMapper">
    <update id="updateBlog">
        update blog
        <set>
            <if test="title!=null">
                title=#{title},
            </if>
            <if test="content!=null">
                content=#{content},
            </if>
            <if test="userId!=null">
                user_id=#{userId},
            </if>
            <if test="deleteFlag!=null">
                delete_flag=#{deleteFlag},
            </if>
        </set>
        where id=#{id}
    </update>
</mapper>

5.项目模块

在这里插入图片描述

6.添加项目公共模块

6.1 common

统一异常抽取为一个类:

@Data
public class Result {
    //业务处理状态码  200成功  <=0失败
    private Integer code;
    //业务返回提示信息
    private String msg;
    //业务返回数据
    private Object data;

    /**
     * 失败时处理内容
     * @return
     */
    public static  Result fail(Integer code,String msg) {
        Result result=new Result();
        result.setCode(code);
        result.setMsg(msg);
        result.setData("");
        return result;
    }

    public static  Result fail(Integer code,String msg,Object data) {
        Result result=new Result();
        result.setCode(code);
        result.setMsg(msg);
        result.setData(data);
        return result;
    }

    /**
     * 业务处理成功
     * @param data
     * @return
     */
    public static  Result success(Object data) {
        Result result=new Result();
        result.setCode(200);
        result.setMsg("");
        result.setData(data);
        return result;
    }

    public static  Result success(String msg,Object data) {
        Result result=new Result();
        result.setCode(200);
        result.setMsg(msg);
        result.setData(data);
        return result;
    }
}

出错时统一异常处理:

@ControllerAdvice
public class ErrorAdvice {

    @ExceptionHandler
    public Result error(Exception e){
        return Result.fail(-1,e.getMessage());
    }
}

数据统一返回格式:

@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {
    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return true;
    }
    //在数据返回之前进行处理
    @SneakyThrows  //异常处理注解
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        if(body instanceof Result){
            return body;
        }
        if(body instanceof String){
            ObjectMapper objectMapper=new ObjectMapper();
            return objectMapper.writeValueAsString(Result.success(body));
        }
        return Result.success(body);
    }
}

6.2 实现前端界面

把之前写好的博客系统静态⻚⾯拷⻉到static⽬录下:

在这里插入图片描述

7.功能实现

7.1实现博客列表

约定前后端交互接口

[请求]
/blog/getlist
[响应]
[
 {
 blogId: 1,
 title: "第⼀篇博客",
 content: "博客正⽂",
 userId: 1,
 postTime: "2021-07-07 12:00:00"
 },
 {
 blogId: 2,
 title: "第⼆篇博客",
 content: "博客正⽂",
 userId: 1,
 postTime: "2021-07-07 12:10:00"
 },
 ...
]

我们约定, 浏览器给服务器发送⼀个 /blog/getlist 这样的 HTTP 请求, 服务器给浏览器返回了⼀个 JSON 格式的数据.

实现服务器代码

在 BlogController 中添加⽅法:

@Slf4j
@RequestMapping("/blog")
@RestController
public class BlogController {

    @Autowired
    private BlogService blogService;

    @RequestMapping("/getlist")
    public List<Blog> getBlogList(){
        return blogService.selectAllBlog();
    }
}

在BlogService 中添加⽅法:

public class BlogService {

    @Autowired
    private BlogMapper blogMapper;

    public List<Blog> selectAllBlog(){
        return blogMapper.selectAllBlog();
    }
}

部署程序, 验证服务器是否能正确返回数据 (使⽤ URL http://127.0.0.1:8080/blog/getlist 即可)

实现客户端代码

修改 blog_list.html, 删除之前写死的博客内容, 并新增js 代码处理 ajax 请求.

    <script src="./js/jquery.min.js"></script>
    <script src="./js/common.js"></script>
    <script>
        $.ajax({
            type:"get",
            url:"/blog/getlist",
            success:function(result){
                if(result.code==200 && result.data!=null && result.data.length>0){
                    var blogs=result.data;
                    var finalHtml="";
                    for(var blog of blogs){
                        finalHtml += '<div class="blog">';
                        finalHtml += '<div class="title">'+blog.title+'</div>'
                        finalHtml += '<div class="date">'+blog.createTime+'</div>'
                        finalHtml += '<div class="desc">'+blog.content+'</div>'
                        finalHtml += '<a class="detail" href="blog_detail.html?blogId='+blog.id+'">查看全文&gt;&gt;</a>'
                        finalHtml += '</div>'
                    }
                    $(".right").html(finalHtml);
                }
            },
            error:function(error){
                console.log(error);
                if(error!=null && error.status==401){
                    //用户未登录
                    location.assign("blog_login.html");
                }
            }
        });
        var url="/user/getUserInfo";
        getUserInfo(url);
    </script>

7.2实现博客详情

⽬前点击博客列表⻚的 “查看全⽂” , 能进⼊博客详情⻚, 但是这个博客详情⻚是写死的内容. 我们期望能够根据当前的 博客 id 从服务器动态获取博客内容.

约定前后端交互接口

/blog/getBlogDetail?blogId=1
[响应]
{
 blogId: 1,
 title: "第⼀篇博客",
 content: "博客正⽂",
 userId: 1,
 postTime: "2021-07-07 12:00:00"
}

实现服务器代码

在 BlogController 中添加getBlogDeatail ⽅法:

   /**
     * 获取博客详情
     * @param blogId
     * @return
     */
    @RequestMapping("/getBlogDetail")
    public Result getBlogDetail(Integer blogId,HttpSession session){
        log.info("blogId:"+blogId);
        if(blogId == null){
            return Result.fail(-1,"非法博客id");
        }
        Blog blog=blogService.selectBlogById(blogId);
        //获取登录用户信息
        User loginUser=(User) session.getAttribute(Constants.USER_INFO_SESSION);
        //判断登录用户和博客作者是否是同一个人
        if(loginUser!=null && loginUser.getId()== blog.getUserId()){
            blog.setLoginUser(1);
        }
        return Result.success(blog);
    }

在BlogService 中添加getBlogDeatil⽅法:

    public Blog selectBlogById(Integer blogId){
        return blogMapper.selectBlogById(blogId);

    }

实现客户端代码

    <script>
        $.ajax({
            type:"get",
            url:"/blog/getBlogDetail"+location.search,
            success:function(result){
                if(result.code==200 && result.data!=null){
                    var blog=result.data;
                    $(".title").text(blog.title);
                    $(".date").text(blog.createTime);
                    editormd.markdownToHTML("content", {
                        markdown: blog.content ,
                    });
                    //$(".detail").text(blog.content);
                    if(blog.loginUser==1){
                        var html="";
                        html+= '<button onclick="window.location.href=\'blog_update.html?blogId='+blog.id+'\'">编辑</button>';
                        html+='<button onclick="deleteBlog()">删除</button>';
                        $(".operating").html(html);
                    }
                }
            },
            error:function(error){
                consolo.log(error);
                if(error!=null && error.status==401){
                    //用户未登录
                    location.assign(blog_login.html);
                }
            }
        });
        var url= "/user/getAuthorInfo" + location.search;
        getUserInfo(url);

common.js代码:

function getUserInfo(url){
    $.ajax({
        type:"get",
        url:url,
        success:function(result){
            if(result!=null && result.code==200 && result.data!=null){
                var user=result.data;
                $(".left .card h3").text(user.userName);
                $(".left .card a").attr("href",user.githubUrl);
            }
        }
    });
}

7.3实现登录

  • 登陆⻚⾯提供⼀个 form 表单, 通过 form 的⽅式把⽤户名密码提交给服务器.

  • 服务器端验证⽤户名密码是否正确. 如果密码正确,

  • 则在服务器端创建 Session , 并把 sessionId 通过 Cookie 返回给浏览器

约定前后端交互接口

[请求]
/user/login
username=test&password=123
[响应]
200 登录成功
<0 登录失败

实现服务器代码

在 UserController 中添加⽅法:

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;

    @RequestMapping("/login")
    public Result login(HttpServletRequest request,String username, String password){
        //参数校验
        if(!StringUtils.hasLength(username) || !StringUtils.hasLength(password)){
            return Result.fail(-1,"用户名密码不能为空");
        }
        //验证密码
        User user=userService.selectByName(username);
        if(user==null || !SecurityUtils.decrypt(password,user.getPassword())){
            return Result.fail(-2,"用户名密码错误");
        }
        //设置session
        HttpSession session= request.getSession(true);
        session.setAttribute(Constants.USER_INFO_SESSION,user);
        return Result.success("登录成功");
    }
}

在UserService 中添加⽅法:

@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private BlogMapper blogMapper;

    public User selectByName(String name){
        return userMapper.selectByName(name);
    }
}

实现客户端代码

    <script src="./js/jquery.min.js"></script>
    <script>
        function login(){
            $.ajax({
                type:"post",
                url:"/user/login",
                data:{
                    username:$("#userName").val(),
                    password:$("#password").val()
                },
                success:function(result){
                    if(result.code==200){
                        location.href="blog_list.html";
                        return;
                    }else if(result.code<0 && result.msg!=''){
                        alert(result.msg);
                        return;
                    }
                },
                error:{

                }
            });
        }
    </script>

7.4实现强制要求登录

当⽤户访问 博客列表⻚ 和 博客详情⻚ 时, 如果⽤户当前尚未登陆, 就⾃动跳转到登陆⻚⾯.

添加拦截器

登录拦截器:

@Component
public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HttpSession session=request.getSession(false);
        if(session!=null && session.getAttribute(Constants.USER_INFO_SESSION)!=null){
            //用户已经登录了
            return true; //不拦截
        }
        response.setStatus(401);
        return false;
    }
}

使用拦截器:

@Configuration
public class AppConfig implements WebMvcConfigurer {
    private final List<String> excludePaths = Arrays.asList(
            "/**/*.html",
            "/blog-editormd/**",
            "/css/**",
            "/js/**",
            "/pic/**",
            "/user/login"
    );
    @Autowired
    private LoginInterceptor loginInterceptor;
    //添加拦截器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterceptor)
                .addPathPatterns("/**")  //拦截所有路径
                .excludePathPatterns(excludePaths);  //不拦截excludePaths包括的类型文件
    }
}

实现客户端代码

1.修改 blog_datail.html

  • 访问⻚⾯时, 添加失败处理代码
  • 使⽤ location.assign 进⾏⻚⾯跳转.
			error:function(error){
                console.log(error);
                if(error!=null && error.status==401){
                    //用户未登录
                    location.assign("blog_login.html");
                }
            }

2.修改 blog_list.html

  • 访问⻚⾯时, 添加失败处理代码
  • 使⽤ location.assign 进⾏⻚⾯跳转.
            error:function(error){
                consolo.log(error);
                if(error!=null && error.status==401){
                    //用户未登录
                    location.assign(blog_login.html);
                }
            }

7.5实现显示用户信息

  • 如果当前⻚⾯是博客列表⻚, 则显示当前登陆⽤户的信息.
  • 如果当前⻚⾯是博客详情⻚, 则显示该博客的作者⽤户信息.

约定前后端交互接口

在博客列表⻚, 获取当前登陆的⽤户的⽤户信息.

[请求]
/user/getUserInfo
[响应]
{
userId: 1,
username: test
 ...
}

在博客详情⻚, 获取当前⽂章作者的⽤户信息

[请求]
/user/getAuthorInfo?blogId=1
[响应]
{
userId: 1,
username: test
}

实现服务器代码

在 UserController 中添加⽅法:

    /**
     * 获取登录用户信息
     * @return
     */
    @RequestMapping("/getUserInfo")
    public Result getUserInfo(HttpSession session){
        if(session==null || session.getAttribute(Constants.USER_INFO_SESSION)==null){
            return Result.fail(-1,"用户未登录");
        }
        User user=(User)session.getAttribute(Constants.USER_INFO_SESSION);
        return Result.success(user);
    }

    /**
     * 获取博客作者信息
     * @return
     */
    @RequestMapping("/getAuthorInfo")
    public Result getAuthorInfo(Integer blogId){
        if(blogId==null || blogId<=0){
            return Result.fail(-1,"博客不存在~");
        }
        User user=userService.selectAuthorByBlogId(blogId);
        return Result.success(user);
    }

在UserService 中添加⽅法:

    public User selectAuthorByBlogId(Integer blogId){
        User user=null;
        Blog blog=blogMapper.selectBlogById(blogId);
        if(blog!=null && blog.getUserId()>0){
            user=userMapper.selectById(blog.getUserId());
        }
        if(user!=null){
            user.setPassword("");
        }
        return user;
    }

7.6实现用户退出

约定前后端交互接口

[请求]
/user/logout
[响应]
true

实现服务器代码

在 UserController 中添加⽅法:

    /**
     * 注销
     * @return
     */
    @RequestMapping("/logout")
    public Result logout(HttpSession session){
        session.removeAttribute(Constants.USER_INFO_SESSION);
        return Result.success(true);
    }

实现客户端代码

客户端代码, 注销改为⼀个a标签, href 设置为logout, 点击的时候就会发送GET/logout请求

<a class="nav-span" href="#" onclick="logout()">注销</a>

在common.js中添加logout⽅法:

function logout(){
    $.ajax({
        type:"get",
        url:"/user/logout",
        success:function(result){
            if(result!=null && result.data==true){
                location.href="blog_login.html";
            }
        }
    });
}

7.7实现发布博客

约定前后端交互接口

[请求]
/blog/add
title=标题&content=正⽂...
[响应]
true 成功
false 失败

实现服务器代码

在 BlogController 中添加⽅法:

    /**
     * 发布博客
     * @return
     */
    @RequestMapping("/add")
    public Result addBlog(String title, String content,HttpSession session){
        if(!StringUtils.hasLength(title) || !StringUtils.hasLength(content)){
            return Result.fail(-1,"标题或内容不能为空");
        }
        User user= (User) session.getAttribute(Constants.USER_INFO_SESSION);
        if(user==null || user.getId()<=0){
            return Result.fail(-1,"用户不存在");
        }
        try{
            Blog blog=new Blog();
            blog.setTitle(title);
            blog.setContent(content);
            blog.setUserId(user.getId());
            blogService.insertBlog(blog);
        }catch (Exception e){
            return Result.fail(-1,"博客发布失败~");
        }
        return Result.success(true);
    }

在BlogService 中添加⽅法:

 public Integer insertBlog(Blog blog){
        return blogMapper.insertBlog(blog);
    }

实现客户端代码

给提交按钮添加click事件 <input type=“button” value="发布⽂章"id=“submit” οnclick=“submit()”>

        $("#submit").click(function(){
            $.ajax({
                type:"post",
                url:"/blog/add",
                data:{
                    title:$("#title").val(),
                    content:$("#content").val()
                },
                success:function(result){
                    if(result!=null && result.code==200 && result.data==true){
                        location.href="blog_list.html";
                    }else{
                        alert(result.msg);
                    }
                },
                error:function(error){
                    if(error!=null && error.status==401){
                        alert("请先登录!!!");
                    }
                }
            });
        });

7.8实现删除/编辑博客

进⼊⽤户详情⻚时, 如果当前登陆⽤户正是⽂章作者, 则在导航栏中显示 “删除” 按钮, ⽤户点击时则删除该⽂章.

需要实现两件事:

  • 判定当前博客详情⻚中是否要显示 删除 按钮
  • 实现删除逻辑.

约定前后端交互接口

编辑博客

[请求]
/blog?BlogId=1
[响应]
{
 blogId: 1,
 title: "第⼀篇博客",
 content: "博客正⽂",
 userId: 1,
 postTime: "2021-07-07 12:00:00",
 loginUser: 1
}

删除博客

[请求]
GET /blog/delete?blogId=1
[响应]
true 删除成功

实现服务器代码

在 BlogController 中添加⽅法:

    /**
     * 更新博客
     * @param blog
     * @return
     */
    @RequestMapping("/updateBlog")
    public Result updateBlog(Blog blog){
        if(!StringUtils.hasLength(blog.getTitle()) || !StringUtils.hasLength(blog.getContent()) || blog.getId()==null){
            return Result.fail(-1,"标题或内容不合法");
        }
        blogService.updateBlog(blog);
        return Result.success(true);
    }

    /**
     * 删除博客
     * @return
     */
    @RequestMapping("/deleteBlog")
    public Result deleteBlog(Integer blogId){
        if(blogId==null){
            return Result.fail(-1,"博客不存在~");
        }
        Blog blog=new Blog();
        blog.setId(blogId);
        blog.setDeleteFlag(1);
        blogService.updateBlog(blog);
        return Result.success(true);
    }
}

在BlogService 中添加⽅法:

    public Integer updateBlog(Blog blog){
        return blogMapper.updateBlog(blog);
    }

实现客户端代码

删除博客:

        function deleteBlog(){
            $.ajax({
                type:"post",
                url:"/blog/deleteBlog" + location.search,
                success:function(result){
                    if(result!=null && result.code==200 && result.data==true){
                        location.href="blog_list.html";
                    }else{
                        alert(result.msg);
                    }
                },
                eeror:function(error){
                    if(error!=null && error.status==401){
                    //用户未登录
                    location.assign("blog_login.html");
                }
                }
            });
        }

编辑博客:

        //获取博客的详细内容,并且反应到页面上
        $.ajax({
            type:"get",
            url:"/blog/getBlogDetail" + location.search,
            success:function(result){
                if(result!=null && result.code==200 && result.data!=null){
                    var blog=result.data;
                    $("#blogId").val(blog.id);
                    $("#title").val(blog.title);
                    $("#content").val(blog.content);
                }else if(result!=null){
                    alert(result.msg);
                }
            },
            error:function(error){
                if(error!=null && error.status==401){
                    //用户未登录
                    location.assign(blog_login.html);
                }
            }
        });

        $("#submit").click(function(){
            $.ajax({
                type:"post",
                url:"/blog/updateBlog",
                data:{
                    id:$("#blogId").val(),
                    title:$("#title").val(),
                    content:$("#content").val()
                },
                success:function(result){
                    if(result!=null && result.code==200 && result.data==true){
                        location.href="blog_list.html";
                    }else if(result!=null){
                        alert(result.msg);
                    }
                }
            });
        });
        
    </script>

7.9实现加密加盐

加密工具类

使用md5进行密码加密:

public class SecurityUtils {
    /**
     * 加密
     * 根据明文,返回密文(salt+加密后的密文)
     * @return
     */
    public static String encry(String inputPassword){
        //生成盐值
        String salt= UUID.randomUUID().toString().replace("-","");
        //md5加密(明文+盐值)
        String password= DigestUtils.md5DigestAsHex((inputPassword+salt).getBytes());
        return salt+password;
    }

    /**
     * 验证密码是否正确
     * @return
     */
    public static boolean decrypt(String inputPassword,String finalPassword){
        //判空
        if(!StringUtils.hasLength(inputPassword) || !StringUtils.hasLength(finalPassword)){
            return false;
        }
        //验证长度
        if(finalPassword.length()!=64){
            return false;
        }
        //验证密码
        String salt=finalPassword.substring(0,32);
        String password= DigestUtils.md5DigestAsHex((inputPassword+salt).getBytes());
        return (salt+password).equals(finalPassword);
    }
}

使用

        //验证密码
        User user=userService.selectByName(username);
        if(user==null || !SecurityUtils.decrypt(password,user.getPassword())){
            return Result.fail(-2,"用户名密码错误");
        }

修改数据库密码

使⽤测试类给密码123456⽣成密⽂:
e2377426880545d287b97ee294fc30ea6d6f289424b95a2b2d7f8971216e39b7

执行SQL:

update user set password='e2377426880545d287b97ee294fc30ea6d6f289424b95a2b2
d7f8971216e39b7' where id=1;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/58792.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于图片、无人机、摄像头拍摄进行智能检测功能

根据要求进行无人机拍摄的视频或图片进行智能识别&#xff0c;开发过程需要事项 1、根据图片案例进行标记&#xff0c;进行模型训练 2、视频模型训练 开发语言为python 根据需求功能进行测试结果如下 根据车辆识别标记进行的测试结果截图 测经过查看视频 8月1日

opencv-33 图像平滑处理-中值滤波cv2.medianBlur()

中值滤波是一种常见的图像处理滤波技术&#xff0c;用于去除图像中的噪声。它的原理是用一个滑动窗口&#xff08;也称为卷积核&#xff09;在图像上移动&#xff0c;对窗口中的像素值进行排序&#xff0c;然后用窗口中像素值的中值来替换中心像素的值。这样&#xff0c;中值滤…

【二等奖方案】Web攻击检测与分类识别赛题「机器学习」团队解题思路

2022 CCF BDCI 数字安全公开赛 赛题「Web攻击检测与分类识别」 地址&#xff1a;http://go.datafountain.cn/4Zj 机器学习战队 获奖方案 团队简介 我们团队由五名成员组成&#xff0c;对机器学习都非常感兴趣&#xff0c;同时在机器学习领域有着丰富的实战经验&#xff0c…

LeetCode 42. 接雨水(动态规划 / 单调栈)

题目&#xff1a; 链接&#xff1a;LeetCode 42. 接雨水 难度&#xff1a;困难 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 示例 1&#xff1a; 输入&#xff1a;height [0,1,0,2,1,0,1,3,2,1,2…

爆肝整理,Postman接口测试-参数关联实战(详细步骤)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 接口测试什么时候…

ES6及以上新特性

ES6&#xff08;ECMAScript 2015&#xff09;及以上版本引入了许多新特性&#xff0c;每个版本都有不同的增强和改进。以下是 ES6 及以上版本的新特性的详细描述&#xff1a; ES6&#xff08;ECMAScript 2015&#xff09;&#xff1a; let 和 const 声明&#xff1a;引入块级作…

瑞吉外卖实战-笔记

软件开发的流程 角色分工 软件环境 开发环境的搭建 数据库环境 maven环境 1.创建完成后&#xff0c;需要检查一下编码、maven仓库、jdk等 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</a…

pytorch 中 view 和reshape的区别

在 PyTorch&#xff08;一个流行的深度学习框架&#xff09;中&#xff0c; reshape 和 view 都是用于改变张量&#xff08;tensor&#xff09;形状的方法&#xff0c;但它们在实现方式和使用上有一些区别。下面是它们之间的主要区别&#xff1a; 实现方式&#xff1a; reshap…

机器学习--课后作业--hw1

机器学习(课后作业–hw1) 本篇文章全文参考这篇blog 网上找了很多教程&#xff0c;这个是相对来说清楚的&#xff0c;代码可能是一模一样&#xff0c;只是进行了一些微调&#xff0c;但是一定要理解这个模型具体的处理方法&#xff0c;这个模型我认为最巧妙的它对于数据的处理…

HTTP(超文本传输协议)学习

关于HTTP补学 一、HTTP能干什么 通过下图能够直观的看出&#xff1a;“交换数据 ” 二、HTTP请求例子 一个 HTTP 方法&#xff0c;通常是由一个动词&#xff0c;像 GET、POST 等&#xff0c;或者一个名词&#xff0c;像 OPTIONS、HEAD 等&#xff0c;来定义客户端执行的动作。…

Django之JWT库与SimpleJWT库的使用

Django之JWT库与SimpleJWT库的使用 JWTJWT概述头部(header)载荷(payload)签名(signature) Django使用JWT说明jwt库的使用安装依赖库配置settings.py文件配置urls.py文件创建视图配置权限 SimpleJWT库的使用安装SimpleJWT库配置Django项目配置路由创建用户接口测试身份认证自定义…

MP的开发流程-2

RESTful的实现等级 0级&#xff1a;传统的RPC&#xff0c;基于SOAP的WS&#xff0c;调用的服务名&#xff0c;参数放在HTTP协议的body里面&#xff0c;同时必须以POST方式提交&#xff0c;问题在于你必须清楚的知道所有服务&#xff0c;子服务&#xff0c;及其参数的信息&…

FileZilla Server同时共享多个目录(手把手教你使用FileZilla Server同时设置多个目录)

网上的基本全是一句话带过怎么共享多个目录&#xff0c;没图很烦&#xff0c;所以我自己就写一个过程 目录 1、创建ftp用户并设置密码 1.1、进入用户管理 1.2、新建用户 1.3、设置密码 2、添加共享的目录 2.1、选择用户添加目录 2.2、给予用户访问权限 2.2.1、客户端访…

长相思·罚站墙Vue

优化前 看效果图 Vue长相思 刚学Vue&#xff0c;正好在追剧&#xff0c;看到这个小案例觉得挺好玩的&#xff0c;第一天学&#xff0c;代码太简陋了 代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta…

windows环境下安装elasticsearch、kibana

通过本文可以快速在windows系统上安装elasticsearch、kibana环境。 当你用Integer类型的时候&#xff0c;要非常小心&#xff0c;因为100等于100、但是200不等于200&#xff0c;当然&#xff0c;如果你会一点小花招&#xff0c;也可以让100不等于100、让200等于200。(运算符比较…

全球十大知名看黄金即时行情的软件名单(综合榜单)

在当今的数字化时代&#xff0c;黄金投资已成为一种受欢迎的投资方式。为了获取即时的黄金行情信息&#xff0c;许多投资者开始使用黄金即时行情软件。然而&#xff0c;选择一款合适的软件并不是一件容易的事情。那么&#xff0c;如何选适合自己需求的软件呢&#xff1f;首先&a…

LeetCode344.反转字符串

344.反转字符串 题目描述 解题思路 这是字符串专题的第一题 在之前反转链表的题目中&#xff0c;我们使用了双指针法来进行反转链表 这道题同样的&#xff0c;也使用双指针&#xff0c;对于字符串的反转&#xff0c;比链表更为简单 因为字符串本质上是一种数组&#xff0c…

【嵌入式学习笔记】嵌入式入门5——窗口看门狗WWDG

1.WWDG简介 WWDG的全称&#xff1a;Window watchdog&#xff0c;即窗口看门狗WWDG的本质&#xff1a;能产生系统复位信号和提前唤醒中断的计数器WWDG的特性&#xff1a;递减的计数器&#xff0c;当递减计数器值从 0x40减到0x3F时复位&#xff08;即T6位跳变到0&#xff09;&am…

性能优化-react路由懒加载和组件懒加载

背景 随着项目越来越大&#xff0c;打包后的包体积也越来越大&#xff0c;严重影响了首屏加载速度&#xff0c;需要对路由和组件做懒加载处理 主要用到了react中的lazy和Suspense。 废话不多说&#xff0c;直接上干货 路由懒加载 核心代码 import React, { lazy, Suspens…

三款AI写作宝介绍,教你玩转AI写作

AI写作宝是一款利用人工智能技术自动生成文章的工具。它采用先进的自然语言处理算法&#xff0c;可以在短时间内生成高质量的文章。与传统的写作方式相比&#xff0c;AI写作宝有着更快的速度、更高的准确性和更低的成本&#xff0c;成为了许多人工智能爱好者和写作从业者的首选…