朝小闇的博客

海上月是天上月,眼前人是心上人

Spring实战第五版英文版及源码资源链接:https://pan.baidu.com/s/18N8tt62cE5H8yXCRh95Jcw 提取码:ko2n

1.注解原理探索及使用

@Repository、@Controller、@Service、@Component 四个包级注解,都实现了@Bean注解,即可以将标注类交托给springbean作为组件处理,除此之外:

  • @Repository:
    • 数据访问层,一般是mapper或者dao层,将标注类中抛出的数据访问异常封装为Spring数据访问异常;
  • @Controller:
    • 控制层,一般是controller层,标注控制器,实现action,能够填充可选的数据模型model并将请求传递给一个视图view;
  • @Service:
    • 服务层(业务逻辑层),一般是service或者manager层,可以理解为对一个或多个DAO的再次封装;
  • @Component:
    • 泛指各种组件,组件不属于以上三种时使用该注解;

(层次结构):

  • pojo:实体层,实体类;
  • repository/mapper/dao:数据访问层,接口类;
  • manager/service(serviceImpl):服务层,接口类和实现类,一般可直接省略接口直接实现;
  • controller:控制层,实现路由跳转等基本控制;
  • config:配置层;
阅读全文 »

第三章.分布式程序设计语言

1.分布式程序设计语言概述

1.1 分布式应用程序的分类

在分布式计算系统中,对应用程序进行程序设计的层面有四:减少单个计算的周转时间、增加可靠性和可用性、使系统某些部分提供特殊功能、固有的分布式应用。

分布式应用程序分类:

  • 并行、高性能应用程序:

    • 粒度是在通信之间的计算时间的长短,并行应用程序可按粒度划分:
      • 大粒度并行应用程序用大部分时间进行计算,而不经常通信;
      • 细粒度并行应用程序经常通信,适合紧密耦合分布计算系统;
      • 松散耦合分布计算系统通信开销非常大,只适合大粒度并行计算,但大粒度并行计算也可适用紧密耦合分布计算系统;
  • 容错应用程序:

    • 分布计算系统具有允许部分失效的特性,一个处理机的故障不影响其它处理机的正常工作,即可靠性高;
    • 除此之外,程序和数据还可在若干处理机上复制,由此进一步增加可靠性;
    • 抵御自然灾害,需要使用处理机在地域上松散耦合;
  • 具有专用功能的应用程序:

    • 每个服务可以使用一个或多个专用处理机,用户通过网络请求这些服务;
    • 易于增加新功能或改进现有功能,通过增加新的处理机即可实现;
  • 固有的分布式应用程序:

    • 有些应用程序本身就是分布的,这种应用程序必须在分布式硬件上运行,如电子邮件;

1.2 分布式程序设计和顺序程序设计的区别

在分布计算系统上实现这些应用程序的活动叫做分布式程序设计。

分布式程序设计和顺序程序设计的三个区别:

  • 使用多个处理机:
    • 系统具有把一个程序的不同部分分配到不同处理机上执行的能力;
  • 处理机合作:
    • 各个进程必须能相互通信和同步;
  • 处理部分失效:
    • 能对系统的部分失效进行检测并恢复;

1.3 分布式程序设计语言的分类

  1. 按并行模式来分:
    • 顺序进程并行语言:
      • 基本模型:一组顺序进程,并行运行,并能通过报文传递进行通信;
      • 语言:C、C++、FORTRUN、SR、Ada、CSP……
    • 具有内在并行性的语言:
      • 函数式语言:无副作用,允许以任意次序(包括并行)计算表达式;
      • 逻辑语言;
      • 面向对象语言;
      • 这些模型中并行的粒度比基本的通信顺序进程模型中小很多;
  2. 按通信模型来分;
  3. 容错模型和技术:
    • 处理机故障:提供故障检测机制;
    • 故障处理模型:
      • 理想情况,系统对程序员隐匿全部处理机故障;
      • 系统给程序员提供高层机制,使程序员能够描述哪些进程和数据是重要的,以及发生崩溃后怎样恢复;
    • 实现可靠性:
      • 程序设计容错:
        • 向前恢复:试图确定错误所在,并在此基础上改正包含错误的系统状态,高级语言中的异常处理机制提供了此系统结构;
        • 向后恢复:通过把系统恢复到错误发生前的状态来改正系统状态,恢复阻塞方案提供了这种系统结构;
      • 通信容错:
        • 通信容错依赖于使用的通信方式及故障类型;
阅读全文 »

ARM汇编语言官方手册:链接:https://pan.baidu.com/s/1k-drPZBD41hSIXzzk4JA2Q 提取码:vjyf

1.计算机组成

  1. 嵌入式系统:以应用为中心,以计算机技术为基础,软硬件可裁剪,适应应用系统对功能、可靠性、成本、体积、功耗等严格要求的专用计算机系统。

  2. 计算机系统:

    1. 冯.诺伊曼结构(普林斯顿结构):计算机按照程序顺序执行程序(指令),程序指令存储地址和数据存储地址指向同一个存储器的不同物理位置;

      组成:

      • CPU(中央处理单元) = 算术逻辑单元(运算器) + 控制电路
      • 存储器 Memory
        • ROM: Read Only Memory 只读存储器
        • RAM: Random Access Memory 随机访问存储器 “R/W”
      • 输入输出设备
    2. 哈佛架构(Harvard Architecture):是一种将程序存储和数据存储分开的存储器结构,数据存储器与程序存储器采用不同的总线。

  3. 各组件通信方式:

    1. 全双工:同一时刻一方即可以发送数据给对方,又可以从对方接收数据;
    2. 半双工:同一时刻一方只能发送数据给对方,或者是从对方接收数据;
    3. 单工:任意时刻 一方只能发送数据给对方,或者是从对方接收数据;
    • 总线bus:计算机系统内部各组件之间是通过“总线”的来通信的;
    • 总线特点:
      • 广播式:多个部件可以同时从总线上接收相同的信息;
      • 系统瓶颈:任意时刻只能有一个设备向总线发送信息;
    • 总线按功能分:
      • 数据总线(DB): 双向,宽度差别8bits/16bits/32bits
      • 地址总线(AB): 单向,CPU发地址,宽度与寻址空间有关 24bit==>16MB
      • 控制总线(CB): 命令和状态
    • 总线按位置分:
      • 片内总线
      • 系统总线
      • 通信总线(I/O总线)
阅读全文 »

1.初始化导入资源

  • 新建项目并配置SpringWeb、Thymeleaf和SpringSecurity依赖(注:只要配置了SpringSecurity依赖后续资源在访问时就会自动被拦截并跳转到登录页,即使并没有配置登录账号);

  • 导入素材,资源链接:https://pan.baidu.com/s/1CsbZrhFKggnucYPHFVaHSw 提取码:v7g7

  • 新建Controller目录,下建RouterController.java路由控制器,实现简单路由即可:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    @Controller
    public class RouterController {
    @RequestMapping({"/","/index"})
    public String index(){
    return "index";
    }
    @RequestMapping("/toLogin")
    public String toLogin(){
    return "views/login";
    }
    @RequestMapping("/level1/{id}")
    public String level1(@PathVariable("id")Integer id){
    return "views/level1/"+id;
    }
    @RequestMapping("/level2/{id}")
    public String level2(@PathVariable("id")Integer id){
    return "views/level2/"+id;
    }
    @RequestMapping("/level3/{id}")
    public String level3(@PathVariable("id")Integer id){
    return "views/level3/"+id;
    }
    }
阅读全文 »

本节讲解数据库连接以及mybatis使用

1.数据库连接及原生用法

  1. 新建项目,配置依赖:

    • Web->Spring Web;
    • SQL->JDBC API;
    • SQL->Spring Data JDBC;
    • SQL->MySQL Driver;
  2. IDEA连接数据库(可选,可以使用其它软件直接打开mysql显示):

    如图,我已连接自己的mysql中springboot_mybatis数据库,其中已配置简单表user:

    image-20210309160519767
  3. 新建application.yml文件(可以使用默认的application.properties),并对该项目连接mysql数据库:

    1
    2
    3
    4
    5
    6
    7
    spring:
    datasource:
    username: root
    password: password
    # serverTimezone=UTC是时区,
    url: jdbc:mysql://localhost:3306/springboot_mybatis?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
    driver-class-name: com.mysql.cj.jdbc.Driver
  4. 新建controller包,并在其下新建JDBCController.java文件,代码如下(运行后已可正常访问并简易增删查改数据库):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    package com.kun.demodata.controller;

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.jdbc.core.JdbcTemplate;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RestController;

    import java.util.List;
    import java.util.Map;

    @RestController
    public class JDBCController {
    // Template是Spring默认配置好的模板bean,可以拿来即用
    @Autowired
    JdbcTemplate jdbcTemplate;
    // 查询数据库所有信息,没有实体类时使用Map获取数据库中的数据
    @GetMapping("/userList")
    public List<Map<String,Object>> userList(){
    String sql = "select * from user";
    List<Map<String,Object>> mapList = jdbcTemplate.queryForList(sql);
    return mapList;
    }
    // 增加用户信息
    @GetMapping("/addUser")
    public String addUser(){
    String sql = "insert into springboot_mybatis.user(id,name,pwd) values(4,'小芳','ffffff')";
    jdbcTemplate.update(sql);
    return "addUser-ok";
    }
    // 修改用户信息
    @GetMapping("/updateUser/{id}")
    public String updateUser(@PathVariable("id") int id){
    // 占位符语法格式
    String sql = "update springboot_mybatis.user set name=?,pwd=? where id="+id;
    // 封装
    Object[] objects = new Object[2];
    objects[0] = "小黄";
    objects[1] = "password";
    // 直接传参
    jdbcTemplate.update(sql,objects);
    return "updateUser-ok";
    }
    // 删除用户信息
    @GetMapping("/deleteUser/{id}")
    public String deleteUser(@PathVariable("id") int id){
    String sql = "delete from springboot_mybatis.user where id=?";
    // 直接传参
    jdbcTemplate.update(sql,id);
    return "deleteUser-ok";
    }
    }
阅读全文 »

本节以一个员工管理系统的实例在前两节的基础上继续讲解一些功能。

1.初始化

  • 依然是上一个项目,但这次我们引入一个员工管理系统的模板,将页面和静态资源分别导入到项目中,并使用Thymeleaf模板解析器(模板资源链接:https://pan.baidu.com/s/15L8ByzIqhKzaCMo2Re_F3g 提取码:8lbu ):

    image-20210306102122875
    • 按照上一节在每一个页面引入Thymeleaf,并修改源html标签属性为Thymeleaf,以index.html文件为例(修改完成之后页面中就可显示样式了):

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      <!DOCTYPE html>
      <html lang="en" xmlns:th="http://www.thymeleaf.org">
      <head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
      <meta name="description" content="">
      <meta name="author" content="">
      <title>Signin Template for Bootstrap</title>
      <!-- Bootstrap core CSS -->
      <!-- /表示静态资源根目录 -->
      <link th:href="@{/css/bootstrap.min.css}" rel="stylesheet">
      <!-- Custom styles for this template -->
      <link th:href="@{/css/signin.css}" rel="stylesheet">
      </head>

      <body class="text-center">
      <form class="form-signin" action="dashboard.html">
      <img class="mb-4" th:src="@{/img/bootstrap-solid.svg}" alt="" width="72" height="72">
      <h1 class="h3 mb-3 font-weight-normal">Please sign in</h1>
      <label class="sr-only">Username</label>
      <input type="text" class="form-control" placeholder="Username" required="" autofocus="">
      <label class="sr-only">Password</label>
      <input type="password" class="form-control" placeholder="Password" required="">
      <div class="checkbox mb-3">
      <label>
      <input type="checkbox" value="remember-me"> Remember me
      </label>
      </div>
      <button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
      <p class="mt-5 mb-3 text-muted">© 2017-2018</p>
      <a class="btn btn-sm">中文</a>
      <a class="btn btn-sm">English</a>
      </form>

      </body>
      </html>
    image-20210306102901100
  • MyMvcConfig文件中重写addViewControllers方法,也就是实现路由跳转功能(注:此功能不实现国际化跳转就会失败):

    1
    2
    3
    4
    5
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
    registry.addViewController("/").setViewName("index");
    registry.addViewController("/index.html").setViewName("index");
    }
阅读全文 »

SpringBoot配置了什么?能不能对其进行修改?能修改什么?能不能扩展?通过自动装配原理的学习,接下来主要根据自动装配源码分析并得到以下结论。

1.导入静态资源

  • 这里的静态资源由果索因,即在网页中localhost:8080/后输入webjars路径相当于访问源文件路径,以此找到源文件中存放静态资源位置,注:静态资源包含html等文件;

  • 找到WebMvcAutoConfiguration文件以下部分:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// 这一段是判断是否在配置文件中自主配置资源路径,如果配置则默认配置失效,直接在此返回
if (!this.resourceProperties.isAddMappings()) {
logger.debug("Default resource handling disabled");
return;
}

Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();

// webjars是以jar包形式封装引入前端资源,此处可以从官网取出引入静态资源依赖的代码
if (!registry.hasMappingForPattern("/webjars/**")) {
customizeResourceHandlerRegistration(registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/")
.setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
}

String staticPathPattern = this.mvcProperties.getStaticPathPattern();
/* 首先从mvcProperties对象的类WebMvcProperties文件中找到staticPathPattern变量
其次从resourceProperties对象的类ResourceProperties文件中找到staticLocations变量
*/
if (!registry.hasMappingForPattern(staticPathPattern)) {
customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern) .addResourceLocations(getResourceLocations(this.resourceProperties.getStaticLocations())) .setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
}
}
  • webjars引入 Maven jquery为例:

    image-20210305125609037
    • 将该段依赖代码放到pom.xml文件依赖中并加载相关依赖项,如图:

      image-20210305130316069

      这一段的含义是localhost:8080/webjars/路径相当于外部依赖库目录的classpath:/META-INF/resources/webjars/,因此在网页中输入localhost:8080/webjars/jquery/3.6.0/jquery.js即可获取到该静态资源,如图所示:

      image-20210305130913244
  • ResourceProperties文件静态资源默认路径:

    image-20210305131847108
    • 此处四个路径全部是根目录下resources文件下目录,而系统默认生成static文件夹用以存放静态资源。经过实践发现后三者优先级:/resources > /static > /public,而第一个路径其实就是外部依赖包路径,参考webjars
    • WebMvcProperties文件下staticPathPattern变量的默认地址就是根路径,即根路径下的资源也能直接访问到;
  • 关于在application.properties文件中修改资源路径,一般不使用,修改的话直接修改staticPathPattern变量即可,这样一来默认存放静态资源的路径就会全部失效;

阅读全文 »

第二章.进程通信

  • 进程通信的两种方式:
    • 同一物理节点上不同进程:管道、共享内存和消息队列等实现;
    • 不同物理节点上不同进程:通信网络实现;

1 同一节点上进程间通信

1.1 管道

单向通信信道,使用write系统调用发送数据,使用read系统调用接收数据。

  • 无名管道:

    • 简称管道,只在父子进程或同父子进程间使用,并与创建该管道的进程同时存在;

    • 管道实质是允许双向通信的,但被强制用作单向通信信道。为了避免两个进程同时自由读写管道,因此习惯上每个进程只读或只写,并且关闭本进程不需要的文件描述符;

    • 通过pipe系统调用创建管道,成功时返回两个文件描述符,一个向管道写入,一个向管道读出:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      /*1.定义*/
      #include <unistd.h>
      // 如果调用成功,filedes[0]用来从管道读出数据,filedes[1]用来向管道写入数据
      int pipe(int filedes[2]);

      /*2.实例*/
      #include <unistd.h>
      #include <stdio.h>
      #define MSGSIZE 16
      char *msg1 = "hello, book # 1 ";
      char *msg2 = "hello, book # 2 ";
      char *msg3 = "hello, book # 3 ";
      main(){
      char inbuf[MSGSIZE];
      int p[2],j;
      // 创建一个管道
      if(pipe(p) == -1){
      perror("pipe call failed");
      exit(1);
      }
      // 通过fork调用生成的子进程会共享父进程的文件描述符p,父进程创建一个管道后,则可以实现父子进程通信
      switch(pid == fork()){
      case -1:
      perror("fork call failed");
      exit(2);
      case 0:
      // 如果是child进程则写入管道
      write(p[1],msg1,MSGSIZE);
      write(p[1],msg2,MSGSIZE);
      write(p[1],msg3,MSGSIZE);
      default:
      // 如果是parent进程则从管道读出
      for(j=0;j<3;j++){
      read(p[0],inbuf,MSGSIZE);
      printf("%s\n",inbuf);
      }
      wait(NULL);
      exit(0);
      }
      }
  • FIFO或命名管道:

    • FIFO在读写时具有和管道相同的属性,甚至在内核级FIFO和管道共享大量的公共代码,但是FIFO是一个持久的设备(文件),被赋予了一个UNIX文件名,有自己的所有者、大小以及访问权限;

    • 初始化部分与管道不同:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      #include <sys/types.h>
      #include <sys/stat.h>
      // mkfifo创建FIFO,文件,参数pathname指定名字,mode给定FIFO的权限,权限有四个如0666
      int mkfifo(const char *pathname, mode_t mode);
      // 创建完成后必须使用open打开该文件,类似于各种文本文件等的打开
      #include <fcntl.h>
      // 注意,此时open函数会被阻塞直至另一个进程打开这个FIFO来读取数据或者该FIFO已被打开则open立即返回调用
      fd = open(pathname, O_WRONLY);
      // 另一种非阻塞调用必须使用O_NONBLOCK,如果没有进程打开FIFO读取,则open返回-1,而不阻塞
      if((fd = open(pathname, O_WRONLY|O_NONBLOCK)) == -1)
      perror("open fail");
      // ?打开之后怎么写入和读取FIFO?
阅读全文 »

前言:前段时间突然想看鬼刀漫画,于是进了有妖气漫画官网,其间觉得一些图太惊艳,于是想着自己把漫画扒下来好好收藏……最开始使用js爬取所有图片链接再使用IDM批量下载,后来本打算直接使用js将链接下载保存到本地,先是遇到了跨域问题尝试了很多方法一直没有解决,后来直接在漫画服务器可以下载,但是却又不方便读取链接或者本地链接文件,于是暂时就此作罢,以后有时间看看用python直接爬取试试

js代码如下:

  • 第一部分几个函数忘了是从哪个大佬博客拿来的了,所以没有链接参考,这一部分直接调用download()可以将字符串保存到本地文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
function serch_char(str,num){
var icount = 0;
var response = 0;
var charChest = '=';
for (var i in str){
var ch = str[i]
if (charChest == ch){
icount++;
if (icount == num)
return response;
}
response++;
}
}

function fake_click(obj) {
var ev = document.createEvent("MouseEvents");
ev.initMouseEvent(
"click", true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null
);
obj.dispatchEvent(ev);
}

function download(name, data) {
var urlObject = window.URL || window.webkitURL || window;

var downloadData = new Blob([data]);

var save_link = document.createElementNS("http://www.w3.org/1999/xhtml", "a")
save_link.href = urlObject.createObjectURL(downloadData);
save_link.download = name;
fake_click(save_link);
}
//调用方法
//download("save.txt","内容");
  • 这一部分全局变量和上面的函数一起定义一次即可:
1
2
3
4
5
// 所有链接地址
var urls = "";
var oldUrl = ""
var url = ""
var countImg = 0;
  • 有妖气漫画由于每一章都会停一次,不能直接按照章节数直接循环到尾,所以需要手动重新在控制台循环这段代码44次(章节数):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
while(true){
var nextButton = document.getElementsByClassName('next');
var Img = document.getElementsByClassName('image_cache loading cur_img');
url = Img[0].getAttribute("src");

if(oldUrl!=url){
oldUrl = url
}else{
break;
}

urls = urls + url + "\n";

// 下一页
nextButton[0].click();
countImg++;
console.log(countImg);
}
  • 最后在保存到本地:
1
download("save.txt",urls);

最后放入下载好的鬼刀漫画一份

文叔叔链接只有七天:

https://ws28.cn/f/45e3vym3sdq

百度网盘链接:

链接:https://pan.baidu.com/s/1iNDip7X0dBpTOABOWgrfmw
提取码:52pj
复制这段内容后打开百度网盘手机App,操作更方便哦

前言:由于课程课时原因,从本章往后部分老师已不细讲,对计算机网络做一个简单了解的话涉及到前三层也差不多了,因此本章会简略些,后续章节也可能不会再出单章博客,不便之处敬请谅解,谢谢!

1.概述

控制平面主要有两种形式:

  • 每路由器控制:在每台路由器中运行一种路由选择算法,每台路由器中都包含转发和路由选择功能;
image-20201201100331662
  • 逻辑集中式控制:
image-20201201100411586
阅读全文 »