栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

SpringBoot开发小而美的博客——学习笔记

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SpringBoot开发小而美的博客——学习笔记

SpringBoot开发小而美的博客——学习笔记
  • 1 需求与功能
    • 1.1 用户故事
    • 1.2 功能规划
  • 2 页面设计与开发
    • 2.1 页面设计
    • 2.2 页面开发
    • 2.3 插件集成
  • 3 框架搭建
    • 3.1 构建与配置
    • 3.2 异常处理
    • 3.3 日志处理
    • 3.4 页面处理
  • 4 设计与规范
    • 4.1 实体设计
    • 4.2 应用分层
    • 4.3 命名约定
  • 5 后台管理
    • 5.1 登录
    • 5.2 分类管理
    • 5.3 标签管理
    • 5.4 博客管理
  • 6 前端展示
    • 6.1 首页展示
    • 6.2 分类页
    • 6.3 标签页
    • 6.4 归档页
    • 6.5 关于我
  • 部署到服务器

学习链接: SpringBoot开发一个小而美的个人博客。

  • 技术组合:
    • 后端:SpringBoot + JPA + thymeleaf模板
    • 数据库:MySQL
    • 前端UI:Semantic UI框架
  • 工作与环境:
    • IDEA
    • Maven3
    • JDK8
    • Axure RP 8
  • 课程内容模块
    • 需求分析和功能规划
    • 页面设计与开发
    • 技术框架搭建
    • 后端管理功能实现
    • 前端管理功能实现
  • 你能学到什么
    • 基于SpringBoot完整全栈式的开发套路
    • Semantic UI框架的使用
    • 一套博客系统的源代码与设计
1 需求与功能 1.1 用户故事

  用户故事是敏捷开发的一种方法,从用户的角度描述需求,用户故事模板:

  • 作为一个(某个角色)使用者,我可以做(某个功能)事情,如此可以有某个(商业价值)的好处。
  • 角色、功能、商业价值

举例:

  • 作为一个招聘网站注册用户,我想查看最近三天发布的招聘信息,以便于了解最新的招聘信息。

确定角色:

  • 普通访客、管理员(我)

访客实现的功能:

管理员实现的功能:

1.2 功能规划

2 页面设计与开发 2.1 页面设计

  使用Axure RP 8进行原型设计,软件下载安装可自行百度。根据上面的功能规划图可以总结出需要设计的页面。

  • 前端展示页面:首页、详情页、分类、标签、归档、关于我
  • 后端管理页面:模板页
2.2 页面开发

  Semantic是快速构建前端页面的框架。我们使用WebStorm开发。把下面的css放在head标签中,第二行js放在body标签最底部。



  在https://www.jsdelivr.com/里找到JQuery的CDN导入。


2.3 插件集成

背景图片资源
编辑器Markdown,
内容排版typo.css,
动画animate.css,
代码高亮prism或者官网,
滚动侦测waypoints,
平滑滚动jquery.scrollTo,
目录生成Tocbot,
二维码生成qrcode.js。

3 框架搭建 3.1 构建与配置

1、引入SpringBoot模块:

  • web
  • Thymeleaf
  • IPA
  • MySQL
  • Aspects(在SpringBoot2.x自动导入了)
  • Devtools

2、application-dev.yml配置

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/bolg?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
    username: root
    password: root
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true

logging:
  level: 
    root: info
    com.zkp: debug

配合logback.xml



    
    
    
    

    
    
        
            ${FILE_LOG_PATTERN}
        
        ${LOG_FILE}
        
            ${LOG_FILE}.%d{yyyy-MM-dd}.%i
            
            3
            
            
                10MB
            

        
    

    
        
        
    


application/yml

spring:
  profiles:
    active: dev
3.2 异常处理

1、定义错误页面

  • 404
  • 500
  • error

  从后台获取信息在static下完成不了,因此在template下定义错误页面,新建error文件夹,下面创建404.html和500.html,如果出现异常,Spring约定会在error文件夹下使用对应的html页面,比如404对应404.html。

2、全局处理异常
  新建包handler,创建类ControllerExceptionHandler,

@ControllerAdvice
public class ControllerExceptionHandler {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @ExceptionHandler(Exception.class)
    public ModelAndView exceptionHandler(HttpServletRequest request, Exception e) throws Exception {
        logger.error("Request URL: {}, Exception: {}", request.getRequestURL(), e.toString());
        e.printStackTrace();

        if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class) != null) {
            throw e;
        }

        ModelAndView mv = new ModelAndView();
        mv.addObject("url", request.getRequestURL());
        mv.addObject("exception", e);
        mv.setViewName("error/error");
        return mv;
    }
}

  在error.html中加上下列代码,作用是在源代码中打印错误信息,这样如果出错,在前端就能看到哪里出错,不用跑到服务器去看。

>'" th:remove="tag">


新建exception,创建NotFoundException

@ResponseStatus(HttpStatus.NOT_FOUND)
public class NotFoundException extends RuntimeException{
    public NotFoundException() {
    }

    public NotFoundException(String message) {
        super(message);
    }

    public NotFoundException(String message, Throwable cause) {
        super(message, cause);
    }
}
3.3 日志处理

  采用SpringBoot的AOP进行日志处理,记录日志内容有:

  • 请求url
  • 访问者ip
  • 调用方法classMethod
  • 参数args
  • 返回内容

编写BlogAspect如下:

@Aspect
@Component
public class LogAspect {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Pointcut("execution(* com.zkp.web.*.*(..))")
    public void log(){

    }

    @Before("log()")
    public void doBrfore(JoinPoint joinPoint) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        String url = request.getRequestURL().toString();
        String ip = request.getRemoteAddr();
        String classMethod = joinPoint.getSignature() + " ";
        Object[] args = joinPoint.getArgs();
        RequestLog requestLog = new RequestLog(url, ip, classMethod, args);
        //记录
        logger.info("Request:" + requestLog);
    }

    @After("log()")
    public void doAfter() {
        // logger.info("------after------");
    }

    @AfterReturning(returning = "result",pointcut = "log()")
    public void doAfterReturn(Object result) {
        //记录
        logger.info("-----Result------:" + result);
    }

    private class RequestLog {
        private String url;
        private String ip;
        private String classMethod;
        private Object[] args;

        public RequestLog(String url, String ip, String classMethod, Object[] args) {
            this.url = url;
            this.ip = ip;
            this.classMethod = classMethod;
            this.args = args;
        }

        @Override
        public String toString() {
            return "{" +
                    "url='" + url + ''' +
                    ", ip='" + ip + ''' +
                    ", classMethod='" + classMethod + ''' +
                    ", args=" + Arrays.toString(args) +
                    '}';
        }
    }
}

效果如下:

3.4 页面处理

1、静态页面导入project
这里如果目录结构没有对上,需要移动html文件位置,记得勾选search for references,会自动修改引用位置。
导入之后再设置路径进行访问,结果报错500,解决方法是clean之后重新编译。F12控制台可以看到有些访问不到

需要使用th:href=“@{}”,注意这里默认到stati里面找。如果页面很多,每一个都需要这样处理比较麻烦,在thymeleaf中的fragment可以解决这个问题。

2、thymeleaf布局

  • 定义fragment
    新建_fregments.html,编写head标签

    
    
    
    首页
    
    
    
    
    
    

  • 使用fragment布局
    在其他html页面的head中这样修改

    
    
    
    首页
    
    


        
        

这样两端都可以用
3、优化错误页面
加入head和footer,并加入错误信息提示:

404

对不起,您访问的资源不存在

4 设计与规范

  

4.1 实体设计

  可以先建表,也可以面向对象的思维,先设计实体,再用Spring Boot的JPA设计数据库表结构。
实体类:

  • 博客Blog
  • 博客分类Type
  • 博客标签Tag
  • 博客评论Comment
  • 用户User

关系:例如,类型和博客之间是一对多的关系。

评论和回复的关系:

Blog类:包含一组标签,一组评论,一个用户。

评论类:

用户类:

  以创建Blog为例,需要加上这些注解:JPA使用@Entity表示有数据库生成的能力,@Table可以指定数据库表的名字,@Id是主键,@GeneratedValue默认生成策略。

@Entity
@Table(name = "t_blog")
public class Blog {

    @Id
    @GeneratedValue
    private Long id;
}

如果是创建日期类型,需要加上注解:

    @Temporal(TemporalType.TIMESTAMP)
    private Date createTime;

创建完实体类后,处理实体类之间的关系,例如一个博客有多个标签。在Blog类中加入注解@ManyToOne,在Type中假如注解@OneToMany。多对多同理用@ManyToMany。关系被维护方指定mappedBy。

    @ManyToOne
    private Type type;
    
    @OneToMany(mappedBy = "type")
    private List blogs = new ArrayList<>();
    
    @ManyToMany
    private List tags = new ArrayList<>();

级联新增@ManyToMany(cascade = {CascadeType.PERSIST})。
启动之后,可以看到自动生成数据库表:

4.2 应用分层

  终端显示层即template。

4.3 命名约定

Serverce和Da层方法命名约定:

  • 获取单个用get
  • 获取多个用list
  • 获取统计值用count
  • 插入用insert
  • 删除用delete
  • 修改用update
5 后台管理 5.1 登录

登录需要的步骤如下:
1、构建登录页面和后台管理首页
登录后台:

2、UserService和UserRepository
继承JpaRepository,User表示操作的对象,Long是主键类型。只要方法名符合规范,就能直接封装好sql语句。

public interface UserRepository extends JpaRepository {
    User findByUsernameAndPassword(String username, String password);
}

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRepository userRepository;

    @Override
    public User checkUser(String username, String password) {
        User user = userRepository.findByUsernameAndPassword(username,password);
        return user;
    }
}

3、LoginController实现登录

@Controller
@RequestMapping("/admin")
public class LoginController {

    @Autowired
    private UserService userService;

    @GetMapping
    public String loginPage(){
        return "admin/login";
    }

    @PostMapping("/login")
    public String login(@RequestParam String username,
                        @RequestParam String password,
                        HttpSession session,
                        RedirectAttributes attributes){
        User user = userService.checkUser(username,password);
        if(user!=null){
            user.setPassword(null);
            session.setAttribute("user",user);
            return "admin/index";
        }
        else{
            attributes.addFlashAttribute("message","用户名或密码错误");
            return "redirect:/admin";
        }
    }

    @GetMapping("/logout")
    public String logout(HttpSession session){
        session.removeAttribute("user");
        return "redirect:/admin";
    }
}

4、MD5加密
创建util.MD5Utils类

public class MD5Utils {
    
    public static String code(String str){
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(str.getBytes());
            byte[] byteDigest = md.digest();
            int i;
            StringBuffer buf = new StringBuffer("");
            for (int offset = 0; offset < byteDigest.length; offset++){
                i = byteDigest[offset];
                if (i<0){
                    i+=256;
                }
                if (i<16){
                    buf.append("0");
                }
                buf.append(Integer.toHexString(i));
            }
            return buf.toString();
        }
        catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        }
    }
}

5、登录拦截器
创建interceptor.LoginInterceptor类

public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response,
                             Object handler) throws Exception {
        if(request.getSession().getAttribute("user")==null){
            response.sendRedirect("/admin");
            return false;
        }
        return true;
    }
}

编写config配置类

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginInterceptor())
                .addPathPatterns("/admin
                
                    
                    验证失败
                    

提交信息不符合规则

""; var qrcode = new QRCode("qrcode", { text: serurl + url, width: 110, height: 110, colorDark: "#000000", colorLight: "#ffffff", correctLevel: QRCode.CorrectLevel.H });

评论功能:
1、评论信息提交与回复
2、评论信息列表展示功能
3、管理员回复评论

6.2 分类页

展示效果如下:

6.3 标签页

操作类似分类页。

6.4 归档页

所谓归档就是按照年份把发布的博客进行展示。

6.5 关于我

最后在resources下新建messages.properties文件。
可以全球化,新建两个文件messages_en_US.properties,和messages_zh_CN.properties。
如果放在i18n文件夹下,需要在yml文件中配置路径。

spring:
	message:
		basename: i18n/messages
部署到服务器

参考另外一篇博客.

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/872292.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号