24.<Spring博客体系①(数据库+公共代码+持久层+显示博客列表+博客详情) ...

诗林  金牌会员 | 2024-11-19 07:16:06 | 来自手机 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 718|帖子 718|积分 2154

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
项目整体预览

   登录页面
  

    主页
   

   查看全文 
  

    编辑
  

   写博客 
  

PS:Service.impl(现在流行写法)

   

  推荐写法。后续完成项目。会实验这样写。
  接口可以有多个实现。每个实现都可以不同。
  这也算一种设计模式。叫做(策略模式)。
  我们博客项目较为简朴。Service层我们还是只写一层。如果后续有更复杂的项目。我们就会利用多层。
  
  而。
  Mapper.impl
  Mapper里放的接口。
  impl里面放的是接口的实现。(早期写法)
    1.分析需求
  
  2.技能方案设计
  ①画UML图、流程图、ER图
  
  ②数据库的设计、
  数据库的表通常分两类。实体表、关系表。
  实体表:可以以为就是一个对象。一个对象包含什么属性。好比人员表、员工表、部门表、图书表、博客表、这些都是实体表
  关系表:表示实体之间的关系,好比员工属于什么部门。用户表、权限表、用户和权限相关关系。实体之间都是有关系的。对于简朴的关系。该表可以省略。可以放在实体表之中。
  好比一个用户可以有多个权限。
  
  
  ③接口设计、、
  
  3.开辟
  4.测试
  5.测试(QA)
  6.联调
  7.验收
  8.上线
  
   数据库的设计
  用户表:用户名、暗码、照片、昵称、github地点
  博客表:标题、日期、内容、作者、分类。
  这两者有很多关系。那么我们可以单独建立一个表
  
  接口的设计
  后端人员是主动地
  登录接口
  一、创建项目

   创建细节就不一一演示了。这是是我们利用的IDEA中重要的依赖的版本。
  1.     <properties>
  2.         <java.version>1.8</java.version>
  3.         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  4.         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  5.         <spring-boot.version>2.6.13</spring-boot.version>
  6.     </properties>
  7.     <dependencies>
  8.         <dependency>
  9.             <groupId>org.springframework.boot</groupId>
  10.             <artifactId>spring-boot-starter-web</artifactId>
  11.         </dependency>
  12.         <dependency>
  13.             <groupId>org.mybatis.spring.boot</groupId>
  14.             <artifactId>mybatis-spring-boot-starter</artifactId>
  15.             <version>2.2.2</version>
  16.         </dependency>
复制代码
二、设置文件处理

   将
  

  修改为
  

  
三、建立数据库


  1. --创建数据库
  2. create database if not exists spring_blog charset utf8mb4;
  3. -- ⽤⼾表
  4. DROP TABLE IF EXISTS spring_blog.user;
  5. CREATE TABLE spring_blog.user(
  6.     `id` INT NOT NULL AUTO_INCREMENT,
  7.     `user_name` VARCHAR ( 128 ) NOT NULL,
  8.     `password` VARCHAR ( 128 ) NOT NULL,
  9.     `github_url` VARCHAR ( 128 ) NULL,
  10.     `delete_flag` TINYINT ( 4 ) NULL DEFAULT 0,
  11.     `create_time` DATETIME DEFAULT now(),
  12.     `update_time` DATETIME DEFAULT now(),
  13. PRIMARY KEY ( id ),
  14. UNIQUE INDEX user_name_UNIQUE ( user_name ASC )) ENGINE = INNODB DEFAULT
  15. CHARACTER SET  = utf8mb4 COMMENT = '⽤⼾表';
  16. -- 博客表
  17. drop table if exists spring_blog.blog;
  18. CREATE TABLE spring_blog.blog (
  19.     `id` INT NOT NULL AUTO_INCREMENT,
  20.     `title` VARCHAR(200) NULL,
  21.     `content` TEXT NULL,
  22.     `user_id` INT(11) NULL,
  23.     `delete_flag` TINYINT(4) NULL DEFAULT 0,
  24.     `create_time` DATETIME DEFAULT now(),
  25.     `update_time` DATETIME DEFAULT now(),
  26.     PRIMARY KEY (id))
  27.     ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT = '博客表';
  28. -- 新增⽤⼾信息
  29. insert into spring_blog.user (user_name, password,github_url)values('zhangsan','123456','https://gitee.com/Bwindmill');
  30. insert into spring_blog.user (user_name, password,github_url)values('lisi','123456','https://gitee.com/Bwindmill');
  31. insert into spring_blog.user (user_name, password,github_url)values('wangwu','123456','https://gitee.com/Bwindmill');
  32. insert into spring_blog.user (user_name, password,github_url)values('luliu','123456','https://gitee.com/Bwindmill');
  33. insert into spring_blog.blog (title,content,user_id) values('第⼀篇博客','1111111',1);
  34. insert into spring_blog.blog (title,content,user_id) values('第二篇博客','2222222',2);
复制代码
四、测试 

    之后运行一下程序,看程序有没有问题。
  并且写一个简朴的程序测测运行正常不正常。
  eg:
  1. @RestController
  2. public class UserController {
  3.     @RequestMapping("/test")
  4.     public String test(){
  5.         return "Hello";
  6.     }
  7. }
复制代码

  对于新手来说。我们就写一点测一点。逐步来。
将前端代码cv到staric目录中。我们再测一测前端代码能不能正常访问。


五、誊写项目公共模块代码

项目架构图


5.1实体类

   UserInfo类
  1. @Data
  2. public class UserInfo {
  3.     private Integer id;
  4.     private String userName;
  5.     private String password;
  6.     private String githubUrl;
  7.     private Integer deleteFlag;
  8.     private Date createTime;
  9.     private Date updateTime;
  10. }
复制代码
  BlogInfo类
  1. @Data
  2. public class BlogInfo {
  3.     private Integer id;
  4.     private String title;
  5.     private String content;
  6.     private Integer userId;
  7.     private Integer deleteFlag;
  8.     private Date createTime;
  9.     private Date updateTime;
  10. }
复制代码
5.2同一结果返回

   Result类
  1. /**
  2. * 统一返回结果
  3. * 我们先设定返回的结果
  4. * 为了让其他地方方便调用。我们统一给方法加上static
  5. */
  6. @Data
  7. public class Result {
  8.     private int code; //200成功, -1失败  -2未登录
  9.     private String errMsg;
  10.     private Object data;
  11.     public static Result success(Object data){
  12.         Result result = new Result();
  13.         result.setCode(Constant.SUCCESS_CODE);
  14.         result.setErrMsg("");
  15.         result.setData(data);
  16.         return result;
  17.     }
  18.     public static Result fail(String errMsg){
  19.         Result result = new Result();
  20.         result.setCode(Constant.FAIL_CODE);
  21.         result.setErrMsg(errMsg);
  22.         result.setData(null);
  23.         return result;
  24.     }
  25.     public static Result fail(String errMsg,Object data){
  26.         Result result = new Result();
  27.         result.setCode(Constant.FAIL_CODE);
  28.         result.setErrMsg(errMsg);
  29.         result.setData(data);
  30.         return result;
  31.     }
  32.     public static Result unLogin(String errMsg){
  33.         Result result = new Result();
  34.         result.setCode(Constant.UNLOGIN_CODE);
  35.         result.setErrMsg("用户未登录");
  36.         result.setData(null);
  37.         return result;
  38.     }
  39. }
复制代码
  ResponseAdvice类
  1. @ControllerAdvice //注意加上这个注解才有效。
  2. public class ResponseAdvice implements ResponseBodyAdvice {
  3.     @Autowired
  4.     private ObjectMapper objectMapper;
  5.     @Override
  6.     public boolean supports(MethodParameter returnType, Class converterType) {
  7.         /**
  8.          * 设定哪些方法统一返回结果
  9.          * 哪个接口执行统一结果返回
  10.          */
  11.         return true;
  12.     }
  13.     @SneakyThrows
  14.     //这个注解帮我们对
  15.     // return objectMapper.writeValueAsString(Result.success(body));
  16.     //进行try catch。异常处理
  17.     @Override
  18.     public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
  19.         //统一结果返回的具体逻辑
  20.         if(body instanceof Result){
  21.             return body;
  22.         }
  23.         //对String 类型单独处理.否则会报错
  24.         if (body instanceof String){
  25.             return objectMapper.writeValueAsString(Result.success(body));
  26.         }
  27.         return Result.success(body);
  28.     }
  29. }
复制代码
5.3同一非常处理

   第一种写法
  ErrorHandler类
  三个注解:@ResponseBody @ControllerAdvice @ExceptionHandler
  1. @ResponseBody
  2. @ControllerAdvice
  3. public class ErrorHandler {
  4.     @ExceptionHandler
  5.     public Result handler(Exception e){
  6.         return Result.fail(e.getMessage());
  7.     }
  8. }
复制代码
  第二种写法
  eg:
  /捕获空指针非常代码的两种写法
  1.     //捕获空指针异常代码的两种写法
  2.     @ExceptionHandler(NullPointerException.class)
  3.     public Result handler(Exception e){
  4.         return Result.fail(e.getMessage());
  5.     }
  6.     @ExceptionHandler
  7.     public Result handler(NullPointerException e){
  8.         return Result.fail(e.getMessage());
  9.     }
复制代码
 如果注解里面没有写捕获什么非常。那么就会以参数中为准。
  
六、业务代码

MybatisGenerate插件

   注:持久层的代码可以由MybatisGenerate插件一键天生。
  直接根据我们的数据库表
天生实体类,mapper类,xml文件
不需要我们自己写mapper类,和基于标签的mapper.xml这些简朴又繁琐的工作
但是值得注意的是天生的方法中的细微区别!!
  接口分析

   1.用户登录
  根据用户名和暗码、判断是否正确。
  
  2.查询用户信息
  根据用户Id.查询用户信息。
  
  3.博客列表
  查询所有博客
  
  4.查询作者信息
  ①根据博客,拿到作者Id
  ②根据作者id,获取作者信息
  
  5.查询博客详情
  根据博客id,查询博客信息
  
  6.修改博客
  根据博客id,修改博客信息
  
  7.添加博客
  插入博客信息
  
  8.删除博客
    梳理一下
  
  用户表:
  1.根据用户名,查询用户信息。
  2.根据用户id,查询用户信息
  
  博客表
  1.查询博客列表
  2.根据博客id,查询博客信息
  3.根据博客id,修改博客信息
  4.插入博客
  5.删除博客 
  6.1持久层代码

   UserMapper类
  1. @Mapper
  2. public interface UserMapper {
  3.     //根据用户名,查询用户信息\
  4.     @Select("select * from user where user_name = #{userName} and delete_flag = 0")
  5.     UserInfo selectByName(String userName);
  6.     @Select("select *from user where id = #{userId} and delete_flag = 0")
  7.     UserInfo selectById(Integer userId);
  8. }
复制代码
   BlogMapper类
  注:由于update既是uptate功能的接口。也是delete功能的接口,因此我们要写动态SQL。
  动态SQL我们利用XML的方式来誊写。
  1. @Mapper
  2. public interface BlogMapper {
  3.     //查询博客列表
  4.     @Select("select * from blog where delete_flag =0 order by create_time desc ")
  5.     List<BlogInfo> selectAllBlog();
  6.     //根据博客Id,查询博客信息。
  7.     @Select("select * from blog where id = #{blogId} and delete_flag = 0")
  8.     BlogInfo selectById(Integer blogId);
  9.     //根据博客Id,修改博客信息。
  10.     //此修改包括修改和删除。根据参数决定修改什么。
  11.     //我们用动态SQL来实现
  12.     Integer updateById(BlogInfo blogInfo);
  13.     //插入博客
  14.     @Insert("insert into blog (title, content, user_id) values (#{title},#{content},#{userId})")
  15.     Integer interBlog(BlogInfo blogInfo);
  16.    
  17. }
复制代码

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  3.         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  4. <mapper namespace="com.qyy.springblog.mapper.BlogMapper">
  5.     <update id="updateById">
  6.         update blog
  7.         <set>
  8.             <if test="title != null">
  9.                 title = #{title},
  10.             </if>
  11.             <if test="content != null">
  12.                 content = #{content},
  13.             </if>
  14.             <if test="deleteFlag != null">
  15.                 delete_flag = #{deleteFlag},
  16.             </if>
  17.         </set>
  18.         where id = #{id}
  19.     </update>
  20. </mapper>
复制代码
  写完之后。我们测试一下持久层代码是否都正确执行。 
  6.2实现前后端接口

6.2.1实现博客列表显示的接口

   后端
  1.     @RequestMapping("/getList")
  2.     public List<BlogInfo> queryBlogList(){
  3.         return blogService.queryBlogList();
  4.     }
复制代码
  1.     public List<BlogInfo> queryBlogList() {
  2.         return blogMapper.selectAllBlog();
  3.     }
复制代码
  前端 
  1.     <script>
  2.         $.ajax({
  3.             type: "get",
  4.             url: "blog/getList",
  5.             success:function(result){
  6.                 //逻辑不全,可以再完善
  7.                 //比如code == 200,但是data为空,页面可以提示,当前没有任何博客,快去写博客。然后进行跳转
  8.                 if(result.code == 200 && result.data!=null){
  9.                     var finalHtml = "";
  10.                     for(var blog of result.data){  //循环的时候每个数据叫blog
  11.                         finalHtml += '<div class="blog">';
  12.                         finalHtml += '<div class="title">'+blog.title+'</div>';
  13.                         finalHtml += '<div class="date">'+blog.createTime+'</div>';
  14.                         finalHtml += '<div class="desc">'+blog.content+'</div>';
  15.                         finalHtml += '<a class="detail" href="blog_detail.html?blogId='+blog.id+'">查看全文&gt;&gt;</a>';
  16.                         finalHtml += '</div>';
  17.                     }
  18.                     $(".right").html(finalHtml);
  19.                 }
  20.             }
  21.         });
  22.     </script>
复制代码
  我们发现显示的时间很长。 返回的时间就如我们postman返回的时间一样。
  如何修改呢。我们最好在后端同一修改了
  


修改时间显示 

   我们在blog实体类中修改。
  1.创建utils包。
  2.创建 DataUtils 类
  3.创建formatDate方法
  指定我们的时间返回格式的方法参考如下表。
  1. public class DateUtils {
  2.     public static String formatDate(Date date){
  3.         SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
  4.         return simpleDateFormat.format(date);
  5.     }
  6. }
复制代码
4.在blog实体类添加如下代码
  1.     public String getCreateTime(){
  2.         return DateUtils.formatDate(createTime);
  3.     }
复制代码

  

存的的问题

这是博客列表显示的 

   在博客列表中我们发现存在####。
  不但云云。我们还希望。在博客列表中只显示一部分博客。而不是将博客全部显示出来。这个又该怎么利用呢?
  这个如何修改呢 
  1.去掉特殊符号
  2.对内容长度进行处理
  ①通过SQL截断
  ②通过Java截断
   我选择通过java截断
  1.     public List<BlogInfo> queryBlogList() {
  2.         List<BlogInfo> blogInfos = blogMapper.selectAllBlog();
  3.         for (BlogInfo blog: blogInfos){
  4.             String result = blog.getContent();
  5.             result = result.replace("#","");
  6.             if(result.length() >= 66){
  7.                 result = result.substring(0,65)+"......";
  8.             }
  9.             blog.setContent(result);
  10.         }
  11.         return blogInfos;
  12.     }
复制代码
实现成功
  

  6.2.2实现博客查看全文接口

   后端
  1.     @RequestMapping("getBlogDetail")
  2.     public BlogInfo queryBlogById(Integer blogId){
  3.         return blogService.queryBlogById(blogId);
  4.     }
复制代码
  1.     @RequestMapping("getBlogDetail")
  2.     public BlogInfo queryBlogById(Integer blogId){
  3.         return blogService.queryBlogById(blogId);
  4.     }
复制代码

正确返回 
   前端
  1.         <div class="right">
  2.             <div class="content">
  3.                 <div class="title"></div>
  4.                 <div class="date"></div>
  5.                 <div class="detail"></div>
  6.                 <div class="operating">
  7.                     <button onclick="window.location.href='blog_update.html'">编辑</button>
  8.                     <button onclick="deleteBlog()">删除</button>
  9.                 </div>
  10.             </div>
  11.         </div>
复制代码
  1.         $.ajax({
  2.             type: "get",
  3.             url: "/blog/getBlogDetail"+location.search, //location.search拿到问号及后面的内容
  4.             success:function(result){
  5.                 var blog = result.data;
  6.                 if(result.code == 200 && result.data!=null){
  7.                     $(".right .content .title").text(blog.title);
  8.                     $(".right .content .date").text(blog.createTime);
  9.                     $(".right .content .detail").text(blog.content);
  10.                 }
  11.             }
  12.         });
复制代码

   成功显示。 
  本篇博客暂时就写到这里啦。后续内容会在下一篇文章更新哦。
后面登录的接口才是本次项目的大Boss。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

诗林

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表