【Spring练习项目】博客系统

news2024/11/18 3:34:27

目录

  • 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;

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

电影《封神》如何应用3D人脸扫描设备进行影视制作?

在电影《封神》中伐纣大战的魔家四将的四个角色在影片中一出现&#xff0c;便吸引了观众的所有目光&#xff0c;这逼真的魔家四将的制作前期是从寺庙、文献中收集了四大天王众多的造型和画像&#xff0c;并且还会依据演员的面貌、面部特征适当地优化。 因此在制作中还需要通过扫…

WAF绕过-AWVS+Xray+Goby+sqlmap-绕过宝塔防火墙

WAF绕过主要集中在信息收集&#xff0c;漏洞发现&#xff0c;漏洞利用&#xff0c;权限控制四个阶段。 1、什么是WAF&#xff1f; Web Application Firewall&#xff08;web应用防火墙&#xff09;&#xff0c;一种公认的说法是“web应用防火墙通过执行一系列针对HTTP/HTTPS的安…

【1++的C++进阶】之多态

&#x1f44d;作者主页&#xff1a;进击的1 &#x1f929; 专栏链接&#xff1a;【1的C进阶】 文章目录 一&#xff0c;什么是多态&#xff1f;二&#xff0c;剖析多态的调用原理三&#xff0c;抽象类四&#xff0c;多继承中的虚函数表 一&#xff0c;什么是多态&#xff1f; …

【LeetCode 75】第十九题(724)寻找数组的中心下标

目录 题目: 示例: ​分析: 代码运行结果: 题目: 示例: 分析: 给一个数组,让我们找出一个下标,在这个下标左边的元素总和等于这个下标右边的元素总和. 我们可以把整个数组的总和求出来,然后再从左往右遍历一次数组,遍历的同时将遍历过的数累加记录到一个变量中.若遍历到一…

【C语言进阶】数据的存储----整型篇

​ &#x1f341; 博客主页:江池俊的博客 &#x1f4ab;收录专栏&#xff1a;C语言——探索高效编程的基石 &#x1f4bb; 其他专栏&#xff1a;数据结构探索 ​&#x1f4a1;代码仓库&#xff1a;江池俊的代码仓库 &#x1f3aa; 社区&#xff1a;GeekHub &#x1f341; 如果觉…

数据库索引失效的情况

1.对添加了索引的字段进行函数运算 2.如果是字符串类型的字段&#xff0c;如果不加单引号也会导致索引失效 3.如果最索引字段使用模糊查询&#xff0c;如果是头部模糊索引将失效&#xff0c;如果是尾部模糊索引则正常 4.如果使用or分割符&#xff0c;如果or前面的条件中的列有…

JUC并发编程(二)ForkJoinPool、Future、CompletableFuture、CAS

文章目录 ForkJoin分治工作窃取ForkJoinPool与ThreadPoolExecutor使用案例不带返回值的计算--RecursiveAction带返回值的计算--RecursiveTask Future 异步回调烧水案例join实现FutureTask实现 CompletableFuture为什么叫CompletableFuture?创建异步任务supplyAsyncrunAsync获取…

Vue插槽 、自定义指令、render函数、过滤器和插件

目录 插槽 自定义指令 directive 全局注册 局部注册 钩子函数 render渲染函数 过滤器 插件 plugin 插槽 普通插槽&#xff0c;具名插槽&#xff0c;作用域插槽 插槽允许我们在调用子组件的时候为子组件传递模板。 <slot> 元素作为承载分发内容的出口。 一个不带…

双链表(带哨兵位头节点)

目录 ​编辑 双链表的初始化&#xff1a; 双链表的打印&#xff1a; 双链表的尾插&#xff1a; 双链表的头插&#xff1a; 双链表的尾删&#xff1a; 双链表的头删&#xff1a; 双链表pos位置之前的插入&#xff1a; 双链表pos位置的删除&#xff1a; 关于顺序表和链表…

MyBatis-Plus实现分页查询

目录 MyBatis-Plus实现分页查询 代码 定义一个MyBatis-Plus拦截器 在连接数据库的配置文件中添加MyBatis-Plus日志查看MyBatis-Plus的SQL语句 测试 运行结果 MyBatis-Plus实现分页查询 代码 定义一个MyBatis-Plus拦截器 package com.dong.config;import com.baomidou.my…

windows下mysql的下载与安装

文章目录 1 下载2 安装目录下新建data文件夹和my.ini3 安装4设置密码与远程连接5 配置环境变量6 navicate连接成功 1 下载 官网地址 https://www.mysql.com/点击下载 社区下载 社区服务 选择版本下载 2 安装目录下新建data文件夹和my.ini my.ini 内容如下 [mysql] # 设置my…

iphone内存不足导致白苹果?可以使用这2种办法解决!

因为iPhone内存不足没及时清理导致打开任何软件闪退&#xff0c;这时很多小伙伴会重启手机来解决闪退问题&#xff0c;但就会出现白苹果问题&#xff0c;无法正常进入手机系统、实现任何操作的一种状态。 内存不足导致iPhone白苹果的问题很常见&#xff0c;可以说是苹果最常见…

linux 文件的权限

修改文件的权限 我这里有一个test.txt 文件&#xff0c;我们ll 查看一下该文件相应的属性信息 其中&#xff0c;权限的位置是相对固定的即&#xff1a; 第一个位置是r 权限&#xff0c;代表可读权限。 第二个位置是w权限&#xff0c;代表可修改权限。 第三个位置是x权限&…

【腾讯云 Cloud Studio 实战训练营】从零开始搭建一个数据大屏

文章目录 前言得到什么?使用Cloud Studio登录Cloud Studio登录方式Cloud Studio 功能介绍项目创建配置描述新建工作空间绑定Coding创建仓库绑定coding创建项目项目空间 项目搭建nuxt 脚手架Cloud Studio 安装插件nuxt初始项目预览问题描述 下载Datav 并体验页面结构展示 获取基…

【项目 线程2】3.5 线程的分离 3.6线程取消 3.7线程属性

3.5 线程的分离 #include <stdio.h> #include <pthread.h> #include <string.h> #include <unistd.h>void * callback(void * arg) {printf("chid thread id : %ld\n", pthread_self());return NULL; }int main() {// 创建一个子线程pthread…

Vue3基础_响应式数据

setup是组合式API 选项式API&#xff0c;是data,methods,computed&#xff0c;watch等等全都是分开的&#xff0c;但是组合式API是把这些东西全都写在一起了。 1 vue2的缺点 (1)使用vue2 Vue2版本对数据的拦截用的是Object.defineProperty, 可以监测到对象的变化。因为o…

Spring源码篇(九)自动配置扫描class的原理

文章目录 前言ClassLoader如何加载jar包里的class自动配置扫描class的原理spring中的加载方式源码总结 前言 spring是怎样通过ComponentScan&#xff0c;或者自动配置扫描到了依赖包里class的&#xff1f; ClassLoader 这里涉及到了class Loader的机制&#xff0c;有些复杂&…

信必优行业服务能力-中国头部综合性证券公司

近期召开的国家高层会议提出 “要活跃资本市场&#xff0c;提振投资者信心”&#xff0c;明确了下一阶段资本市场发展新任务、新要求&#xff0c;资本市场有望呈现新气象、新风貌。各证券公司积极响应&#xff0c;全力推进资本市场回暖&#xff1b;同时各公司也借此东风修炼内功…

【科普知识】了解电机T型速度曲线和S型速度曲线的区别!

当电机从静止状态启动并加速到额定转速时&#xff0c;其速度变化并非线性的&#xff0c;而是呈现出不同的曲线特征。T型速度曲线和S型速度曲线是两种典型的电机加速曲线类型。那它们之间有什么区别呢&#xff1f;今天&#xff0c;就让我们来深入探讨电机加速曲线的奥秘。 电机速…

国内是不是很缺音视频的开发人员,想学习音视频开发

第一、音视频开发人员的培养是一个长期投入&#xff0c;见效慢的过程&#xff0c;不像有些培训机构&#xff0c;半年培训就可以出去找工作了。同时培训机构最终的目的是快速培训&#xff0c;推荐工作然后挣钱。而音视频开发见效太慢&#xff0c;没有一定时间的锻炼和项目喂养&a…