【开源项目--稻草】Day04

news2024/11/23 1:32:53

【开源项目--稻草】Day04

  • 1. 续 VUE
    • 1.1 完善VUE+AJAX完成注册功能
  • Spring验证框架
    • 什么是Spring验证框架
    • 使用Spring-Validation
  • 稻草问答-学生首页
    • 显示首页
    • 制作首页的流程
    • 开发标签列表
      • 标签列表显示原理
    • 从业务逻辑层开始
    • 编写控制层代码
    • 开发问题列表
      • 开发业务逻辑层
      • 开发页面和JS代码显示问题
  • 随笔

1. 续 VUE

1.1 完善VUE+AJAX完成注册功能

我们现在注册用户只能在浏览器控制台看到结果

怎么能再注册页面上看到注册结果呢?

实际上,register.html页面已经准备好了一个显示注册信息的div

改写它代码如下

<div id="error" class="alert alert-danger"
       style="display: none"
       v-bind:class="{'d-block':hasError}">
       <i class="fa fa-exclamation-triangle"></i>
       <span v-text="message">邀请码错误!</span>
</div>

其中v-bind:class="{‘d-block’:hasError}"的含义为

根据Vue代码中绑定的hasError变量来决定是否将class="d-block"加入到当前div中

如果将这个class加入得到当前div的样式中,则这个div会显示出来

页面修改后,register.js文件也要随之修改

代码如下

let app = new Vue({
    el:'#app',
    data:{
        inviteCode:'',
        phone:'',
        nickname:'',
        password:'',
        confirm:'',
        message:'',
        hasError:false
    },
    methods:{
        register:function () {
            console.log('Submit');
            let data = {
                inviteCode: this.inviteCode,
                phone: this.phone,
                nickname: this.nickname,
                password: this.password,
                confirm: this.confirm
            }
            console.log(data);
            if(data.password !== data.confirm){
                this.message="两次密码输入不一致";
                this.hasError=true;
                return;
            }
            $.ajax({
                url:"/register",
                method: "POST",
                data: data,
                success: function (r) {
                    console.log(r);
                    if(r.code == CREATED){
                        console.log("注册成功");
                        console.log(r.message);
                        //注册成功,可以直接跳转到登录页
                        location.href="/login.html?register";
                    }else{
                        console.log(r.message);
                        //如果注册失败将信息显示在信息Div中
                        app.message=r.message;
                        app.hasError=true;
                    }
                }
            });
        }
    }
});

新增两个属性:hasError和message

这两个属性控制页面上是否显示错误div以及错误div中出现的提示信息是什么

Spring验证框架

什么是Spring验证框架

Spring提供的对用户输入信息进行验证的框架组件

是服务器端验证技术

在这里插入图片描述

使用Spring验证框架验证发送到服务器的内容的合法性!

Spring-validation(验证)

使用Spring-Validation

步骤1:

导入依赖

子项目pom.xml文件添加:

<!-- 验证框架 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

步骤2:

定位到要验证信息的实体类

将验证规则按照给定注解来标记即可

要验证注册业务,就找RegisterVo类即可

@Data
public class RegisterVo implements Serializable {
    //只能作用在String上,不能为null,去掉空格之后也不能为""
    @NotBlank(message = "邀请码不能为空")
    private String inviteCode;
    @NotBlank(message = "用户名不能为空")
    //@Pattern()表示下面的属性需要通过指定正则表达式的判断
    @Pattern(regexp="^1\\d{10}$",message ="手机号格式不正确")
    private String phone;
    @NotBlank(message = "昵称不能为空")
    @Pattern(regexp="^.{2,20}$",message ="昵称在2到20位之间")
    private String nickname;
    @NotBlank(message = "密码不能为空")
    @Pattern(regexp="^\\w{6,20}$",message ="密码在6~20位之间")
    private String password;
    @NotBlank(message = "确认密码不能为空")
    private String confirm;

}

步骤3:

在控制器从表单或ajax获得实体类对象参数时就可以对这个实体类属性的值进行上面设置的验证了

验证方法非常简单,只需要加一个注解即可!

SystemController注册方法代码修改如下

@PostMapping("/register")
    public R registerStudent(
            //控制器接收的参数前加@Validated
            //表示要按这个类规定的验证规则,验证这个对象属性的值
            @Validated RegisterVo registerVo,
            //固定用法,在验证参数后再跟一个参数:BindingResult
            //这个参数中记录保存上面验证过程中的验证信息和结果
            BindingResult validaResult){
        //在控制器调用业务逻辑前,先判断BindingResult对象中是否有错误
        if(validaResult.hasErrors()){
            //如果验证结果中包含任何错误信息,进入这个if
            //获得其中的一个错误信息显示,一般是按顺序的第一个错误信息
            String error=validaResult.getFieldError()
                        .getDefaultMessage();
            return R.unproecsableEntity(error);
        }
        System.out.println(registerVo);
        log.debug("得到信息为:{}",registerVo);
        try{
            userService.registerStudent(registerVo);
            return R.created("注册成功!");
        }catch (ServiceException e){
            log.error("注册失败",e);
            return R.failed(e);
        }
    }

就可以测试验证的效果了

稻草问答-学生首页

显示首页

步骤1:

将static文件中的index.html复制到templates文件夹中

步骤2:

创建HomeController类,显示index.html

代码如下

@RestController
@Slf4j
public class HomeController {

    //显示首页
    @GetMapping("/index.html")
    public ModelAndView index(){
        return  new ModelAndView("index");
    }
}

步骤3:

撤销在SecurityConfig类中对index.html的放行

达到必须登录才能访问主页的效果

http.csrf().disable()
                .authorizeRequests()//对当前全部请求进行授权
                .antMatchers(
                        "/img/*",
                        "/js/*",
                        "/css/*",
                        "/bower_components/**",
                        "/login.html",
                        "/register.html",
                        "/register"
                )//设置路径
                .permitAll()//允许全部请求访问上面定义的路径
                //其它路径需要全部进行表单登录验证
                .anyRequest().authenticated().and()
                .formLogin()
                .loginPage("/login.html")
                .loginProcessingUrl("/login")
                .failureUrl("/login.html?error")
                .defaultSuccessUrl("/index.html")
                .and().logout()
                .logoutUrl("/logout")
                .logoutSuccessUrl("/login.html?logout");

制作首页的流程

1.制作首页导航栏的tag列表

2.制作学生问题的显示和分页

3.制作学生信息面板

开发标签列表

标签列表显示原理

在这里插入图片描述

在用户已经能够登录显示主页的前提下

  1. 主页页面中编写ajax向控制器发送请求所有标签
  2. 控制接到请求后调用业务逻辑层
  3. 业务逻辑层从tagMapper接口查询所有标签
  4. 业务逻辑层将查询到的信息返回给控制器
  5. 控制器获得所以标签返回JSON格式
  6. ajax中获得JSON对象,利用VUE绑定显示在页面上

从业务逻辑层开始

我们可以选择先编写业务逻辑层

步骤1:

ITagService接口中添加方法

public interface ITagService extends IService<Tag> {
    List<Tag> getTags();
}

步骤2:

实现这个接口

TagServiceImpl类中代码如下

@Service
public class TagServiceImpl extends ServiceImpl<TagMapper, Tag> implements ITagService {

    //CopyOnWriteArrayList<>是线程安全的集合,适合在高并发的环境下使用
    private final List<Tag> tags=new CopyOnWriteArrayList<>();

    @Override
    public List<Tag> getTags() {

        //这个if主要是为了保证tags被顺利赋值之后的高效运行
        if(tags.isEmpty()) {
            synchronized (tags) {
                //这个if主要是为了保证不会有两条以上线程为tags重复添加内容
                if (tags.isEmpty()) {
                    //super.list()是父类提供的查询当前指定实体类全部行的代码
                    tags.addAll(super.list());
                }
            }
        }
        return tags;
    }
}

步骤3:

测试

@SpringBootTest
public class TagTest {

    @Autowired
    ITagService tagService;
    @Test
    public void test() {
        List<Tag> list = tagService.getTags();
        for (Tag tag : list)
            System.out.println(tag);
    }

}

编写控制层代码

步骤1:

TagController类中编写代码如下

@RestController
//下面的注解表示想访问本控制器中的任何方法需要前缀/v1/tags
//这个v1开头的格式是后期微服务的标准名为RESTful
@RequestMapping("/v1/tags")
public class TagController {

    @Autowired
    private ITagService tagService;

    //查询所有标签@GetMapping("")表示使用类上声明的前缀就可以访问这个方法
    @GetMapping("")
    public R<List<Tag>> tags(){
        List<Tag> list=tagService.getTags();
        return R.ok(list);
    }
}

步骤2:

到页面中(index.html)绑定vue需要的变量

页面代码如下

	<div class="nav font-weight-light" id="tagsApp">
    <a href="tag/tag_question.html" class="nav-item nav-link text-info">	<small>全部</small></a>
    <!-- v-for 循环中in左侧是随意起的变量名,会在循环体中使用
            in右侧的变量名,绑定这VUE代码中的变量-->
    <a href="tag/tag_question.html"
       class="nav-item nav-link text-info"
       v-for="tag in tags">
       <small v-text="tag.name">Java基础</small>
    </a>
  </div>

步骤3:

index.html网页的结束位置要引入两个js文件

</body>
<script src="js/utils.js"></script>
<script src="js/index.js"></script>
<script src="js/tags_nav.js"></script>
</html>

步骤4:

编写js/tags_nav.js代码如下

let tagsApp = new Vue({
    el:'#tagsApp',
    data:{
        tags:[]
    },
    methods:{
        loadTags:function () {
            console.log('执行了 loadTags');
            $.ajax({
                url:'/v1/tags',
                method:'GET',
                success:function (r) {
                    console.log(r);
                    if (r.code === OK){
                        console.log('成功获取tags');
                        //将从控制器获得的所有标签赋值给vue定义的
                        //tags数组,由于双向绑定,赋值同时页面就开始循环了
                        tagsApp.tags = r.data;
                    }
                }
            });
        }
    },
    //这个方法会在页面加载完毕之后运行
    created:function () {
        //页面加载完毕,立即调用loadTags
        this.loadTags();
    }
});

开发问题列表

了解开发流程

在这里插入图片描述

开发业务逻辑层

步骤1:

在业务逻辑层的接口中声明方法

IQuestionService接口给中声明方法

public interface IQuestionService extends IService<Question> {

    //按登录用户查询当前用户问题的方法
    List<Question> getMyQuestions();
}

步骤2:

要想实现查询当前登录的用户信息,必须使用Spring-Security提供的指定方法

调用这个方法的代码可能在项目后面的业务中也需要

这样写字QuestionService中就不合适了,所以我们先在IUserService中添加一个获得当前登录用户名的方法

IUserService添加代码

 //从Spring-Security中获得当前登录用户的用户名的方法
    String currentUsername();

步骤3:

在UserServiceImpl类中实现获得当前登录用户名并返回

@Override
    public String currentUsername() {
        //利用Spring-Security框架获得当前登录用户信息
        Authentication authentication=
                SecurityContextHolder.getContext()
                        .getAuthentication();
        //判断当前用户有没有登录,如果没有登录抛出异常
        if(!(authentication instanceof AnonymousAuthenticationToken)){
            //上面代码是判断当前用的抽象权限类型是不是匿名用户
            //如果不是匿名用户,就是登录的用户,只有登录的用户才能返回用户名
            String username=authentication.getName();
            return username;
        }
        //没运行上面的if证明用户没有登录,抛出异常即可
        throw ServiceException.notFound("没有登录");

    }

步骤4:

现在就可以在QuestionServiceImpl类中调用上面编写的方法来获得当前登录用户了

在根据这个用户信息(id)查询这个用户的问题

代码如下

@Service
@Slf4j
public class QuestionServiceImpl extends ServiceImpl<QuestionMapper, Question> implements IQuestionService {
    @Autowired
    IUserService userService;
    @Autowired
    UserMapper userMapper;
    @Autowired
    QuestionMapper questionMapper;
    //按登录用户查询当前用户问题的方法
    @Override
    public List<Question> getMyQuestions() {
        //获得当前登录用户的用户名
        String username=userService.currentUsername();
        log.debug("当前登录用户为:{}",username);
        //如果已经登录,使用之前编写好的findUserByUsername方法
        //查询出当前用户的详细信息(实际上主要需要用户的id)
        User user=userMapper.findUserByUsername(username);
        if(user == null){
            throw ServiceException.gone("登录用户不存在");
        }
        log.debug("开始查询{}用户的问题",user.getId());
        QueryWrapper<Question> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("user_id",user.getId());
        queryWrapper.eq("delete_status",0);
        queryWrapper.orderByDesc("createtime");
        List<Question> list=questionMapper.selectList(queryWrapper);
        log.debug("当前用户的问题数量为:{}",list.size());

        return list;
    }
}

步骤5:

编写完QuestionServiceImpl类中的代码

就可以在控制器中调用了,

控制器调用无需任何参数直接调用即可

第一次打开QuestionController类编写代码如下

@RestController
@RequestMapping("/v1/questions")
@Slf4j
public class QuestionController {
    @Autowired
    IQuestionService questionService;

    //查询返回当前登录用户发布的问题
    @GetMapping("/my")
    public R<List<Question>> my(){
        log.debug("开始查询当前用户的问题");
        //这里要处理个异常,因为用户可能没有登录
        try{
            List<Question> questions=
                    questionService.getMyQuestions();
            return R.ok(questions);
        }catch (ServiceException e){
            log.error("用户查询问题失败!",e);
            return R.failed(e);
        }
    }
}

编写到这里,我们就可以向浏览器编写路径

http://localhost:8080/v1/questions/my来看到控制返回的JSON格式信息

开发页面和JS代码显示问题

步骤1:

先在index.html页面中编写VUE代码准备绑定JSON格式信息

<div class="container-fluid" id="questionsApp">
          <h4 class="border-bottom m-2 p-2 font-weight-light"><i class="fa fa-comments-o" aria-hidden="true"></i> 我的问答</h4>
          <div class="row" style="display: none">
            <div class="alert alert-warning w-100" role="alert">
              抱歉您还没有提问内容, <a href="question/create.html" class="alert-link">您可以点击此处提问</a>,或者点击标签查看其它问答
            </div>
          </div>
          <div class="media bg-white m-2 p-3" v-for="question in questions" >
            <div class="media-body w-50">
              <div class="row">
                <div class="col-md-12 col-lg-2">
                  <span class="badge badge-pill badge-warning" style="display: none">未回复</span>
                  <span class="badge badge-pill badge-info" style="display: none">已回复</span>
                  <span class="badge badge-pill badge-success">已解决</span>
                </div>
                <div class="col-md-12 col-lg-10">
                  <h5 class="mt-0 mb-1 text-truncate">
                    <a class="text-dark" href="question/detail.html"
                      v-text="question.title">
                      eclipse 如何导入项目?
                    </a>
                  </h5>
                </div>
              </div>

              <div class="font-weight-light text-truncate text-wrap text-justify mb-2" style="height: 70px;">
                <p v-html="question.content">
                  eclipse 如何导入项目?
                </p>
              </div>
              <div class="row">
                <div class="col-12 mt-1 text-info">
                  <i class="fa fa-tags" aria-hidden="true"></i>
                  <a class="text-info badge badge-pill bg-light" href="tag/tag_question.html"><small >Java基础 &nbsp;</small></a>
                </div>
              </div>
              <div class="row">
                <div class="col-12 text-right">
                  <div class="list-inline mb-1 ">
                    <small class="list-inline-item"
                           v-text="question.nickname">风继续吹</small>
                    <small class="list-inline-item">
                            <span v-text="question.pageViews">12</span>浏览</small>
                    <small class="list-inline-item" >13分钟前</small>
                  </div>
                </div>
              </div>

            </div>
            <!-- / class="media-body"-->
            <img src="img/tags/example0.jpg"  class="ml-3 border img-fluid rounded" alt="" width="208" height="116">
          </div>
          <div class="row mt-2">
            <div class="col-6 offset-3">
              <nav aria-label="Page navigation example">
                <div class="pagination">
                  <a class="page-item page-link" href="#" >上一页</a>
                  <a class="page-item page-link " href="#" >1</a>
                  <a class="page-item page-link" href="#" >下一页</a>
                </div>
              </nav>
            </div>

          </div>
        </div>

步骤2:

js/index.js文件修改为

/*
显示当前用户的问题
 */
let questionsApp = new Vue({
    el:'#questionsApp',
    data: {
        questions:[]
    },
    methods: {
        loadQuestions:function () {
            $.ajax({
                url: '/v1/questions/my',
                method: "GET",
                success: function (r) {
                    console.log("成功加载数据");
                    console.log(r);
                    if(r.code === OK){
                        questionsApp.questions = r.data;
                    }
                }
            });
        }
    },
    created:function () {
        console.log("执行了方法");
        this.loadQuestions(1);
    }
});

随笔

内存操作是纳秒级别

硬盘操作是毫秒级别

1毫秒=1000微妙

1微秒=1000纳秒

内存和硬盘操作差着百万倍级别

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/841072.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue系列第八篇:echarts绘制柱状图和折线图

本篇将使用echarts框架进行柱状图和折线图绘制。 目录 1.绘制效果 2.安装echarts 3.前端代码 4.后端代码 1.绘制效果 2.安装echarts // 安装echarts版本4 npm i -D echarts4 3.前端代码 src/api/api.js //业务服务调用接口封装import service from ../service.js //npm …

Go Windows下开发环境配置(图文)

Go Windows下开发环境配置 下载 安装 点击下载的安装包进行安装。安装路径可以选择到自己的目录。 环境变量配置 GOROOT&#xff1a;&#xff08;指定到安装目录下&#xff09; GOPATH&#xff1a;&#xff08;是工作空间&#xff09; path&#xff1a;在安装时已经添加了…

XML基础知识讲解

文章目录 1. xml简介2. xml快速入门3. xml的元素(标签)定义4. xml标签的命名规范5. xml的属性定义和注释6. 转义字符7. CDATA区8. xml的处理指令9. xml的约束 1. xml简介 XML&#xff08;eXtensible Markup Language&#xff09;是一种用于描述数据的标记语。 它以纯文本的方…

并查集练习 — 岛屿问题(解法二)

题目如岛屿问题解法一文章所介绍&#xff0c;这里不过多赘述&#xff0c;直接讲解第二种解法。 并查集解法 并查集解法的整体思路是&#xff0c;将二维数组中为‘1’的部分提取出来作为样本&#xff0c;再进行判断&#xff0c;如果左上方向有同样为‘1’的&#xff0c;则进行…

架构训练营学习笔记:6-1 微服务

序 这部分是了解的。传统企业使用soa较多。很多企业银行、电信对于Oracle 依赖大&#xff0c;强调稳定性。各个项目侧重外包&#xff0c;技术栈不统一。 soa 历史 这个之前电信的BOSS系统就是这种架构&#xff0c;不知道现在呢&#xff0c;核心计费系统billing是运行在tuxduo…

整理mongodb文档:collation

文章连接 整理mongodb文档:collation 看前提示 对于mongodb的collation。个人主要用的范围是在createcollection&#xff0c;以及find的时候用&#xff0c;所以本片介绍的时候也是这两个地方入手&#xff0c;对新手个人觉得理解概念就好。不要求强制性掌握&#xff0c;但是要…

jmeter工具测试和压测websocket协议【杭州多测师_王sir】

一、安装JDK配置好环境变量&#xff0c;安装好jmeter 二、下载WebSocketSampler发送请求用的&#xff0c;地址&#xff1a;https://bitbucket.org/pjtr/jmeter-websocket-samplers/downloads/?spma2c4g.11186623.2.15.363f211bH03KeI 下载解压后的jar包放到D:\JMeter\apache-j…

MyCat配置rule.xml、server.xml讲解

1. rule.xml分片规则配置文件 rule.xml中配置的主要就是拆分表的规则&#xff0c;rule.xml中主要包含两类标签 tableRule 和Function。 tableRule标签里面主要配置我们的分片规则&#xff0c;Function里面涉及的是分片规则里面所涉及的java类&#xff0c;都是在function中配置…

python中的装饰器的真正含义和用法

闭包&#xff1a; 闭包是python中的一个很实用的写法&#xff0c;可以使得用户在函数中调用该函数外的函数的变量&#xff0c;使得该变量常驻于内存中。 闭包函数&#xff1a; 输入是函数&#xff0c;输出也是一个函数。 装饰器的写法是python闭包的语法糖。 面试中经常面…

[C++] KY79 浮点数加法 北京大学复试上机题

题目链接 KY79 浮点数加法https://www.nowcoder.com/questionTerminal/ddec753f446e4ba4944e35378ba635c8 描述 求2个浮点数相加的和 题目中输入输出中出现浮点数都有如下的形式&#xff1a; P1P2...Pi.Q1Q2...Qj 对于整数部分&#xff0c;P1P2...Pi是一个非负整数 对于小数…

【前端】html

HTML标签&#xff08;上&#xff09; 目标&#xff1a; -能够说出标签的书写注意规范 -能够写出HTML骨架标签 -能够写出超链接标签 -能够写出图片标签并说出alt和title的区别 -能够说出相对路径的三种形式 目录&#xff1a; HTML语法规范HTML基本结构标签开发工具HTML常用标…

C语言案例 99乘法口诀-04

难度2复杂度2 题目&#xff1a;打印99乘法口诀 步骤一&#xff1a;定义程序目标 编写一个C程序&#xff0c;打印99乘法口诀。 步骤二&#xff1a;程序设计 整个程序分别为两个部分&#xff0c;第一部分是使用for循环打印的行数&#xff0c;第二部分是使用for循环控制打印的列…

基于Azure OpenAI Service 的知识库搭建实验⼿册

1.概要 介绍如何使⽤Azure OpenAI Service 的嵌⼊技术&#xff0c;创建知识库&#xff1b;以及创建必要的资源组和资源&#xff0c;包括 Form Recognizer 资源和 Azure 翻译器资源。在创建问答机器⼈服务时&#xff0c;需要使⽤已部署模型的 Azure OpenAI 资源、已存在的…

一键翻译,实现文件名简体中文转日语的便捷改名!

您是否曾经遇到过想要将文件名从简体中文翻译成日语&#xff0c;却苦于没有合适的工具&#xff1f;现在&#xff0c;让我们为您介绍一款便捷的解决方案——文件名简体中文转日语翻译工具&#xff01; 首先&#xff0c;第一步&#xff0c;我们需要打开文件批量改名&#xff0c;…

无涯教程-Perl - binmode函数

描述 此函数设置在区分两者的操作系统上以二进制形式读取和写入FILEHANDLE的格式。非二进制文件的CR LF序列在输入时转换为LF,在LF时在输出时转换为CR LF。这对于使用两个字符分隔文本文件中的行的操作系统(MS-DOS)至关重要,但对使用单个字符的操作系统(Unix,Mac OS,QNX)没有影…

付款方式谈得好,订单跑不了

在与客户商讨付款方式时出现分歧&#xff0c;其实是非常常见的情况。 在这种情况下&#xff0c;我们需要紧握谈判的节奏&#xff0c;不可忽视任何细节&#xff0c;更不能让自己陷入混乱之中。 先看一个案例~ 客户发来邮件&#xff1a; Dear... Please find our attached f…

远程访问桌面软件 OpenText Exceed TurboX(ETX)如何提高企业生产力

远程访问桌面软件 OpenText Exceed TurboX&#xff08;ETX&#xff09;如何提高企业生产力 几乎所有规模和行业的企业&#xff0c;员工的工作方式、时间和地点方面发生重大变化&#xff0c;这主要得益于新技术和全球商业与协作。业务领导者正在推动其 IT 部门提出解决方案&…

使用yarn启动项目报错

使用yarn启动项目报错 解决方法&#xff1a; 1.点击“开始”菜单搜索找到 Windows PowerShell ISE并以管理员身份运行(注&#xff1a;不是以管理员的身份直接运行cmd) 2. 输入 set-ExecutionPolicy RemoteSigned 回车 3.输入&#xff08;选择全是&#xff09; 4.再输入get-Exe…

【Linux】五、进程

一、冯诺依曼体系结构 存储器&#xff1a;指的是内存&#xff1b; 输入设备&#xff1a;键盘、摄像头、话筒&#xff0c;磁盘&#xff0c;网卡&#xff1b; 输出设备&#xff1a;显示器、音响、磁盘、网卡&#xff1b; 中央处理器&#xff08;CPU&#xff09;&#xff1a;运算器…

【架构】Java 系统架构演进的思考

文章目录 1 前言2 单体应用架构3 垂直应用架构4 分布式架构5 SOA 架构6 微服务云架构7 总结 1 前言 随着移动互联的发展&#xff0c;网站、H5、移动端的应用规模也不断扩大&#xff0c;不管是应用的数量还是质量都得到了指数级的提升。开发者的数量与日俱增&#xff0c;应用的…