SSM个人博客项目

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


SSM个人博客系统实现

SSM个人博客项目,项目,项目,java,spring boot,mybatis
SSM个人博客项目,项目,项目,java,spring boot,mybatis
SSM个人博客项目,项目,项目,java,spring boot,mybatis
SSM个人博客项目,项目,项目,java,spring boot,mybatis

项目介绍

本项目是一个前后端分离的个人博客系统,实现的主要功能有用户注册、用户登录、找回密码、验证码、文章的发布和删除、定时发布文章功能、草稿箱功能、文章列表分页功能、用户信息修改包括上传头像。利用SpingAOP实现了统一的登录验证、异常处理、统一返回格式。

一、准备工作

0. 创建项目添加对应依赖

SSM个人博客项目,项目,项目,java,spring boot,mybatis

从Maven仓库引入SprinAOP依赖和第三方Hutool依赖

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.16</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

1. 数据库设计

数据库一共有6张表,分别是用户表、文章表、文章草稿表、定时发布文章表、密保问题表

SSM个人博客项目,项目,项目,java,spring boot,mybatis

2. 定时实体类

实体类分别对应数据表

用户类

@Data
public class User {
    private int id;
    private String username;
    private String password;
    private String netName;
    private String photo;
    private String git;
    private Integer articleCount;
    private Date createTime;
    private Date updateTime;
    // 用户是否第一次登录
    private int state;
}

文章类

@Data
public class Article {
    private Integer id;
    private String title;
    private String content;
    private Date createTime;
    private Date updateTime;
    private Integer userId;
    private Integer visits;
}

文章草稿

@Data
public class Drafts {
    private Integer id;
    private String title;
    private String content;
    private Date createTime;
    private Date updateTime;
    private Integer userId;
}

定时发布的文章

@Data
public class TimingArticle {
    private Integer id;
    private String title;
    private String content;
    private Date postTime;
    private Integer userId;
}

密保问题

@Data
public class QuestionPassword {
    private Integer id;
    private String question1;
    private String question2;
    private String question3;
    private String answer1;
    private String answer2;
    private String answer3;
    private Integer userId;
}

二、功能实现

1.统一功能处理

使用SpringAOP可以实现统一功能的处理,统一的功能处理可以避免代码的冗余。

统一返回格式

先定义一个响应类,重载一些方法,success表示执行成功(正确的查询数据、登录成功等),fail表示执行失败(密码错误、参数非法的),重载可以非常灵活的让我们给前端返回数据。

@Getter
@Setter
public class Response {
    private int code;
    private String message;
    private Object data;
    public static Response success(Object data) {
        Response response = new Response();
        response.code = 200;
        response.message = "";
        response.data = data;

        return response;
    }

    public static Response success(String message) {
        Response response = new Response();
        response.message = message;
        response.code = 200;
        return response;
    }
    public static Response success(Object data,String message) {
        Response response = new Response();
        response.message = message;
        response.code = 200;
        response.data = data;
        return response;
    }
    public static Response fail(String message) {
        Response response = new Response();
        response.code = -1;
        response.message = message;

        return response;
    }
    public static Response fail(String message,int code) {
        Response response = new Response();
        response.code = code;
        response.message = message;

        return response;
    }
}

实现统一响应格式实现,统一的返回格式有利于后端统一标准规范,降低前后端的沟通成本。定义ResponseAdvice类实现ResponseBodyAdvice接口,并用@ControllerAdvice注解修饰表示该类为一个增强类

@ControllerAdvice
@ResponseBody
public class ResponseAdvice implements ResponseBodyAdvice {
    @Resource
    private ObjectMapper mapper;

    @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 Response) {
            return body;
        }
        if (body instanceof String) {
            // 转换成json根式的返回格式
            return mapper.writeValueAsString(Response.success(body));
        }
        return Response.success(body);
    }
}

最后的响应返回格式,后面的所有响应都是如此

正确执行的响应

{
    code:200
    data: "自定义的返回数据"
    message: "自定义的返回消息"
}

错误执行的响应

{
    code:-1
    data: ""
    message: "自定义的返回消息"
}

统一异常处理

统一的异常处理,服务器发送异常后我们可以通过增强类做统一处理后给前端返回响应,可以添加一些预计会发送的异常分别进行处理。

@ControllerAdvice
@ResponseBody
public class ExceptionAdvice {
    @ExceptionHandler(Exception.class)
    public Object handler(Exception e) {
        return Response.fail("服务器异常",500);
    }
}

定义登录拦截器

定义登录拦截器,可以避免大量登录验证的代码冗余,让指定的接口统一验证。

/**
 * 自定义登录拦截器
 */
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(Constant.SESSION) != null) {
            response.setStatus(200);
            return true;
        }
        // 重定向到登录页面
        response.sendRedirect("/login.html");
        return false;
    }
}

添加自定义拦截器,如果某些接口被拦截器拦截就需要经过拦截器验证后才能去执行对应的Controller方法,也就是需要登录后才能使用。

@Configuration
public class AppConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginInterceptor()) // 添加自定义拦截器
                .addPathPatterns("/**") //拦截所有接口
                .excludePathPatterns("/user/login") //排除的接口
                .excludePathPatterns("/user/reg")
                .excludePathPatterns("/user/getVerify")
                .excludePathPatterns("/user/byIdUser")
                .excludePathPatterns("/questionPass/getQuestion")
                .excludePathPatterns("/questionPass/findPass")
                .excludePathPatterns("/questionPass/setNewPass")
                .excludePathPatterns("/article/byIdArticle")
                .excludePathPatterns("/article/pagingGetArticle")
                .excludePathPatterns("/login.html")
                .excludePathPatterns("/blog_detailed.html")
                .excludePathPatterns("/blog_list.html")
                .excludePathPatterns("/find_pass.html")
                .excludePathPatterns("/register.html")
                .excludePathPatterns("/img/**")
                .excludePathPatterns("/js/**")
                .excludePathPatterns("/photo/**")
                .excludePathPatterns("/css/**");
    }
}

2. 注册登录实现

生成获取验证码

使用第三方工具Hutool来绘制验证码,把生成的验证码保存到session中,通过响应把图片传递个前端

@GetMapping("/getVerify")
public Response getVerify(HttpSession session,HttpServletResponse response) {
    VerificationCodeUtil.getCode(session,response);

    return Response.success("ok");
}

密码加盐实现

通过密码加盐来保证用户密码的一定安全性

  • 加盐的实现思路为:用户注册把生成一个UUID拼接上用户前端传递的明文密码进行MD5,以#号分割再把生成的UUID拼接到#后面,生成最终密码存入数据库。
  • 解密思路:把数据库加密的代码查询出来,以#把UUID分割出来,把用户输入的明文密码以同样的方式拼接上分割出来的UUID,加盐后再和数据库查询的密码进行比对
public class PasswordUtil {

    /**
     * 密码加盐
     * @param password 明文密码
     * @return
     */
    public static String passwordAddSalt(String password) {

        String uuid = UUID.randomUUID().toString().replace("-","");
        String finalPass = (DigestUtils.md5DigestAsHex((uuid+password).getBytes())+"#"+uuid);

        return finalPass;
    }

    /**
     * 验证密码
     * @param password 明文密码
     * @param finalPass 加密密码
     * @return
     */
    public static boolean check(String password,String finalPass) {
        String uuid = finalPass.split("#")[1];
        String pass = (DigestUtils.md5DigestAsHex((uuid+password).getBytes())+"#"+uuid);
        return pass.equals(finalPass);
    }
}

注册功能

SSM个人博客项目,项目,项目,java,spring boot,mybatis

约定前后端交互

请求:

{
    username : "用户名",
    password : "密码",
    confirmPass :"确认密码",
    verifyCode : "验证码"
}

响应:

{
 "code":200,
 "message":"注册成功",
 "data":null
}

先简单的数据校验,密码加盐,再生成随机的网名,注意网名和用户名要区分,考虑到用户名已经存在问题。

@PostMapping("/reg")
public Response reg(String username,String password,String confirmPass,HttpSession session,String verifyCode) {
    if (verifyCode == null || "".equals(verifyCode.trim()) || !VerificationCodeUtil.check(session,verifyCode)) {
        return Response.fail("验证码错误");
    }
    if (username == null || password == null || confirmPass == null || "".equals(username.trim())
        || "".equals(password.trim()) || "".equals(confirmPass.trim())) {
        return Response.fail("用户名密码非法");
    }
    if (!password.equals(confirmPass)) {
        return Response.fail("两次密码输入不一致");
    }
    User user = userService.byNameUser(username);
    if (user != null) {
        return Response.fail("用户已经被注册");
    }
    // 密码加盐
    String finalPass = PasswordUtil.passwordAddSalt(password);
    String netName = "用户"+System.currentTimeMillis()%1000000;
    int ret = userService.reg(username,finalPass,netName);

    if (ret == 1) {
        return Response.success("注册成功");
    }
    return Response.fail("用户名密码非法");
}

登录功能

SSM个人博客项目,项目,项目,java,spring boot,mybatis

约定前后端交互

请求:

{
    username:"用户名",
    password:"密码",
    inputVerify="验证码"
}

响应:

{
    "code":200,
    "message":"登录成功/用户名密码错误/验证码错误",
    "data":null
}

登录成功后把用户信息保存session会话,前端跳转到博客列表页

@PostMapping("/login")
public Response login(String username, String password,String inputVerify ,HttpSession httpSession,HttpServletRequest request) {
    if (inputVerify == null || "".equals(inputVerify.trim()) || !VerificationCodeUtil.check(httpSession,inputVerify)) {
        return Response.fail("验证码错误");
    }
    if (username == null || password == null || "".equals(username.trim()) || "".equals(password.trim())) {
        return Response.fail("用户名密码错误");
    }

    User user = userService.byNameUser(username);
    if (user != null && PasswordUtil.check(password,user.getPassword())) {
        // 把密码置为空
        user.setPassword("");
        user.setUsername("");

        HttpSession session = request.getSession(true);
        session.setAttribute(Constant.SESSION,user);

        return Response.success("登录成功");
    }
    return Response.fail("用户名密码错误");
}

注销功能

删除session会话即可

@PostMapping("/logout")
public Response login(HttpServletRequest request) {
    User user = LogInUserInfo.getUserInfo(request);
    if (user == null) {
        return Response.fail("当前未登录");
    }
    request.removeAttribute(Constant.SESSION);
    return Response.success("注销成功");
}

3.登录用户博客列表

登录成功后跳转到博客列表页面,需要获取当前用户的所有博客信息,和当前用户的信息。
SSM个人博客项目,项目,项目,java,spring boot,mybatis

获取登录用户信息

用户登录后通过用户的id来查询到用户的信息,查询到后要把用户名和密码一些敏感信息给影响。

请求:

"http://127.0.0.1:7070/usre/getUserInfo"

响应:

{"code":200,
 "message":"",
 "data":{
     "id":1,
     "username":"",
     "password":"",
     "netName":"用户11326",
     "photo":"../img/logo.jpg"
         ,"git":"https://gitee.com/he-hanyu",
     "articleCount":0,
     "createTime":null,
     "updateTime":null,
     "state":0
 }
}

主意通过用户的state字段判断用户是否第一次登录,如果是第一次登录就在前端提示用户设置密保问题。
SSM个人博客项目,项目,项目,java,spring boot,mybatis

@GetMapping("/getUserInfo")
public Response getUserInfo(HttpServletRequest request) {
    User user = LogInUserInfo.getUserInfo(request);
    User myUser = userService.byIdUser(user.getId());
    myUser.setPassword("");
    myUser.setUsername("");
    // 判断是否是第一次登录
    if (myUser.getState() == 1) {
        //如果是第一登录就修改状态
        userService.updateState(user.getId());
    }
    return Response.success(myUser);
}

获取登录用户文章列表

请求:

"http://127.0.0.1:7070/user/getUserArticle"

响应:

{
    "code":200,
    "message":"",
    "data":[
        {"id":1,
         "title":"测试",
         "content":"#Hh宇的个人博客",
         "createTime":"2023-08-06",
         "updateTime":null,
         "userId":1,
         "visits":0}
    ]
}

通过用户id来查看当前用户的博客,显示博客是博客列表要注意把文章内荣进行一个截取

@GetMapping("/getUserArticle")
public Response getUserArticle(HttpServletRequest request) {
    User user = LogInUserInfo.getUserInfo(request);
    List<Article> articleList = articleService.getUserArticle(user.getId());
    for (Article article : articleList) {
        if (article.getContent().length() > 100) {
            article.setContent(article.getContent().substring(0,100)+"......");
        }
    }
    return Response.success(articleList);
}

SSM个人博客项目,项目,项目,java,spring boot,mybatis

博客列表有对应的查看文章响应,修改文章,删除文章。

4.文章相关操作

SSM个人博客项目,项目,项目,java,spring boot,mybatis

发布文章

发布文章校验标题和正文是否为空,校验完毕后给数据表添加信息。

约定前后端交互:

请求:

{
    title: "文章标题",
    content: "文章正文"
}

响应:

{
    "code":200,
    "message":"发布成功",
    "data":null
}
@PostMapping("/addArticle")
public Response addArticle(String title,String content,HttpServletRequest request) {
    if (title == null || content == null || "".equals(title.trim()) || "".equals(content.trim())) {
        return Response.fail("发布失败");
    }
    User user = LogInUserInfo.getUserInfo(request);
    int row = articleService.addArticle(title,content,user.getId());
    if (row == 1) {
        userService.articleCountAuto(user.getId(),1);
        return Response.success("发布成功");
    }
    return Response.fail("发布失败");
}

删除文章

点击登录用户文章列表后通过博客id来删除文章,文章id由前端在生成链接时拼接在querystr中。点击删除链接,就会获取到文章Id给后端发送删除请求。且删除时验证该文章是否属于当前登录用户。
SSM个人博客项目,项目,项目,java,spring boot,mybatis

请求:

POST http://127.0.0.1:7070/article/idDeleteArticle
{
    articleId : 文章Id
}
@PostMapping("/idDeleteArticle")
public Response idDeleteArticle(Integer articleId,HttpServletRequest request) {
    if (articleId == null || articleId <= 0) {
        return Response.fail("删除失败");
    }
    User user = LogInUserInfo.getUserInfo(request);
    int ret = articleService.idDeleteArticle(articleId,user.getId());
    if (ret == 1) {
        userService.articleCountAuto(user.getId(),-1);
        return Response.success("删除成功");
    }
    return Response.fail("删除失败");
}

修改文章

点击修改文章后,会在url里拼接上一个文章id进入博客编辑页面,再次点击发布博客后会判断url中的querystr中是否有文章Id如果有说明是修改博客。
SSM个人博客项目,项目,项目,java,spring boot,mybatis
SSM个人博客项目,项目,项目,java,spring boot,mybatis

获取博客请求也就是通过querystr中的id查询博客:

GET http://127.0.0.1:7070/article/byIdArticle?articleId=2 

修改博客请求:

POST http://127.0.0.1:7070/article/updateArticle HTTP/1.1
{
    title: "修改后的标题",
    content: "修改后的正文"
}

响应:

{
    "code":200,
    "message":"修改成功",
    "data":null
}
@PostMapping("/updateArticle")
public Response updateArticle(String title,String content,Integer articleId,HttpServletRequest request) {
    if (title == null || content == null || "".equals(title.trim()) || "".equals(content.trim())
        || articleId == null || articleId <= 0) {
        return Response.fail("内容非法");
    }
    User user = LogInUserInfo.getUserInfo(request);
    int ret = articleService.updateArticle(title,content,articleId,user.getId());
    if (ret == 1) {
        return Response.success("修改成功");
    }
    return Response.fail("修改失败");
}

定时发布文章

SSM个人博客项目,项目,项目,java,spring boot,mybatis

定时发布文章前端给后端传递格式化的时间,后端再装换成和数据库对应的Date时间存,把待发布文章存入数据库,通过Spring的定时任务,每5秒扫描一下定时任务数据表,如果当前的大于发布时间就从数据库中获取到文章信息并进行发布,且删除对应的文章信息。

请求:

{
    title: "文章标题",
    content: "文章正文",
    postTime : "2023-08-06 16:28:26"
}

响应:

{
    "code":200,
    "message":"定时博客任务发布成功",
    "data":null
}

需要通过正则判断前端传递的时间格式是否正确,且发布时间没有大于预期值。

@RestController
@RequestMapping("/timed")
public class TimedArticleController {
    @Autowired
    private TimedArticleService timedArticleService;
    @SneakyThrows
    @PostMapping("/timingPost")
    public Response addTimedPost(String title, String content, String postTime, HttpServletRequest request) {

        if (title == null || content == null || postTime == null ||
        "".equals(title.trim()) || "".equals(content.trim()) || "".equals(postTime.trim())) {
            return Response.fail("内容非法");
        }
        // 校验时间格式是否正确
        if (DateTimeUtil.isValidDateTimeFormat(postTime)) {
            System.out.println(postTime);
            // 获取当前时间
            String time = DateUtil.now();
            // 判断当前时间和发布时间是否合法
            if (DateTimeUtil.getTimeDifferenceDay(time,postTime) > 7) {
                return Response.fail("发布时间不合法,请输入小于7天的发布时间");
            }
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date date = format.parse(postTime);
            User user = LogInUserInfo.getUserInfo(request);
            int ret = timedArticleService.addTimedPost(title,content,date,user.getId());
            if (ret == 1) {
                return Response.success("定时博客任务发布成功");
            }

        }

        return Response.fail("发布失败");
    }
}

在SpingBoot的启动类上添加注解开启定时任务,

@SpringBootApplication
@EnableScheduling
public class BlogApplication {

    public static void main(String[] args) {
        SpringApplication.run(BlogApplication.class, args);
    }

}

再创建一个定时任务类每5秒扫描一下数据库

@Component
public class ScheduledRelease {
    @Autowired
    private TimedArticleService timedArticleService;
    @Autowired
    private ArticleService articleService;
    // 每5秒执行一次
    @Scheduled(fixedRate = 5000)
    @Transactional
    public void scheduledTak() {
        Date date = new Date();
        List<TimingArticle> timingArticles = timedArticleService.getPostArticle(date);
        for(TimingArticle article : timingArticles) {
            articleService.addArticle(article.getTitle(),article.getContent(),article.getUserId());
            // 发布后立马删除记录
            timedArticleService.idDelete(article.getId());
        }
    }
}

需要注意的是查询时间对比sql要先把时间转换为时间戳

<select id="getPostArticle" resultMap="TimingArticleInfo">
        select * from timed_article where unix_timestamp(#{time}) > unix_timestamp(post_time);
    </select>

分页获取所有用户的文章

所有用户的文章数量比较多,为了减小服务器压力,所以采用分页。一页显示5篇文章。每次进入博客列表页,后端会先查询数据库中的文章数量通过公式计算出一共有多少页,再把最大页数和当前页的文章传递给前端,前端默认获取第一页的文章。
分页公式为文章总数*1.0/每页显示数量向上取整算出页数,前端传递的(页数-1)*每页显示数量求出从数据表中哪一条数据开始查询。

请求:

GET http://127.0.0.1:7070/article/pagingGetArticle?pageNumber=1&size=5 HTTP/1.1

响应:

{
"code":200,
"message":"",
"data":{
	"pageCount":2,
	"articles":
	[
		{"id":6,
		"title":"再来一篇文章",
		"content":"#Hh宇的个人博客",
		"createTime":"2023-08-	08",
		"updateTime":null,
		"userId":2,"visits":0},
	]
	}
}

后端代码

/**
     * 分页获取所有用户博客
     * @param pageNumber 页数
     * @param size 每页显示多少篇文章
     * @return
     */
    @GetMapping("/pagingGetArticle")
    public Response pagingGetArticle(Integer pageNumber,Integer size) {
        if (pageNumber < 1) {
            pageNumber = 1;
        }
        // 获取所有文章数量
        int articleCount = articleService.getArticleCount();
        // 计算出每页size个最多有多少页
        int pageCount = (int)(Math.ceil(articleCount*1.0/size));
        // 公式计算步长
        int offset = (pageNumber-1)*size;
        List<Article> articles = articleService.pagingGetArticle(size,offset);
        System.out.println(articles);
        HashMap<String,Object> result = new HashMap<>();
        result.put("pageCount",pageCount);
        result.put("articles",articles);
        return Response.success(result);
    }

SSM个人博客项目,项目,项目,java,spring boot,mybatis

文章详情

点击查看全文即可查看文章详情,文章详情里展示了文章标题、文章发布时间、文章的浏览量和文章正文。左边显示的是当前文章的作者信息。先通过querystr中的的文章id查询到文章,再同过文章里返回的当前用户id,来查询到当前文章作者对应的信息。

SSM个人博客项目,项目,项目,java,spring boot,mybatis

请求:

GET http://120.25.124.200:7070/article/byIdArticle?articleId=5 HTTP/1.1

响应:

{
"code":200,
"message":"",
"data":
	{
		"id":5,
		"title":"文章分页",
		"content":"#Hh宇的个人博客",
		"createTime":"2023-08-08",
		"updateTime":null,
		"userId":2,
		"visits":0
	}
}

5.文章草稿箱实现

SSM个人博客项目,项目,项目,java,spring boot,mybatis

文章草稿包存草稿箱和发布文章类似,点击保存草稿后就把文章保存到草稿箱当中,并更新数据表信息,可以从草稿箱中发布博客,也可以修改草稿箱里的草稿文章或者删除草稿。

需要注意的是修改草稿,点击修改草稿后,通过url中的querystr来查询到对应的草稿

GET http://127.0.0.1:7070/blog_editor.html?draftId=1 HTTP/1.1

响应:

{
    "code":200,
    "message":"",
    "data":
    {
        "id":1,
        "title":"这是一篇草稿",
        "content":"#Hh宇的个人博客",
        "createTime":null,
        "updateTime":null,
        "userId":1
    }
}

从草稿箱发布文章

因为发布文章和草稿共用的是一个页面,所以发布文章的时候,需要通过url中的querystr的id来判断是普通发布文章还是从草稿箱中发布文章。从草稿箱发布完文章后,就删除草稿数据报中的文章。
SSM个人博客项目,项目,项目,java,spring boot,mybatis

请求:

POST http://127.0.0.1:7070/articleDraft/postArticle HTTP/1.1
{
    title:"草稿标题"
    content:"草稿正文",
    draftId : 1
}

响应:

{
    "code":200,
    "message":"发布成功",
    "data":null
}
@PostMapping("/postArticle")
public Response postArticle(String title,String content,Integer draftId,HttpServletRequest request) {
    if (title == null || content == null || "".equals(title.trim()) || "".equals(content.trim()) || draftId <= 0) {
        return Response.fail("发布失败");
    }
    User user = LogInUserInfo.getUserInfo(request);
    int ret = articleService.addArticle(title,content,user.getId());
    // 发布成功就删除草稿
    if (ret == 1) {
        int row = articleDraftService.idDeleteDrafts(draftId,user.getId());
        if (row == 1) {
            return  Response.success("发布成功");
        }
    }
    return Response.fail("发布失败");
}

修改草稿

如果是修改草稿,也就是点击编辑草稿后再次点击保存草稿,此时就是修改草稿了,而不是保存草稿,同样是在前端通过querystr区分。

请求:

POST http://127.0.0.1:7070/articleDraft/updateDraft HTTP/1.1
{
    draftId : 2,
    title : "标题",
    content : "正文"
}

响应:

{
    "code":200,
    "message":"保存成功",
    "data":null
}
/**
     * 修改草稿
     * @param title
     * @param content
     * @param draftId
     * @return
     */
@PostMapping("/updateDraft")
public Response updateDraft(String title,String content,Integer draftId,HttpServletRequest request) {
    if (title == null || content == null || "".equals(title.trim()) || "".equals(content.trim())
        || draftId == null ||draftId < 1) {
        return Response.fail("内容非法");
    }
    User user = LogInUserInfo.getUserInfo(request);
    int ret = articleDraftService.updateDraft(title,content,draftId,user.getId());
    if (ret == 1) {
        return Response.success("保存成功");
    }
    return Response.success("保存失败");
}

6.个人信息修改

SSM个人博客项目,项目,项目,java,spring boot,mybatis

头像修改

前端传递头像,后端校验一下文件格式,生成唯一的文件名,把头像路径更新到对应的用户数据库。SpingBoot对文件上传大小有默认限制,我们只需处理对应的异常即可。

@SneakyThrows
@PostMapping("/updatePhoto")
public Response updatePhoto(@RequestPart("photo")MultipartFile imgFile, HttpServletRequest request,
                            HttpServletResponse response) {
    // 设置重定向
    response.setStatus(302);
    response.sendRedirect("/user_blog_list.html");
    if (imgFile != null && !imgFile.isEmpty()) {
        String fileName = imgFile.getOriginalFilename();
        if (fileName.contains(".jpg") || fileName.contains(".png")) {
            // 1.生成唯一文件名
            String newFileName = UUID.randomUUID().toString().replaceAll("-","")+fileName.substring(fileName.length()-4);
            // 路径,文件名
            File file = new File(photoPath,newFileName);
            //保存文件
            imgFile.transferTo(file);
            User user = LogInUserInfo.getUserInfo(request);
            int ret = userService.updatePhoto(user.getId(),Constant.PHOTO_UPLOAD_PATH+newFileName);
            if (ret == 1) {
                return Response.success("修改成功");
            }
        }
    }

    return Response.fail("修改失败");
}

基本信息修改

修改网名和gitee连接

请求:

POST http://127.0.0.1:7070/user/updateUserInfo HTTP/1.1
{
    netName:"网名",
    "gitee": "gitee链接"
}

响应:

{
    "code":200,
    "message":"修改成功",
    "data":null
}
@PostMapping("/updateUserInfo")
public Response updateUserInfo(String netName,String git,HttpServletRequest request) {
    if (netName == null || git == null || "".equals(netName.trim()) || "".equals(git.trim())
        || (!git.contains("https://"))) {
        return Response.fail("参数非法或git链接非法");
    }
    User user = LogInUserInfo.getUserInfo(request);
    int ret = userService.updateUserInfo(netName,git,user.getId());
    if (ret == 1) {
        return Response.success("修改成功");
    }
    return Response.fail("修改失败");
}

7. 其它密码相关功能实现

SSM个人博客项目,项目,项目,java,spring boot,mybatis

修改密码

修改密码比较简单,用户登录后,输入原密码和新密码,后端通过解密方式验证。验证通过即可修改密码。

@PostMapping("/updatePassword")
public Response updatePassword(String password,String newPassword,String confirmPassword,
                               HttpServletRequest request) {
    if (password ==null || newPassword == null || confirmPassword == null ||
        "".equals(password.trim()) || "".equals(newPassword.trim()) || "".equals(confirmPassword.trim())) {
        return Response.fail("修改失败");
    }
    User user = LogInUserInfo.getUserInfo(request);
    User myUser = userService.byIdUser(user.getId());
    if (PasswordUtil.check(password,myUser.getPassword())) {
        String finalPass = PasswordUtil.passwordAddSalt(newPassword);
        int ret = userService.updatePassword(finalPass,user.getId());
        if (ret == 1) {
            HttpSession session = request.getSession(false);
            session.removeAttribute(Constant.SESSION);
            return Response.success("修改成功");
        }
    }

    return Response.fail("修改失败,密码错误");
}

设置密保问题

SSM个人博客项目,项目,项目,java,spring boot,mybatis

在用户第一登录的时候提示用户设置密保问题,通过密保问题即可找回密码。

给定3个问题和指定的问题选项,让用户输入答案,和用户密码进行设置密码问题。再对答案进行md5加密存入数据库。

请求:

POST http://127.0.0.1:7070/questionPass/addQuestionPassword HTTP/1.1
{
    password:hhy,
    question1=你最相信的人的姓名是,
    question2=你的出生地是,
    question3=你最喜欢吃的水果是,
    answer1=某某,
    answer2=湖南,
    answer3=葡萄
}

响应:

{
    "code":200,
    "message":"密保问题设置成功",
    "data":null
}

找回密码

通过用户设置的密保问题来找回密码,用户输入查找的用户名来获取对应的密保问题,再输入答案后,对答案进行md5同问题一起比对验证,端验证正确后,再给用户输入新密码,输入新密码后再次提交。修改密码前再次验证一下密保问题,如果验证通过即可修改密码。
SSM个人博客项目,项目,项目,java,spring boot,mybatis文章来源地址https://www.toymoban.com/news/detail-635219.html


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

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

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

相关文章

  • SSM vs Spring Boot+Mybatis:哪个框架更适合你?

    SSM框架是指Spring+Spring MVC+Mybatis三个框架的组合,它是一个传统的Java Web开发框架,可以实现Web层、业务层和持久层的分离和整合。 SSM框架的优点有: 结构清晰,分层明确,符合MVC模式。 Spring MVC是一个轻量级的Web层框架,可以接收用户请求,调用业务逻辑层,处理模型数据,

    2024年02月11日
    浏览(56)
  • 课程设计基于Spring Boot+Semantic ui的个人博客系统的设计与实现

    项目背景: 本项目是基于互联网软件开发技术搭建的一款个人博客系统,因为自己十分喜欢创作,比如写一些开源项目,写一些博客笔记,虽然网络上有许多大型博客系统,但是一直想写一个属于自己专有的博客系统,比如可以上传一些自己的知识笔记,上传一些自己的生活

    2024年02月04日
    浏览(39)
  • (附源码)基于Spring Boot的个人博客系统的设计与实现 毕业设计271611

    目 录 摘要 1 1 绪论 1 1.1研究意义 1 1.2开发背景 1 1.3系统开发技术的特色 1 1.4论文结构与章节安排 1 2 个人博客系统系统分析 3 2.1 可行性分析 3 2.2 系统流程分析 3 2.2.1数据增加流程 3 2.3.2数据修改流程 4 2.3.3数据删除流程 4 2.3 系统功能分析 4 2.3.1 功能性分析 4 2.3.2 非功能性分析

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

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

    2024年01月22日
    浏览(82)
  • java版企业工程项目管理系统 Spring Cloud+Spring Boot+Mybatis+Vue+ElementUI+前后端分离 功能清单

         Java版工程项目管理系统 Spring Cloud+Spring Boot+Mybatis+Vue+ElementUI+前后端分离 功能清单如下: 首页 工作台:待办工作、消息通知、预警信息,点击可进入相应的列表 项目进度图表:选择(总体或单个)项目显示1、项目进度图表  2、项目信息 施工地图:1、展示当前角色权

    2024年02月08日
    浏览(64)
  • SSM(Spring,SpringMVC,MyBatis)整合项目

    2024年01月18日
    浏览(62)
  • 个人博客系统(SSM版 前端+后端)

             在学习Servlet的时候,也写了一个博客系统,主要的就是使用servelet加Tomcat进行实现的,而这个项目 仅仅适合去学习Web项目开发的思想,并不满足当下企业使用框架的思想,进行学习过Spring,Spring Boot,Spring MVC以及MyBatis之后,我们就可以对之前的项目使用SSM框架的形式进行升

    2024年02月16日
    浏览(38)
  • spring boot3单模块项目工程搭建-上(个人开发模板)

      ⛰️个人主页:     蒾酒 🔥系列专栏 :《spring boot实战》 目录 写在前面 上文衔接 常规目录创建 common目录 exception.handle目录 result.handle目录 controller目录 service目录 mapper目录 entity目录 test目录 写在最后 本文介绍了springboot开发后端服务,单模块项目工程搭建。单模块搭建出

    2024年04月29日
    浏览(38)
  • spring boot3单模块项目工程搭建-下(个人开发模板)

    ⛰️个人主页:     蒾酒 🔥系列专栏 :《spring boot实战》 目录 写在前面 上文衔接 常用依赖介绍以及整合 web组件 测试组件 样板代码生成 数据库连接器 常用工具包 面向切面编程 ORM框架 数据连接池 接口测试、文档导出 缓存中间件 参数校验 认证鉴权 基础功能完善 跨域问

    2024年04月28日
    浏览(37)
  • 基于SSM+vue框架的个人博客网站源码和论文

    基于SSM+vue框架的个人博客网站源码和论文061  开发工具:idea   数据库mysql5.7+  数据库链接工具:navcat,小海豚等   技术:ssm (设计)研究背景与意义 关于博客的未来:在创办了博客中国(blogchina)、被誉为“博客教父”的方兴东接受了记者的专访。他认为,博客这一事物在中

    2024年02月11日
    浏览(47)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包