Spring实现博客系统

2023-11-11

     在上次用Servlet实现了博客系统之后,一直觉得代码写起来比较繁琐,而且耦合度很高。直到学习了Spring,我又看到了一线生机,运用SpringBoot重新改造了我的博客系统,接下来讲讲Spring是个什么东西,并把我的改造思路给大家分享下。 

1、什么是Spring
Spring简直是个神奇的东西,它向所有的对象提供它所需的东西,同时也把对象所需要的东西提供给对方,大大降低了代码之间的耦合度。所有对象的销毁和创建都由Spring掌控,在Spring中有个主要概念,就是控制反转,那么什么是控制反转呢?对于某个具体的对象而言,以前是它控制其他对象,现在是所有对象都被spring控制,这就叫控制反转(IOC)。IoC在系统运行中时,动态的向某个对象提供它所需要的其他对象。而这就是由我们经常听过的DI来实现的,也就是依赖注入。举个例子,比如对象A需要操作数据库,以前我们总是要在A中自己编写代码来获得一个Connection对象,有了 spring我们就只需要告诉spring,A中需要一个Connection,至于这个Connection怎么构造,何时构造,A不需要知道。在系统运行时,spring会在适当的时候制造一个Connection,然后注射到A中,这样就完成了对各个对象之间关系的控制。A需要依赖 Connection才能正常运行,而这个Connection是由spring注入到A中的,依赖注入的名字就这么来的。那么DI是如何实现的呢? 反射(reflection)就是一种手段,它允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性,spring就是通过反射来实现注入的。

2、Spring框架配置使用流程
(1)启动容器
(2)加载xml配置
(3)根据xml配置路径,执行包扫描
(4)把带注解的对象注册到容器中,一般常用的类注解有这几种:@Controller,@Service,@Configuration,@Repository
(5)装配对象依赖关系,有这两个常见注解:@Autowired,@Resource

3、SpringBoot、SpringMVC和Spring的关系
在学了Spring之后,我们知道了它的概念,那么SpringBoot又和Spring有什么关系呢?它对Spring的缺点进行了改善和优化,典型的特点就是基于“约定优于配置”的思想。它没有了Servlet配置繁琐的缺点,没有代码生成,无需xml文件配置,可以用于嵌入式web服务器、安全、指标、健康监测、外部配置。而SpringMVC呢,它就是一种软件架构模式,把软件系统分为模式、视图、控制器三个基本部分。它的交互流程如下:
在这里插入图片描述
4、项目架构
关于Spring的知识,我会另外写一篇文章进行讲述,今天重点在于博客系统的改造。项目的开发一般的流程如下:业务需求采集->产品设计->系统设计->编码设计->测试->部署上线->运维,那么博客系统架构大概如下:
在这里插入图片描述
对于首页:显示文章列表,有注册/登录功能
对于登录页面:后端,校验用户名,密码成功—创建session,保存用户信息,提供注销功能;
文章详情页面:显示文章信息
个人博客管理页面:和首页类似,显示文章列表,提供新增,删除,修改功能
以上是整体页面的设计;
4.1基础设施搭建
(1)准备环境
maven配置:引入SpringBoot相关依赖,SpringBoot启动配置文件application.properties,里面配置日志打印
(2)基础设施
前后端约定统一的响应格式,统一异常处理,提供自定义异常(抛自定义异常,给用户看的中文错误消息,提高用户体验感)非自定义异常,不能给用户看,需要转成用户可以看的信息,加入统一异常处理后,响应状态码都是200;前后端接口,需要使用的字段,抽象为模型类。统一用户会话管理:使用拦截器,搭配后端服务统一前缀,需要准备好页面以及后端接口;
4.2业务实现
(1)准备页面,在脑海里想象一下,页面之间是如何交互的,前后端又是如何交互的(业务流程)
(2)准备后端接口+模拟数据
特别要注意的是业务流程,如果是ajax相关,ajax发请求–后端请求映射方法,返回响应–ajax回调函数执行,收集请求数据发送。
4.3前端设计
(1)设计html页面元素
结合vue.js前端框架(快速开发前端的js框架,前端dom元素对应的双向绑定的)
绑定变量:
(1.1)标签内容绑定变量:{{变量名}}
(1.2)表单输入绑定:表单标签使用v-model=“变量名”
(1.3)条件:某个标签使用v-if=“变量名”/v-else 使用在某些条件展示内容
变量设计遵循不需要和后端交互原则,如前端按钮点击事件。
(2)设计用户事件相关
在某个事件发生时,绑定事件函数,如页面初始化事件,其他用户事件,一般是和变量结合设计。
4.4前后端开发
(1)约定好前后端接口,前端、后端可以独立开发,符合现在前后端分离的模式。
以上就是我对博客系统的整体架构,下面展示实现流程;
5、后端具体实现
5.1启动类,使用SpringApplication

package org.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication

// 启动类
public class Application {

    //SpringBoot在idea中运行,是在taregt/class目录下

    public static void main(String[] args) {

        // 注意第一个参数是当前类的类对象
        SpringApplication.run(Application.class, args);

    }


}

5.2自定义异常和响应数据的设计

package org.example.exception;


public class AppException extends RuntimeException{

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

    public AppException(String message,Throwable cause) {
        super(message,cause);
    }
}

package org.example.base;


import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@ToString
@Getter
@Setter

public class ResponseResult {

    //业务操作是否成功:前端统一在成功回调处理
    private boolean ok;

    //业务操作成功.
    private Object data;

    //业务操作失败,返回提示信息
    private String message;
}

package org.example.config;

import lombok.extern.slf4j.Slf4j;
import org.example.base.ResponseResult;
import org.example.exception.AppException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * 统一异常处理:
 * 响应需要返回统一数据格式(ok=false,messgae)
 * 自定义异常,直接取异常携带中文信息,以便用户读懂
 * 非自定义异常,转换
 */

@ControllerAdvice
@Slf4j
public class ExceptionAdvice {

    @ExceptionHandler(AppException.class)
    @ResponseBody
    public Object handleAppException(AppException e){

        //异常的打印
        log.debug("自定义异常",e);
        ResponseResult json = new ResponseResult();

        json.setMessage(e.getMessage());
        return json;
    }


    @ExceptionHandler(Exception.class)
    @ResponseBody
    public Object handleException(Exception e){

        log.error("系统出错了!",e);
        ResponseResult json = new ResponseResult();

        json.setMessage("未知错误,请联系管理员!");
        return json;

    }
}

5.3用户和文章字段设计

package org.example.model;


import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import java.io.Serializable;

@ToString
@Setter
@Getter
//User对象需要保存在session里,属于java对象序列化(序列化为二进制数据)
public class User implements Serializable {


    private static final long serialVersionUID = 0;

    /**
     * 用户名
     */
    private String username;

    /**
     * 密码
     */
    private String password;

    /**
     * 昵称
     */

    private String nickname;

    /**
     * 邮箱
     */

    private String email;

    /**
     * 头像
     */

    private String head;


}

package org.example.model;


import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@ToString
@Setter
@Getter
public class Article {

    /**
     * 文章id
     */
    private Integer id;

    /**
     * 文章标题
     */
    private String title;

    /**
     * 文章内容
     */
    private String content;

}

5.4数据的模拟以及对象注册

package org.example.config;

import org.example.model.Article;
import org.example.model.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.ArrayList;
import java.util.List;

@Configuration
public class DataConfig {


    @Bean
    public User user(){
        User user = new User();
        user.setUsername("abc");
        user.setPassword("123");
        user.setNickname("Kaiser");
//        user.setEmail("1732000@qq.com");

        return user;
    }

    @Bean
    public List<Article> articleList(){

        List<Article> list = new ArrayList<>();

        Article a1 = new Article();
        a1.setId(1);
        a1.setTitle("手动蝶阀带我飞");
        a1.setContent("举舞弄轻盈");
        list.add(a1);

        Article a2 = new Article();
        a2.setId(2);
        a2.setTitle("单身宿舍");
        a2.setContent("的单色驱蚊器而且我开发及");
        list.add(a2);

        Article a3 = new Article();
        a3.setId(3);
        a3.setTitle("慕课上");
        a3.setContent("开发,十一哦哦巨大市财政局");
        list.add(a3);

        return list;

    }
}

5.5封装Controller里返回空的情况

package org.example.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.example.config.web.RequestResponseBodyMethodProcessorWrapper;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

//定义SpringMVC的启动配置类
@Configuration
public class AppConfig implements WebMvcConfigurer, InitializingBean {

    @Autowired
    private ObjectMapper objectMapper;

    @Resource
    private RequestMappingHandlerAdapter adapter;

    //之前以@ControllerAdvice+实现ResponseBodyAdvice接口,完成统一处理返回数据包装:无法解决返回值为null需要包装
    //改用现在这种方式,可以解决返回null包装为自定义类型
    @Override
    public void afterPropertiesSet() throws Exception {

        List<HandlerMethodReturnValueHandler> returnValueHandlers = adapter.getReturnValueHandlers();
        List<HandlerMethodReturnValueHandler> handlers = new ArrayList(returnValueHandlers);
        for(int i=0; i<handlers.size(); i++){
            HandlerMethodReturnValueHandler handler = handlers.get(i);
            if(handler instanceof RequestResponseBodyMethodProcessor){
                handlers.set(i, new RequestResponseBodyMethodProcessorWrapper(handler));
            }

        }
        adapter.setReturnValueHandlers(handlers);

    }


    //配置Controller中请求映射方法路径匹配规则
    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        //设置路径前缀的规则,以第二个参数的返回值作为请求映射方法是否添加前缀
        configurer.addPathPrefix("api", c->true);

    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {

    }

}
package org.example.config.web;

import org.example.base.ResponseResult;
import org.springframework.core.MethodParameter;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;

public class RequestResponseBodyMethodProcessorWrapper implements HandlerMethodReturnValueHandler {

    private final HandlerMethodReturnValueHandler delegate;

    public RequestResponseBodyMethodProcessorWrapper(HandlerMethodReturnValueHandler delegate) {
        this.delegate = delegate;
    }

    @Override
    public boolean supportsReturnType(MethodParameter returnType) {
        return delegate.supportsReturnType(returnType);
    }

    @Override
    public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
        //returnValue是Controller请求方法执行完,返回值
        if(!(returnValue instanceof ResponseResult)){//返回值本身就是需要的类型,不进行处理
            ResponseResult json = new ResponseResult();
            json.setOk(true);
            json.setData(returnValue);
            returnValue = json;
        }

        delegate.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
    }
}

5.6后端对于用户登录、注销的响应

package org.example.controller;

import org.example.exception.AppException;
import org.example.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private User user;


    @PostMapping("/login")
    public Object login(@RequestBody User user, HttpServletRequest request){

        //模拟请求账号密码,在数据库查询对比
        if (!this.user.getUsername().equals(user.getUsername())){

            throw new AppException("账号不存在");
        }

        if (!this.user.getPassword().equals(user.getPassword())){

            throw new AppException("密码错误!");

        }

        HttpSession session = request.getSession();
        session.setAttribute("user",this.user);
        return null;

    }

    //注销功能
    @GetMapping("/logout")
    public Object logout(HttpSession session){

        session.removeAttribute("user");
        return null;

    }
}

5.7后端对于文章的新增、查看、修改、删除的响应

package org.example.controller;


import org.example.exception.AppException;
import org.example.model.Article;
import org.example.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.NumberFormat;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/article")
public class ArticleController {

    @Autowired
    private List<Article> articleList;


    @GetMapping("/init")
    public Object init(HttpServletRequest request){
        Map<String,Object> data = new HashMap<>();

        //获取用户信息
        HttpSession session = request.getSession(false);
        if (session != null) {
            User user = (User) session.getAttribute("user");
            if (user != null) {

                data.put("user",user);
            }
        }
        data.put("articleList",articleList);
        return data;//ok=true,data={user:{},articleList:[{}]

    }


    @GetMapping("/detail")
    public Object detail(Integer id){

        for (Article a:articleList){
            if(Integer.compare(a.getId(),id)==0){
                return a;
            }
        }

        throw new AppException("找不到该文章"+id);
    }

    @PostMapping("/add")
    public Object add(@RequestBody Article a){

        int max = 0;
        for (Article cur:articleList){
            if (cur.getId()>max){
                max = cur.getId();

            }

        }
        a.setId(max+1);
        articleList.add(a);
        return null;

    }

    @PostMapping("/update")
    public Object update(@RequestBody Article a){

        for (int i=0;i<articleList.size();i++){

            Article cur = articleList.get(i);

            if (Integer.compare(cur.getId(),a.getId())==0){
                articleList.set(i,a);
                return null;

            }
        }

       throw new AppException("修改失败,没有该文章"+a.getId());

    }


    @GetMapping("/delete")
    public Object delete(int id){

        for (int i=0;i<articleList.size();i++){

            Article cur = articleList.get(i);

            if (cur.getId()==id){

                articleList.remove(id);

                return null;
            }

        }

        throw new AppException("删除失败,没有该文章"+id);

    }

}

6、前端页面的实现
6.1首页

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>YYCN博客</title>

</head>
<body>


<div id="app">
    <h2>YYCN首页</h2>
       <!--    绑定变量 {{...}}-->
    <div v-if="user.nickname">欢迎你,{{user.nickname}} <a href="javascript:void(0)" @click="logout()">注销</a> <a href="personalArticle.html">个人博客管理</a> </div>
    <div v-else> <a href="login.html">登录</a>/<a href="register.html">注册</a></div>

    <ul>
        <li v-for="article in articles">
            <a href="javascript:void(0)" onclick="toDetail(article.id)">{{article.title}}</a>

        </li>

    </ul>

    <!--    以弹出框展示登录页面 展示和隐藏-->
<!--    <button @click="showLogin">登录</button>-->
<!--    <div v-if="showLogin">-->
<!--        用户名:<input type="text">-->


    </div>
    <!--    设计用户事件相关 在某个动作发生时,绑定事件函数   1、页面初始化事件 created:function(){  2、其他用户事件,比如按钮、链接/div元素/图片..点击-->
    <!--    标签上:v-on:click-"方法名" 简写@click="方法名"  定义方法 methods:{ 方法名 function(){  -->
    <!--    涉及后端的数据,需要前后端ajax (1)发送请求 (2)解析响应-->


<script type="application/x-javascript" src="vue.js"></script>
<script type="application/x-javascript" src="axios.js"></script>


<script>
    let app = new Vue({

        el: "#app",
        data: {

            user: {},

            articles: [],

        },
        methods: {

            toDetail: function () {

                localStorage.setItem('aid', id);
                window.location.href = "detail.html";

            },

            logout: function () {

                axios.get("api/user/logout")
                    .then(function (resp) {
                        let body = resp.data;

                        if (body.ok) {

                            app.user = {};

                        } else {
                            alert(body.message)
                        }

                    })
              }
            },

        //初始化方法,页面加载后就执行
        created: function () {
            //发送首页初始化ajax请求,获取用户登录及文章列表信息
            axios.get("api/article/init")
                .then(function (resp) {
                    // console.log(resp)
                    let body = resp.data;

                    if (body.ok) {

                        //如果||前的值等于空,就赋值为||后的值
                        app.user = body.data.user || {};
                        app.articles = body.data.articleList || [];


                    } else {

                        alert(body.message)

                    }
                })

        }


    })
</script>
</body>
</html>

前端页面比较多,这里就不一一上传了,大家可以看我的github账号:github账号
引入SpringBoot框架之后,后端代码少了很多,也少了很多配置,总之引用框架好处太多了,可以跨各种平台部署,灵活的依赖注入,通过POJO缓解了注射测试的数据。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring实现博客系统 的相关文章

  • xss-labs/level5

    输入 查看回显 如下所示 能够发现script被恶意替换为scr ipt 查看源代码 第一个输出点被转义了 所以没有利用价值了 第二个输出点如同刚才所言被进行了关键字的恶意替换操作 那没办法 我们只能继续尝试一下在标签内部构造一个新属性然后
  • opencv CvSolve函数深度解析

    Opencv CvSolve函数主要是用来求解线性系统Ax b的方程 X的解 solve函数跟它的算法是一样的 也是用来求解线性系统 设方程Ax b 根据有效的方程个数和未知数的个数 可以分为以下3种情况 1 rank A lt n 也就是
  • mysql故障切换 java_java.sql.SQLException: Value'0000-00-00'异常解决办法及mysql的url设置...

    一 0000 00 00错误及解决方案 在使用MySql 时 数据库中的字段类型是timestamp的 默认为0000 00 00 会发生异常 java sql SQLException Value 0000 00 00 can not b
  • 音频服务器运行失败怎么办,音频服务错误1068怎么解决 音频服务未运行win10解决方法...

    win10音频服务无法启动 提示错误1068 依赖服务或组无法启动是什么情况 怎么解决 在这里就跟着小编一起来了解一下吧 让大家解决电脑不能够出声的问题 音频服务未运行win10问题排除 一 电脑没了声音 小喇叭上有个红叉 鼠标放上去显 音
  • 【Python学习笔记2】Python网络爬虫的异常处理

    本文信息主要来源于韦玮老师的 精通python网络爬虫 仅作为个人学习笔记 通过python库函数urllib request去爬取网页时 遇到的异常主要时URL类和网页类的错误 python已提供URLError类和HTTPError类来
  • Ado.Net总结

    ADO NET总结 ADO NET 是在 NET 平台上访问数据库的组件 它是以 ODBC Open Database Connectivity 技术的方式来访问数据库的一种技术 ADO NET常用命名空间 命名空间 数据提供程序 Syst
  • 多输入多输出

    多输入多输出 MATLAB实现GRU门控循环单元多输入多输出 目录 多输入多输出 MATLAB实现GRU门控循环单元多输入多输出 预测效果 基本介绍 程序设计 往期精彩 参考资料 预测效果 基本介绍 MATLAB实现GRU门控循环单元多输入
  • spark SQL配置连接Hive Metastore 3.1.2

    Hive Metastore作为元数据管理中心 支持多种计算引擎的读取操作 例如Flink Presto Spark等 本文讲述通过spark SQL配置连接Hive Metastore 并以3 1 2版本为例 通过Spark连接Hive
  • HTML <progress> 标签

    实例 正在进行的下载
  • kali 破解压缩包密码

    一 提取加密压缩包的哈希值 zip2john 文件名 gt hash txt zip2john 文件名 能提取出文件的哈希值 然后我们通过重定向 将它写入一个文档中 二 利用工具对提取到的哈希值进行破解 john hash txt 然后就能
  • windows11安装微软商店里的ubuntu报错,已解决

    1 问题情况 安装微软商店的Ubuntu系统 安装完成后打开开始菜单的Ubuntu图标 初始化过程中卡住 点击界面下方的展开按钮有文字提示报错 报错提示内容为 Installing this may take a few minutes W
  • 京东抢购服务高并发实践

    声明 本位来自京东张开涛的微信公众号 kaitao 1234567 授权CSDN转载 如需转载请联系作者 作者 张子良 京东高级开发工程师 在京东负责抢购后端服务系统架构和开发工作 责编 钱曙光 关注架构和算法领域 寻求报道或者投稿请发邮件
  • eclipse与Mysql数据库是否连接的检验

    先去下载与Mysql数据库版本匹配的架包 然后导入到项目中 在这里我用的是Mysql8 0 Mysql8 0的驱动类名是 com mysql cj jdbc Driver 首先新建一个Demo类 然后进行数据库的连接即检验 代码如下 pac
  • Java架构直通车——基于数据库for update实现分布式锁

    文章目录 使用数据库解决超卖问题 非分布式 分为三步 原始方法 合并二 三步 使用update行锁使操作下沉到数据库 合并一 二 三步 使用方法锁 优化 使用块锁 使用数据库解决分布式超卖问题 主要原理 解决方案 解决库存超卖问题 可以另扣
  • 转帖:C++大师Lippman:我对中国程序员的忠告

    天极网特稿 记者 宋保强 C 语言的创立者 斯坦 利普曼 Stan Lippman 9月17日参加了在北京召开的微软技术大会Tech Ed2004并做了 The C Binding Integrating a Static and dyna
  • 嵌套循环基础练习题

    目录 java循环以及循环嵌套练习题 01 求10以内的偶数的和 02 求100以内的所有素数 素数 一个大于1的自然数 除了1和它本身外 不能被其他自然数整除 03 随机产生一个1 100之间的整数 看能几次猜中 要求 猜的次数不能超过7
  • CloudEvents 入门文档

    CloudEvents 入门文档 1 0 3 版本 文档来自 GitHub CloudEvents 摘要 这份非技术规范文档用来为你提供关于 CloudEvents 规范的总体概览 它补充了 CloudEvents 规范的相关背景以及在制定
  • midjourney最新使用方法教程指令关键词

    自ChatGPT走红以来 以 聊天 为核心的人工智能协作工具们受到了各行各业的关注 让AI写首诗 发封邮件 或是做一份计划书 这些工作已经成为AI聊天机器人的 日常需求 但似乎 人们遗忘了AI还具有创作文字以外的内容 比如 一幅画 2022

随机推荐

  • [完美解决]VS2012创建或打开C++浏览数据库文件时出现错误

    完美解决 VS2012创建或打开C 浏览数据库文件时出现错误 在使用VC2012的时候出现问题如下 创建或打开C 浏览数据库文件XXXXXXX stdf时发生错误 IntelliSense和浏览信息将不能用于C 项目 请确保已安装Micro
  • 全自动高清录播服务器,常态化高清录播服务器 高清全自动录播系统

    特点 支持高清视频会议终端1080P 720P下的录制 点播和直播 双流录制可到高两路1080P 60帧图像 支持把录制下来的会议或者培训内容直播给网内所有的客户端 PC和视频会议终端 支持IPhone IPAD 安卓系统等点播和直播 设计
  • BitLocker的解密

    BitLocker的解密 解密 以管理员身份运行命令提示符 然后在里面输入命令 C指的是盘符 这里以解密C为例 manage bde off C 弹出所有用法 manage bde 更多使用方法 可参考官网 https docs micro
  • win11打开应用被管理员阻止怎么办 window11管理员已阻止你运行此应用的解决方法

    大家在使用windows11系统时 是否有出现过电脑运行应用被阻止的情况呢 可能很多人的蒙着不知道如何处理这个问题 下面就和大家分享一下解决方法吧 更多Windows11安装教程 可以参考小白重装系统网 1 用鼠标右键单击开始图标 接着在出
  • TCP和UDP

    文章目录 TCP和UDP 什么是TCP 用JAVA实现一个基于TCP的简单网络通信 什么是UDP 用JAVA实现一个基于UDP的网络通信 TCP和UDP 什么是TCP TCP即传输控制协议 Transmission Control Prot
  • 【Unity学习笔记】Animation、Input类

    Animation Animation View 通过动画视图可以直接创建和修改动画片段 Animation Clips 显示动画视图 Window Animation 创建动画片段 为物体添加Animation组件 在动画视图中创建片段
  • Maven、JDK的安装以及环境配置

    Maven 项目管理工具 什么是Maven Maven是一个项目管理工具 它包含了一个对象模型 一组标准集合 一个依赖管理系统 和用来运行定义在生命周期阶段中插件目标和逻辑 核心功能 Maven的核心功能是合理叙述项目间的依赖关系 通俗点就
  • 端口转发工具 rinetd 的使用

    rinetd 可以将服务器的端口转发到另一个端口 1 安装rinetd 服务 vi etc yum repos d nux misc repo 输入以下内容报存 nux misc name Nux Misc baseurl http li
  • c++与c#的区别

    1 继承 C 支持多继承 C 类只能继承一个基类中的实现但可以实现多个接口 2 数组 声明 C 数组和声明 C 数组的语法不同 在 C 中 标记出现在数组类型的后面 3 数据类型 在C 中bool类可以与整型转换 但C 中bool 类型和其
  • 脚本ssh进入其他主机报错--bash: jps: command not found和Error: JAVA_HOME is not set and java could not be found

    文章目录 一 报错图例 二 报错原因 三 解决方案 三种 一 报错图例 二 报错原因 原因 在shell脚本写的ssh到其他节点的时候默认是不加载配置文件的 linux并不能去找到java中jps的命令和java的path路径等 三 解决方
  • 【java面试题】lock和synchronized有什么区别?

    学习目标 掌握 lock 与 synchronized 的区别 理解 ReentrantLock 的公平 非公平锁 理解 ReentrantLock 中的条件变量 lock 与 synchronized 的区别有三个层面 学习内容 1 不同
  • QT运行不出界面

    如果只出现如下一个黑色运行窗口 说明你环境配置的基本没啥问题 可以试试 项目 gt 构建设置中 gt General gt Shadow build 取消勾选 如下 如果第一种没有解决 看下构建出的release目录或者debug目录中 是
  • 自己实现图形验证码

    如果不想重复造轮子 参考上一篇文章 SpringBoot生成图形验证码 Muscleheng的博客 CSDN博客 这里不需要依赖开源组件包 完全自己实现图形验证码功能 两步完成 第一步 编写图形验证码工具 package com zhh d
  • 微信小程序 webiew缓存问题

    在微信小程序webview中嵌套H5页面 我们原本使用了localStorage用来标识用户信息的 但是后来发现在android手机上每一次杀掉小程序进程之后 localStorage的数据也会被清除 这样的话就和我们原本的意愿是相违背的
  • web 服务器安全维护,Web服务器安全攻击及防护机制详解

    Web安全分为两大类 Web服务器的安全性 Web服务器本身安全和软件配置 Web应用程序的安全性 在Web服务器上运行的Java ActiveX PHP ASP代码的安全 Web服务器面临的攻击 Web服务器攻击利用Web服务器软件和配置
  • 标定CCP协议在S32K144上的移植实战

    文章目录 目录 文章目录 前言 一 CCP是什么 二 移植步骤 1 准备工作 2 移植 3 测试验证 总结 前言 CCP协议在新能源汽车电子领域发挥着重要作用 CCP观测和标定作用对开发工程师起着重要作用 疫情宅在家无聊 把这块的知识重新梳
  • 4.3 配置Mysql与注册登录模块(下)

    目录 学习目标 学习内容 登录状态持久化 学习目标 前端页面授权 注册页面 登录状态的持久化 学习内容 实现前端页面的授权 import createRouter createWebHistory from vue router impor
  • LATEX以及宏包的下载和安装(附下载链接)

    LATEX以及宏包的下载和安装 附下载链接 TexStudio以及宏包下载和安装 LATEX以及宏包的下载和安装 附下载链接 1 环境下载 2 环境安装 2 1 MiKTeX安装 2 2 TexStudio的安装 3 配置 写作 1 环境下
  • 50个常见的 Java 错误及避免方法(第二部分)

    接上文50个常见的 Java 错误及避免方法 第一部分 17 Cannot Return a Value From Method Whose Result Type Is Void 当一个void方法尝试返回值时 就会发生此Java错误 例
  • Spring实现博客系统

    在上次用Servlet实现了博客系统之后 一直觉得代码写起来比较繁琐 而且耦合度很高 直到学习了Spring 我又看到了一线生机 运用SpringBoot重新改造了我的博客系统 接下来讲讲Spring是个什么东西 并把我的改造思路给大家分享