基于Spring实现博客项目

这篇具有很好参考价值的文章主要介绍了基于Spring实现博客项目。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

访问地址:用户登录

代码获取:基于Spring实现博客项目: Spring项目写博客项目 

 一.项目开发

1.项目开发阶段

  1. 需求评审,需求分析
  2. 项目设计(接口设计,DB设计等,比较大的需求,需要设计流程图,用例图,UML, model中的字段)
  3. 开发+自测
  4. 提测(提交测试)
  5. 验收:预发布环境/预生产环境部署测试(开发,测试,产品)
  6. 上线
     

2.前端页面 

1.登录页面: 根据用户名和密码,进行登录
2.博客列表页:显示所有博客列表,以及显示登录用户的个人信息                                                      3.博客详情页:显示当前博客的详细信息,以及作者信息
4.博客插入/编辑页

3.需求分析

1.登录接口(根据用户名和密码,来判断是否登录成功)                                                                       2.根据用户ID,获取用户相关信息
3.获取所有的博客列表
4.根据博客ID,获取博客的详情信息(作者ID)                                                                                     5.根据博客ID,更新博客内容
6.插入博客
7.删除博客

4.数据库设计

        --建表sql
        create database if not exists `java_blog_spring` charset utf8mb4;
        --用户表
        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 = '⽤户表';
        --博客表
        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);

二.Java项目

1.创建Spring项目

基于Spring实现博客项目,Java项目,spring,java,后端

基于Spring实现博客项目,Java项目,spring,java,后端 创建好之后为以下页面

基于Spring实现博客项目,Java项目,spring,java,后端

2.创建实体类

 用户实体类

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

博客实体类 

@Data
public class Blog {
    private Integer id;
    private String title;
    private String content;
    private Integer userId;
    private Byte deleteFlag;
    private Date createTime;
}

3.创建Mapper

userMapper.java

@Mapper
public interface UserMapper {
    @Select("select * from user where id=#{id}")
    User selectById(Integer id);
    @Select("select * from user where user_name=#{name}")
    User selectByName(String name);
}

userMapper.xml

<?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.javastudy.blog_spring.mapper.UserMapper">



</mapper>

blogMapper.java

@Mapper
public interface BlogMapper {
    @Select("select * from blog where delete_flag=0")
    List<Blog> selectAll();

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

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

 blogMapper.xml

<?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.javastudy.blog_spring.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>

4.配置文件

application.yml

spring:
  profiles:
    active: dev

# 日志信息
logging:
  file:
    path: logs/
  level:
    root: info

application-dev.yml

server:
  port: 8080


# 数据库连接配置
spring:
  datasource:
    url: jdbc:mysql://localhost:13306/java_blog_spring?characterEncoding=utf8&useSSL=false
    username: root
    password: woaini520
    driver-class-name: com.mysql.cj.jdbc.Driver

#  mybatis xml 配置路径
mybatis:
  mapper-locations: classpath:mapper/**Mapper.xml
  configuration: # 配置打印 MyBatis 执行的 SQL
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    map-underscore-to-camel-case: true  #驼峰转换

application-prod.yml

server:
  port: 8080


# 数据库连接配置
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/java_blog_spring?characterEncoding=utf8&useSSL=false
    username: root
    password: woaini520
    driver-class-name: com.mysql.cj.jdbc.Driver

#  mybatis xml 配置路径
mybatis:
  mapper-locations: classpath:mapper/**Mapper.xml
  configuration:
    map-underscore-to-camel-case: true

5.测试类

userMapper

@SpringBootTest
@Slf4j
class UserMapperTest {
    @Autowired
    UserMapper userMapper;

    @Test
    void selectById() {
        User user = userMapper.selectById(1);
        log.info(user.toString());
    }

    @Test
    void selectByName() {
        User user = userMapper.selectByName("zhangsan");
        log.info(user.toString());
    }
}

基于Spring实现博客项目,Java项目,spring,java,后端

基于Spring实现博客项目,Java项目,spring,java,后端 基于Spring实现博客项目,Java项目,spring,java,后端

blogMapper

@SpringBootTest
@Slf4j
class BlogMapperTest {
    @Autowired
    BlogMapper blogMapper;

    @Test
    void selectAll() {
        List<Blog> blogs = blogMapper.selectAll();
        log.info(blogs.toString());

    }

    @Test
    void selectById() {
        Blog blog = blogMapper.selectById(1);
        log.info(blog.toString());
    }

    @Test
    void updateBlog() {
        Blog blog = new Blog();
        blog.setId(1);
        blog.setTitle("测试的第一篇博客");
        blog.setTitle("测试的第一篇博客的正文内容");
        blogMapper.updateBlog(blog);
    }

    @Test
    void insertBlog() {
        Blog blog = new Blog();
        blog.setTitle("第三篇博客");
        blog.setContent("第三篇博客的正文内容");
        blog.setUserId(1);
        blogMapper.insertBlog(blog);
    }
}

基于Spring实现博客项目,Java项目,spring,java,后端

基于Spring实现博客项目,Java项目,spring,java,后端 基于Spring实现博客项目,Java项目,spring,java,后端

基于Spring实现博客项目,Java项目,spring,java,后端 基于Spring实现博客项目,Java项目,spring,java,后端

 6.Common包

1.Result

@Data
public class Result {
    //业务处理状态码 200成功 <=0表示失败  (注意与请求状态码区分)
    private Integer code;
    //业务返回信息
    private String msg;
    //业务数据
    private Object data;


    /**
     * 业务处理失败
     *
     * @param code
     * @param message
     * @return
     */
    public static Result fail(Integer code, String message) {
        Result result = new Result();
        result.setCode(code);
        result.setMsg(message);
        result.setData("");

        return result;
    }

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

        return result;
    }

    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 message, Object data) {
        Result result = new Result();
        result.setCode(200);
        result.setMsg(message);
        result.setData(data);

        return result;
    }

}

2.ErrorAdvice(统一异常返回)

@ControllerAdvice
public class ErrorAdvice {
    @ExceptionHandler
    public Result error(Exception e) {

        return Result.fail(-1, e.getMessage());

    }
}

3.统一返回格式处理 

@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);
    }

}

7.导入前端代码

前端代码在这取:基于Spring实现博客项目: Spring项目写博客项目

三.业务代码

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"
 },

 

2.Service层

UserService

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

    public User selectById(Integer id) {
        return userMapper.selectById(id);
    }

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

    public User getAuthorInfoByBlogId(Integer id) {
        Blog blog = blogMapper.selectById(id);
        if (blog == null || blog.getUserId() < 0) {
            return null;
        }
        return userMapper.selectById(blog.getUserId());
    }
}

BlogService

@Service
public class BlogService {
    @Autowired
    private BlogMapper blogMapper;

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

    public Blog getBlogById(Integer id) {
        return blogMapper.selectById(id);
    }

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

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

}

3.Controller层

BlogController

@RestController
@RequestMapping("/blog")
public class BlogController {
    @Autowired
    BlogService blogService;

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

    }

    @RequestMapping("/getBlogDetail")
    public Result getBlogDetail(Integer id, HttpSession httpSession) {
        if (id == null || id < 0) {
            return Result.fail(-1, "非法的参数");
        }
        Blog blog = blogService.getBlogById(id);
        User user = (User) httpSession.getAttribute(Constants.USER_INFO_SESSION);

        if (blog.getUserId() == user.getId()) {
            blog.setIsLoginUser(true);
        }

        return Result.success(blog);

    }

    @RequestMapping("/add")
    public Result addBlog(String title, String content, HttpSession httpSession) {
        if (!StringUtils.hasLength(title) || !StringUtils.hasLength(content)) {
            return Result.fail(-1, "内容不能为空");
        }
        User user = (User) httpSession.getAttribute(Constants.USER_INFO_SESSION);
        if (user == null || user.getId() < 0) {
            return Result.fail(-1, "用户不存在");
        }
        Blog blog = new Blog();
        blog.setContent(content);
        blog.setTitle(title);
        blog.setUserId(user.getId());
        blogService.addBlog(blog);

        return Result.success(true);

    }

    @RequestMapping("/update")
    public Result updateBlog(Blog blog) {
        if (!StringUtils.hasLength(blog.getContent()) || !StringUtils.hasLength(blog.getTitle()) || blog.getId() == null) {
            return Result.fail(-1, "内容不能为空");
        }
        blogService.updateBlog(blog);

        return Result.success(true);

    }

    @RequestMapping("/delete")
    public Result deleteBlog(@RequestParam("id") Integer blogId) {
        if (blogId == null || blogId < 0) {
            return Result.fail(-1, "博客id不合法或者为空");
        }
        Blog blog = new Blog();
        blog.setId(blogId);
        blog.setDeleteFlag((byte) 1);
        blogService.updateBlog(blog);
        return Result.success(true);
    }
}

UserController

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

    @RequestMapping("/login")
    public Result login(HttpServletRequest request, String username, String password) {
        //参数校验
        if (!StringUtils.hasLength(username) || !StringUtils.hasLength(password)) {
            return Result.fail(-2, "账号或密码不能为空");
        }
        //密码校验
        User user = userService.selectByName(username);
        if (user == null || !user.getPassword().equals(password)) {
            return Result.fail(-3, "用户名不存在或者密码错误");
        }

        //参数返回
        user.setPassword("");
        HttpSession session = request.getSession(true);
        session.setAttribute(Constants.USER_INFO_SESSION, user);

        return Result.success("登陆成功");
    }

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

    }

    @RequestMapping("/getAuthorInfo")
    public Result getAuthorInfoByBlogId(@RequestParam("id") Integer blogId) {
        if (blogId == null || blogId < 0) {
            return Result.fail(-1, "id参数错误");
        }
        User user = userService.getAuthorInfoByBlogId(blogId);
        if (user == null) {
            return Result.fail(-1, "不存在文章作者");
        }
        user.setPassword("");

        return Result.success(user);


    }

    @RequestMapping("/logout")
    public Result logout(HttpSession session) {
        session.removeAttribute(Constants.USER_INFO_SESSION);

        return Result.success(true);

    }
}

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) {
            response.setStatus(401);
            return false;
        }
        return true;
    }
}
@Configuration
public class AppConfig implements WebMvcConfigurer {
    @Autowired
    private LoginInterceptor loginInterceptor;

    private final List<String> excludes = Arrays.asList(
            "/**/*.html",
            "/blog-editormd/**",
            "/css/**",
            "/js/**",
            "/pic/**",
            "/user/login"
    );

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterceptor).
                addPathPatterns("/**"). //拦截所有路径
                excludePathPatterns(excludes);
    }
}

在blog_list.html和blog_detail的ajax请求添加

                error: function (error) {
                    if (error != null && error.status == 401) {
                        location.assign("/blog_login.html");

                    }

                }

四.前端代码

有些代码重复出现,可以抽象为一个函数,我们放在./js/common.js中

function logout() {

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

    })
}

1.blog_list.html

先来个前置知识:日期格式化

方式一:将日期格式改为(java.sql.Date适用)

private Timestamp createTime;

然后引入js包

function formatDate(time) {
    var date = new Date(time);

    var year = date.getFullYear(),
        month = date.getMonth() + 1,//月份是从0开始的
        day = date.getDate(),
        hour = date.getHours(),
        min = date.getMinutes(),
        sec = date.getSeconds();
    var newTime = year + '-' +
        (month < 10 ? '0' + month : month) + '-' +
        (day < 10 ? '0' + day : day) + ' ' +
        (hour < 10 ? '0' + hour : hour) + ':' +
        (min < 10 ? '0' + min : min) + ':' +
        (sec < 10 ? '0' + sec : sec);

    return newTime;
}

 直接进行转化即可

<script src="./js/common.js"></script>
formatDate(blog.createTime)

方式二:(java.util.Date适用)

工具类

public class DateUtils {
    public static String formatDate(Date date) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return simpleDateFormat.format(date);
    }
}

博客实体类 

@Data
public class Blog {
    private Integer id;
    private String title;
    private String content;
    private Integer userId;
    private Byte deleteFlag;
    private Date createTime;

    public String getCreateTime() {
        return DateUtils.formatDate(createTime);
    }
}

此时就不需要多余的操作了

     finalHtml += '<div class="date">'+blog.createTime+'</div>';

之后javascrip代码

    <script src="./js/jquery.min.js"></script>
    <script src="./js/common.js"></script>

    <script>
        $(function () {
            $.ajax({
                type: "get",
                url: "/blog/getlist",
                success: function (result) {
                    var finalHtml = "";
                    if (result.code == 200 && result.data != null && result.data.length > 0) {
                        var dataHtml = result.data;
                        for (var i = 0; i < dataHtml.length; ++i) {
                            var blog = dataHtml[i];
                            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?id=' + blog.id + '">查看全文&gt;&gt;</a>';
                            finalHtml += '</div>';
                        }
                        $(".right").html(finalHtml);

                    }
                },
                error: function (error) {
                    if (error != null && error.status == 401) {
                        location.assign("/blog_login.html");

                    }

                }
            });

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

                },
                error: function (error) {
                    if (error != null && error.status == 401) {
                        location.assign("/blog_login.html");

                    }

                }
            });

            logout();


        })

    </script>

2.blog_detail.html

    <script src="./js/jquery.min.js"></script>
    <script src="blog-editormd/editormd.js"></script>
    <script src="blog-editormd/lib/marked.min.js"></script>
    <script src="blog-editormd/lib/prettify.min.js"></script>
    <script src="js/common.js"></script>

    <script>
        $(function () {
            $.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,
                        });

                        if (result.data.isLoginUser == true) {
                            var innerhtml = "";
                            innerhtml += '<button onclick="window.location.href = \'blog_update.html?id=' + blog.id + '\'">编辑</button>';
                            innerhtml += '<button onclick="deleteBlog()">删除</button>';
                            $(".operating").html(innerhtml);
                        }
                    }

                },
                error: function (error) {
                    if (error != null && error.status == 401) {
                        location.assign("/blog_login.html");

                    }

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

                },
                error: function (error) {
                    if (error != null && error.status == 401) {
                        location.assign("/blog_login.html");

                    }

                }
            });

            // jQuery("#deleteButton").click(function () {
            //     if (confirm("确定要删除吗?")) {
            //         $.ajax({
            //             type: "post",
            //             url: "/blog/delete" + location.search,
            //             success: function (result) {
            //                 if (result != null && result.data == true) {
            //                     location.assign("blog_list.html");
            //                 }
            //             }

            //         })
            //     }

            // });


        })
        function deleteBlog() {
            if (confirm("确定要删除吗?")) {
                $.ajax({
                    type: "post",
                    url: "/blog/delete" + location.search,
                    success: function (result) {
                        if (result != null && result.data == true) {
                            location.assign("blog_list.html");
                        }
                    }

                })
            }

        };
        logout();


    </script>

3.blog_login.html

    <script src="./js/jquery.min.js"></script>
    <script>
        $(function () {

            $("#submit").click(function () {
                //获取用户名
                var username = jQuery("#username");
                if (!username.val()) {
                    alert("用户名不能为空");
                    username.focus();
                    return;
                }

                //获取密码
                var password = jQuery("#password");
                if (!password.val()) {
                    alert("密码不能为空");
                    password.focus();
                    return;
                }


                $.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{
                            //业务处理失败
                            alert(result.msg);
                            return;
                        }
                        
                    },
                    error: function () {

                    }
                })

            })


        })
        
    </script>

4.blog_edit.html

    <script src="js/jquery.min.js"></script>
    <script src="blog-editormd/editormd.min.js"></script>
    <script type="text/javascript">

        $(function () {
            var editor = editormd("editor", {
                width: "100%",
                height: "550px",
                path: "blog-editormd/lib/"
            });

            $("#submit").click(function () {
                $.ajax({
                    type: "post",
                    url: "/blog/add",
                    data: {
                        title: $("#title").val(),
                        content: $("#content").val()
                    },
                    success: function (result) {
                        if (result != null && result.data != null && result.data == true) {
                            location.assign("blog_list.html");

                        }

                    },
                    error: function (result) {
                        if (result != null && result.status == 401) {
                            alert("请登录之后再进行操作");
                        }

                    }
                })
            })


        });
    </script>

5.blog_update.html

    <script src="js/jquery.min.js"></script>
    <script src="blog-editormd/editormd.min.js"></script>
    <script src="js/common.js"></script>
    <script type="text/javascript">

        $(function () {
            var editor = editormd("editor", {
                width: "100%",
                height: "550px",
                path: "blog-editormd/lib/"
            });

            $.ajax({
                type: "get",
                url: "/blog/getBlogDetail" + location.search,
                success: function (result) {
                    var blog = result.data;
                    if (result != null && result.code == 200 && result.data != null) {
                        $("#title").val(blog.title);
                        $("#content").val(blog.content);
                        $("#blogId").val(blog.id);
                    }

                },
                error: function (result) {
                    if (result != null && result.status == 401) {
                        alert("请登录之后再进行操作");
                    }

                }

            });
            $("#submit").click(function () {
                $.ajax({
                    type: "post",
                    url: "/blog/update",
                    data: {
                        title: $("#title").val(),
                        content: $("#content").val(),
                        id: $("#blogId").val()
                    },
                    success: function (result) {
                        if (result != null && result.data == true) {
                            location.assign("blog_list.html");
                        }

                    },
                    error: function (result) {
                        if (result != null && result.status == 401) {
                            alert("请登录之后再进行操作");
                        }

                    }
                })
            })

        });

    </script>

五.加密措施

1.加密

假设我们的数据库被黑客进行劫持,那么用户的一些重要信息(比如密码,身份证号)就可能被获取,这样对用户是十分不利的,因此我们需要对数据库中一些重要的信息进行加密存储.

目前有许多的加密算法,包括可逆加密和非可逆加密,可逆加密在http和https的时候就有使用,通过密钥就可以使明文变为密文,同时也可以让密文变为明文,但是非可逆加密就不同了,非可逆加密只能使明文加密为密文,不能从密文变为明文,一般在数据库中我们采用非可逆加密.

常用的非可逆加密有MD5加密,通过对明文加密,可以得到长度固定的MD5值,MD5加密就可以得到32位或者16位的加密后的结果.

基于Spring实现博客项目,Java项目,spring,java,后端

Java中使用MD5加密

@SpringBootTest
class BlogSpringApplicationTests {

    @Test
    void contextLoads() {
        String finalPassword = DigestUtils.md5DigestAsHex("123456".getBytes());
        System.out.println("第一次加密:" + finalPassword);
        finalPassword = DigestUtils.md5DigestAsHex("123456".getBytes());
        System.out.println("第二次加密:" + finalPassword);
        finalPassword = DigestUtils.md5DigestAsHex("123456".getBytes());
        System.out.println("第三次加密:" + finalPassword);
    }

}

基于Spring实现博客项目,Java项目,spring,java,后端

 可以观察到:MD5加密后得到的值是都是一样的,并且无论进行多少次MD5加密(对产生的MD5值多次进行加密),得到的结果都是一样的.

那么这样会不会产生安全问题呢?当然会!虽然说MD5加密是不可逆的加密,但是可以通过提前生成对应的明文和密文对应的表,然后通过需要破解的密文与之前生成表的密文进行对应,从而找到相应的明文,但是这种方法是十分低效的,但是也可以进行破解明文,尤其对于密码不复杂且短的很容易破解,那么怎么样可以避免这种情况呢?

首先可以在用户端进行,我们在设置的密码的时候,通常网站都要求需要字母与数字的组合,并且长度都要求大于一定的值,这样密码的安全等级很高,不容易被破解,(比如纯数字组合就10种,字母加数字就有26+10种,大小写字母加数字组合就有26*2+10种,长度越长组合自然也就越多).

接下来通过服务端通过加盐的方式存储密码.

2.盐值

假设用户的密码安全很低,如果在存储的时候将密码与随机的字符串的进行拼接,然后再通过MD5加密的方式进行存储的话,同样也可以时密码难以破解,并且可以通过生成多个不同的随机字符串,可以解决MD5不能实现多次加密的问题.随机生成的字符串也要存储到数据库中,通常与生成的MD5数值拼接存储.

代码展示,通过UUID生成随机的字符串.

    @Test
    void contextLoads() {
        String salt = UUID.randomUUID().toString();
        String finalPassword = DigestUtils.md5DigestAsHex(("123456" + salt).getBytes());
        System.out.println("第一次salt:" + salt);
        System.out.println("第一次加密:" + finalPassword);
        salt = UUID.randomUUID().toString();
        finalPassword = DigestUtils.md5DigestAsHex(("123456" + salt).getBytes());
        System.out.println("第二次salt:" + salt);
        System.out.println("第二次加密:" + finalPassword);
        salt = UUID.randomUUID().toString();
        finalPassword = DigestUtils.md5DigestAsHex(("123456" + salt).getBytes());
        System.out.println("第三次salt:" + salt);
        System.out.println("第三次加密:" + finalPassword);
    }

基于Spring实现博客项目,Java项目,spring,java,后端 我们不希望产生的salt含有特殊字符,因此我们可以通过以下的方式将"-"去掉

    @Test
    void contextLoads() {
        String salt = UUID.randomUUID().toString().replace("-", "");
        String finalPassword = DigestUtils.md5DigestAsHex(("123456" + salt).getBytes());
        System.out.println("第一次salt:" + salt);
        System.out.println("第一次加密:" + finalPassword);
        salt = UUID.randomUUID().toString().replace("-", "");
        finalPassword = DigestUtils.md5DigestAsHex(("123456" + salt).getBytes());
        System.out.println("第二次salt:" + salt);
        System.out.println("第二次加密:" + finalPassword);
        salt = UUID.randomUUID().toString().replace("-", "");
        finalPassword = DigestUtils.md5DigestAsHex(("123456" + salt).getBytes());
        System.out.println("第三次salt:" + salt);
        System.out.println("第三次加密:" + finalPassword);
    }

基于Spring实现博客项目,Java项目,spring,java,后端

3.实现

public class SecurityUtils {

    /**
     * 将密码进行加密
     * 根据明文,返回密文(salt+MD5)
     *
     * @param password
     * @return
     */
    public static String encry(String password) {
        //生成盐值
        String salt = UUID.randomUUID().toString().replace("-", "");
        //进行加密
        String finalPassword = DigestUtils.md5DigestAsHex((password + salt).getBytes());
        return salt + finalPassword;

    }

    /**
     * @param inputPassword 输入的密码
     * @param finalPassword 数据库存储的密码
     * @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);


    }


}

修改密码验证的接口

    @RequestMapping("/login")
    public Result login(HttpServletRequest request, String username, String password) {
        //参数校验
        if (!StringUtils.hasLength(username) || !StringUtils.hasLength(password)) {
            return Result.fail(-2, "账号或密码不能为空");
        }
        //密码校验
        User user = userService.selectByName(username);
        if (user == null || !SecurityUtils.decrypt(password, user.getPassword())) {
            return Result.fail(-3, "用户名不存在或者密码错误");
        }

        //参数返回
        user.setPassword("");
        HttpSession session = request.getSession(true);
        session.setAttribute(Constants.USER_INFO_SESSION, user);

        return Result.success("登陆成功");
    }

六.上线发布

1.多平台开发

    <profiles>
        <profile>
            <id>dev</id>
            <properties>
                <env>dev</env>
            </properties>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
        </profile>
        <profile>
            <id>prod</id>
            <properties>
                <env>prod</env>
            </properties>
            <activation>
                <activeByDefault>false</activeByDefault>
            </activation>
        </profile>
    </profiles>

如果需要跳过test,可以点击基于Spring实现博客项目,Java项目,spring,java,后端 

基于Spring实现博客项目,Java项目,spring,java,后端

 application.yml文件

基于Spring实现博客项目,Java项目,spring,java,后端

 此时打包即可

2.部署linux服务器 

1.创建数据库

可以将sql语句变成一个文件,然后执行下面的

基于Spring实现博客项目,Java项目,spring,java,后端

 source /root/java78/create.sql

2.将代码打包

基于Spring实现博客项目,Java项目,spring,java,后端

打包完成之后,将jar包拖拽到linux服务器上

基于Spring实现博客项目,Java项目,spring,java,后端3.运行代码 

 后台启动项目

nohup java -jar Blog_Spring-0.0.1-SNAPSHOT.jar &

基于Spring实现博客项目,Java项目,spring,java,后端

 查看日志

cd logs/

tail -f spring.log

 

 终止当前的服务

ps -ef | grep [ ] 

基于Spring实现博客项目,Java项目,spring,java,后端

 注意:如果开启多个服务,需要开端口,给防火墙添加端口号

查看防火墙状态(如果没开启,建议开启,不开启可以直接访问,开启了需要进行已下的操作访问)

systemctl status firewalld

 启动防火墙和关闭防火墙

systemctl start firewalld

systemctl stop firewalld

查看开放的端口号

firewall-cmd --list-ports

开启8080端口

firewall-cmd --permanent --add-port=8080/tcp

重启防火墙

firewall-cmd --reload

设置开机启动

systemctl enable firewalld

添加安全组

基于Spring实现博客项目,Java项目,spring,java,后端

 否则无法正常访问文章来源地址https://www.toymoban.com/news/detail-679432.html

到了这里,关于基于Spring实现博客项目的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java后端07(Spring未完成)

    ​涉及的设计模式:单例模式,简单工厂模式,代理模式,观察者模式,反射,注解。。。。。 ​在传统模式下,对象的创建和赋值,都是由开发者自己手动完成,事实情况下,开发者只关心如何获取赋值好的对象,但是并不希望自己手动进行创建对象和赋值的事情(sprin

    2024年02月14日
    浏览(50)
  • Java项目:ssm框架基于spring+springmvc+mybatis框架的民宿预订管理系统设计与实现(ssm+B/S架构+源码+数据库+毕业论文)

    本项目是一套ssm827基于SSM框架的民宿预订管理系统设计与实现,主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者。 包含:项目源码、数据库脚本等,该项目附带全部源码可作为毕设使用。 项目都经过严格调试,eclipse 确保可以运行! 该系统功能

    2024年01月22日
    浏览(84)
  • Java设计模式-策略模式-基于Spring实现

    策略模式是一种行为设计模式,它允许在运行时选择算法的行为。它将算法封装在 独立的策略类 中,使得它们可以相互替换,而不影响客户端代码。这种模式通过 将算法的选择从客户端代码中分离出来 ,提供了更大的灵活性和可维护性。 在Java中,策略模式的设计理念可以

    2024年02月08日
    浏览(59)
  • JAVA后端开发面试基础知识(八)——Spring

    Spring是一个轻量级Java开发框架 我们一般说 Spring 框架指的都是 Spring Framework,它是很多模块的集合,使用这些模块可以很方便地协助我们进行开发,比如说 Spring 支持 IoC(Inverse of Control:控制反转) 和 AOP(Aspect-Oriented Programming:面向切面编程)、可以很方便地对数据库进行访问、

    2024年03月10日
    浏览(74)
  • 基于Java+Spring的图书管理系统详细设计和实现

     博主介绍 : ✌ 全网粉丝20W+,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战 ✌ 🍅 文末获取源码联系 🍅 👇🏻 精彩专栏 推荐订阅 👇🏻 不然下次找不到哟  java项

    2024年02月03日
    浏览(87)
  • 网页版Java(Spring/Spring Boot/Spring MVC)五子棋项目(二)前后端实现用户的登录和注册功能【用户模块】

    1. 用户id 2. 用户名 3. 密码 4. 天梯积分 5. 总场数 6. 获胜场数 和数据库的数据一一对应 1. 连接数据库(application.yml连接数据库) 这个可以直接赋值代码 2. 创建UserMapper的Java接口(interface UserMapper) 创建接口,在UserMapper.xml实现 在model中创建 需要实现@Mapper注释 3. 创建UserMappe

    2024年02月13日
    浏览(51)
  • 基于Java+Spring+vue+element商城销售平台设计和实现

    博主介绍 : ✌ 全网粉丝20W+,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战 ✌ 🍅 文末获取源码联系 🍅 👇🏻 精彩专栏 推荐订阅 👇🏻 不然下次找不到哟  java项目

    2024年02月02日
    浏览(63)
  • 微信小程序的授权登录-Java 后端 (Spring boot)

    微信开发文档链接:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html 一个可以测试的微信小程序 此微信小程序的APPID和APPscret(至开发者后台获取) 从时序图我们可以了解到流程大致分为两步: 小程序端获取code后传给Java后台 Java后台获取code后向微信后台接口

    2024年02月09日
    浏览(55)
  • 基于微服务+Java+Spring Cloud开发的建筑工地智慧平台源码 云平台多端项目源码

    建筑工地智慧平台源码,施工管理端、项目监管端、数据大屏端、移动APP端全套源码 技术架构:微服务+Java+Spring Cloud +Vue+UniApp +MySql+自主版权+实际应用案例+演示 建筑工地智慧平台已应用于线上巡查、质量管理、实名制管理、危大工程管理、运渣车管理、绿色施工、视频监控

    2024年02月07日
    浏览(55)
  • Java(一):创建 Spring Boot 项目并实现连接操作MySQL数据库

    MySQL 命令 Maven 相关地址 下载地址: https://maven.apache.org/ maven配置方法地址: https://developer.aliyun.com/mvn/guide 仓库搜索地址: https://mvnrepository.com/ https://repo.maven.apache.org/ maven 本地配置 conf/settings.xml 下载 idea 并配置本地环境 maven Maven 构建 生命周期 Maven 的构建 生命周期 包括 三

    2024年02月07日
    浏览(70)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包