记录一下学习笔记

@ConfigurationProperties 主要用来把properties配置文件转化为bean来使用的

@EnableConfigurationProperties({HttpUrl.class}) 是使@ConfigurationProperties注解生效(并获取该实例), 也就是将实例交由spring管理(@EnableConfigurationProperties注解是用来开启对@ConfigurationProperties注解配置Bean的支持。

也就是@EnableConfigurationProperties注解告诉Spring Boot 使能支持@ConfigurationProperties)

Spring Boot支持的所有动装配类存放在spring-boot-autoconfigure包下的META-INF/spring.factories文件中

为什么多个jar包存在spring.factories,都会被SpringBoot加载,因为spring-core包里定义了SpringFactoriesLoader类,这个类实现了检索META-INF/spring.factories文件。他会检索classLoader中所有jar包下的spring.factories,具体细节可查看官网https://blog.csdn.net/lldouble/article/details/80690446

 

@EnableAutoConfiguration注解的意思为自动装配,实现的关键在于引入了AutoConfigurationImportSelector,其核心逻辑为selectImports方法,逻辑大致如下:

1.从配置文件META-INF/spring.factories加载所有可能用到的自动配置类;

2.去重,并将exclude和excludeName属性携带的类排除;

3.过滤,将满足条件(@Conditional)的自动配置类返回;

 

spring.provides文件的作用是在当前文件所在的jar包中,将指定依赖的依赖名(artifactId)配置的在该文件中,引入该jar包,将自动引入配置文件中指定的jar包

 

在日常工作中,我们可能需要实现一些SDK或者Spring Boot Starter给被人使用,这个使用我们就可以使用Factories机制。Factories机制可以让SDK或者Starter的使用只需要很少或者不需要进行配置,只需要在服务中引入我们的jar包。

 

除了使用@EnableConfigurationProperties时@ConfigurationProperties生效,还有几个方法,可以搭配@Configuration 注解来提供 @Bean,也可以单独使用并注入 @Configuration bean。

 

 

在使用springboot微服务开发中,如果遇到需要调用依赖模块的配置文件的时候(就是在服务启动的时候自动加载依赖配置文件的内容)可以使用spring.profiles.include来实现

服务的配置文件为:application.yml 依赖模块的配置文件为:application-dependency.yml(需要注意的是依赖模块的前缀必须和当前服务的配置文件保持一致)

application.yml

spring:

  profiles:

    include: dependency

即可完成

在实际开发中,SpringBoot都是率先读取application.yml配置文件,然后通过spring.profiles.active来查看接下来需要读取的配置文件

 

1.rest api中的model, vo, dto之间的关系

model:用于接收数据库中的数据,通过mybatis 的ORM对象关系映射来获取数据

service主要是来处理业务逻辑,返回数据(数据的返回不会做如何处理,只是将model中的数据进行整合然后保证返回的数据完整性,比如在service中返回一个user model 和一个 role model, 会提供一个UserROleBO来接收user 和 role的数据)

dto: dto主要是用来作为传输数据,在我们的项目中是用来接收远程调用接收响应的对象

vo:主要是我们本地调用的对象, 用来向用户显示(BO中的user和role只需要显示userName和roleName,会通过VO来进行显示)

在实际的开发中,VO对应页面上需要显示的数据,DO对应于数据库中储存的数据(表列,也就是model),DTO对应于除二者之外需要传递的数据。 DTO(data transfer object):数据传输对象,以前被称为值对象(VO,value object),作用仅在于在应用程序的各个子系统间传输数据,在表现层展示。与POJO对应一个数据库实体不同,DTO并不对应一个实体,可能仅存储实体的部分属性或加入符合传输需求的其他的属性。

2(*).关于@EnableConfigurationProperties,在SpringBoot的注释中是这样说明的:为带有@ConfigurationProperties注解的Bean提供有效的支持。这个注解可以提供一种方便的方式来将带有@ConfigurationProperties注解的类注入为Spring容器的Bean。你之前可能听说过类似这样的说法@ConfigurationProperties注解可以生效是因为在SpringBoot中有一个类叫ConfigurationPropertiesAutoConfiguration,它为@ConfigurationProperties注解的解析提供了支持的工作,这种说法更准确一点的说法是在这个类上还存在了@Configuration和@EnableConfigurationProperties这两个注解!

@SpringbootApplication注解是@Configuration, @EnableAutoConfiguration, @ComponentScan的集合

@EnableAutoConfiguration主要的作用就是将当前类路径下的被@ComponentScan扫描的包的注解进行自动装配置到spring容器中,@EnableAutoConfiguration注解下有一个@import(AutoConfigurationImportSelector.class)

AutoConfigurationImportSelector中使用到了SpringFactoriesLoader。

重点:SpringFactoriesLoader类是springboot内部的一个拓展类,主要是将META-INF目录下的spring.factories(用于配置spring的接口和实现类的对照关系)文件中的指定的类进行初始化,交由springboot管理。@EnableAutoConfiguration可在spring.factories通过”org.springframework.boot.autoconfigure.EnableAutoConfiguration=“找到获取需要实例化的类,所以也可以自定义该文件,在springboot中的多个jar包都含有spring.factories, 都会在服务启动的时候自动配置,所以可以将自己打包的文件中想要在服务启动的时候自动初始化的类配置在spring.factories中

3(*). 关于java的类加载器:(类装载器就是寻找类或接口字节码文件进行解析并构造JVM内部对象表示的组件)

(1).1.隐式装载, 程序在运行过程中当碰到通过new 等方式生成对象时,隐式调用类装载器加载对应的类到jvm中。 2.显式装载, 通过class.forname()等方法,显式加载需要的类

类加载器:

1、bootstrap loader : Bootstrp加载器是用C++语言写的,它是在Java虚拟机启动后初始化的,它主要负责加载%JAVA_HOME%/jre/lib,-Xbootclasspath参数指定的路径以及%JAVA_HOME%/jre/classes中的类。

2、ExtClassLoader: Bootstrp loader加载ExtClassLoader,并且将ExtClassLoader的父加载器设置为Bootstrp loader.ExtClassLoader是用Java写的,具体来说就是 sun.misc.Launcher$ExtClassLoader,ExtClassLoader主要加载%JAVA_HOME%/jre/lib/ext,此路径下的所有classes目录以及java.ext.dirs系统变量指定的路径中类库。

3、AppClassLoader:Bootstrp loader加载完ExtClassLoader后,就会加载AppClassLoader,并且将AppClassLoader的父加载器指定为 ExtClassLoader。AppClassLoader也是用Java写成的,它的实现类是 sun.misc.Launcher$AppClassLoader,另外我们知道ClassLoader中有个getSystemClassLoader方法,此方法返回的正是AppclassLoader.AppClassLoader主要负责加载classpath所指定的位置的类或者是jar文档,它也是Java程序默认的类加载器。

三个类加载器之间的关系是:3 extends 2 extends 1,加载的顺序是 1 -->2 -->3和一个类加载相同,先初始化父类,然后再是自己。(类装载器有载入类的需求时,会先请示其Parent使用其搜索路径帮忙载入,如果Parent 找不到,那么才由自己依照自己的搜索路径搜索类”)

我们平时使用this.class.getClassLoader获取的类加载时就是AppClassLoader.

类加载的过程:我们所编写的.java文件经过Java编译器后生成的.class文件(JVM可以识别的指令),被JVM加载到内存中,并创建class对象。

1.getResource、getResourceAsStream如果被Class直接调用,带“/”就是从classpath底下查找,不带“/”就是从此类所在的包底下查找

2. getResource、getResourceAsStream如果被ClassLoader直接调用,默认则是从ClassPath根下获取,path不能以’/'开头

4(*): 工作流

processEngine是工作流的核心,可以通过流程引擎获取工作流所有相关的东西

databaseSchemaUpdate属性的取值:

flase: 默认值。activiti在启动时,会对比数据库表中保存的版本,如果没有表或者版本不匹配,将抛出异常。

true: activiti会对数据库中所有表进行更新操作。如果表不存在,则自动创建。

create_drop: 在activiti启动时创建表,在关闭时删除表(必须手动关闭引擎,才能删除表)。

drop-create: 在activiti启动时删除原来的旧表,然后在创建新表(不需要手动关闭引擎)。

使用工作流的目的主要是将流程状态的流转交由工作流来管理,开发人员只需要处理自己相关的业务逻辑即可,不需要关心流程状态的改变和处理人的问题,使其与业务逻辑解耦,利与拓展。

5. springboot中有一个类叫做RequestContextHolder,该类主要是用来获取请求的request对象和响应的response对象, springboot中的Environment类主要是用来获取配置文件的内容.

6.@ConditionalOnClass(name = {"org.activiti.rest.service.api.RestUrls"}) 其用途是判断当前classpath下是否存在指定类,若是则将当前的配置装载入spring容器

@Configuration

@ConditionalOnClass({Billy.class}) //当编译后,启动服务,存在Billy.class后,才会加载VanConfig类(执行以下方法加载springboot容器中管理)

public class VanConfig {

@Bean

public Fighter billy(){

return new Billy();

}

@Bean

public Van van(){

return new Van(billy());

}

}

 

7.@AutoConfigureAfter(ClassA.class)解表示在加载完当前配置类之后在加载注解指定的类(@AutoConfigureAfter 在加载参数类之后再加载当前类 它的value 是一个数组 一般配合着@import 注解使用 ,在使用import时必须要让这个类先被spring ioc 加载好 所以@AutoConfigureAfter必不可少)

8.CommandLineRunner接口的作用:平常开发中有可能需要实现在项目启动后执行的功能,SpringBoot提供的一种简单的实现方案就是添加一个model并实现CommandLineRunner接口,实现功能的代码放在实现的run方法中, # 如果有多个类实现CommandLineRunner接口,如何保证顺序

> SpringBoot在项目启动后会遍历所有实现CommandLineRunner的实体类并执行run方法,如果需要按照一定的顺序去执行,那么就需要在实体类上使用一个@Order注解(或者实现Order接口)来表明顺序

具体可参考:https://www.cnblogs.com/myblogs-miller/p/9046425.html

9.http协议:http1.0和http1.1协议之间的区别在于。http1.0版本是发送一次连接,响应后自动释放连接(一次只能发送过一次请求)

http1.1协议对其进行了拓展,发送一次连接请求后,可以发送多个请求和接收多个响应,全部完成后,释放连接,http协议的规定是,只能客户端向服务器发起请求和服务器响应,这里的服务器是被动的,无法主动发送消息至客户端。(websocket)很好的解决了这个问题。

websocket是html5推出的一种应用层协议(本质上是基本tcp协议(数据传输层)),借用了http协议中的部分协议(tcp),自身对http协议进行了相应的拓展,

websocket和http1.1协议的联系和区别:首先两者都是应用层协议,而且 WebSocket 在建立连接时,需要借用 http 的 101 switch protocol 来达到协议转换,为了建立一个 WebSocket 连接,客户端浏览器首先要向服务器发起一个HTTP请求,这个请求和通常的HTTP请求不同,包含了一些附加头信息,其中附加头信息"Upgrade: WebSocket"和"Connection: Upgrade"表明这是一个申请协议升级的 HTTP 请求,服务器端解析这些附加的头信息然后产生应答信息返回给客户端,客户端和服务器端的 WebSocket 连接就建立起来了,在建立连接后,就和HTTP没有关系了,双方就可以通过这个连接通道自由的传递信息。

在HTTP中,一个Request对应着一个Response,早期的HTTP1.0每次的HTTP连接都需要打开一个TCP连接,在一个Request后,服务器产生一个应答Request,这次HTTP连接就结束了,同时关闭了TCP连接,重复的建立TCP连接是一种资源浪费,主动关闭TCP连接后还会出现time_wait状态,继续占用资源 一段时间,这种情况在HTTP1.1中进行了一定的改进,使得有一个keep-alive,也就是说,在一个HTTP连接中,可以发送多个Request,接收多个Response,可以减少建立和拆除TCP连接的次数,因此同时减少了time_wait状态的连接,但是,如果设置了keep-alive的超时时间比如nginx中是keepalive_timeout,一段时间没有通信超时后服务器主动关闭连接也是可能造成服务器出现time_wait状态的,如果不设置超时时间也会造成一定的资源浪费(占用连接却不发送数据),所以怎么设置这个超时时间也很重要。

websocket(http协议的替代者)和socket区别:socket在第五层会话层,它并不是一个协议,而是一组接口(api),更是一个规范,为了方便使用底层协议而存在的一种抽象层。 两台机器需要进行通信就需要进行socket连接,进行socket连接就需要依赖底层tcp协议,tcp协议又依赖于ip协议来找寻网络中的主机。找到了主机后,根据端口号( TCP 、UDP 地址)与应用程序进行通信。

对用户来说可以直接使用socket,根据参数让它去符合不同的协议进行通信。(网络中的Socket是一个抽象的接口,可以理解为网络中连接的两端。通常被叫做套接字接口,其意义在对传输层进行封装屏蔽了传输层的复杂性。它并不是一个协议,是为了大家更方便的使用传输层协议产生的一个抽象层。大部分的主流编程语言都提供socket函数.)

10. ssh(远程连接工具):SSH是一种网络协议,用于计算机之间的加密登录,ssh服务是一个守护进程(demon),系统后台监听客户端的连接,ssh服务端的进程名为sshd,负责实时监听客户端的请求(IP 22端口),包括公共秘钥等交换等信息。客户端请求登录服务器,服务器将自己的公钥返回给客户端,客户端确认是自己想要连接的服务器,将自己的登录密码经过服务器的公钥加密后,发送给服务器,服务器通过自己的私钥进行解密,确认密码正确后,连接成功。

11. 中间人攻击

SSH之所以能够保证安全,原因在于它采用了公钥加密。

整个过程是这样的:(1)远程主机收到用户的登录请求,把自己的公钥发给用户。(2)用户使用这个公钥,将登录密码加密后,发送回来。(3)远程主机用自己的私钥,解密登录密码,如果密码正确,就同意用户登录。

这个过程本身是安全的,但是实施的时候存在一个风险:如果有人截获了登录请求,然后冒充远程主机,将伪造的公钥发给用户,那么用户很难辨别真伪。因为不像https协议,SSH协议的公钥是没有证书中心(CA)公证的,也就是说,都是自己签发的。

可以设想,如果攻击者插在用户与远程主机之间(比如在公共的wifi区域),用伪造的公钥,获取用户的登录密码。再用这个密码登录远程主机,那么SSH的安全机制就荡然无存了。这种风险就是著名的"中间人攻击"(Man-in-the-middle attack)。

12. 数据库在进行写入操作之前,都是先写入日志文件,然后对数据库的表进行crud.

13. 每个基于mybatis的应用都是以SqlSessionFactory(会话工厂)为中心的,sqlSessionFactory可以通过SqlSessionFactoryBuilder来获取,而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先定制的 Configuration 的实例构建出 SqlSessionFactory 的实例(具体可查看源码)。configuration对象保存了mybatis的所有配置文件的信息(主要包含sqlConfig.xml基础配置信息和mapper.xml映射器配置文件),sqlSession对象是在创建后。进行crud的时候才创建connection对象,如果添加了事务,多个sql语句之间的执行时同一个sqlSession,因为在一个connection下才能保证事务的一致性,如果未定义事务,则每次都是创建一个新的会话(sqlSession是线程不安全的,所以应当放入方法体中定义和获取)

14. mybatis中的MappedStatement表示的是mapper.xml文件中的一个sql.(比如<select></select>). MappedStatement对mapper.xml文件维护了一条<select|update|delete|insert>节点的封装,Configuration类封装了mybatis的配置文件和mapper.xml配置文件。SqlSession对象中包含了configuration的引用。sqlsession对象可以对数据库进行增删改查的操作,但真正与数据库交互的是Executor类。

ResultMap类相当与<resultMap/>,ResultMapping类 相当于<id/>或<column/>,具体可查看源码,对于返回或传递的类型不匹配时,mybatis包含一个typeHandler接口,实现了大部分的类型转换问题,具体可查看源码(BaseTypeHandler)。

mybatis的动态代理是通过SqlSession.getMapper(Class class)来实现的,底层是通过MapperRegistry类的(mapperProxyFactory)来实现,具体细节可查看源码。

mybatis中的SqlSession下的四大对象:

(1).Executor(执行器): sql语句的执行器(mybatis有3种执行器,具体可查看源码),executor内部的执行和需要用到语句处理器和参数处理器。参数处理器用于将参数映射到对应的sql语句中

(2).statementHandler(语句处理器):对sql语句进行处理,包含PrepareStatementHandler,具体可参考源码

(3).parameterHandler(参数处理器):将参数映射到指定的语句中

(4).resultHandler(结果集处理器):对查询的结果集进行处理

四大对象都可以通过实现拦截器接口来进行操作。

15. 开发系统时引入工作流的目的是为了分离业务逻辑和过程逻辑,让业务开发人员专注于核心的业务开发,过程逻辑的处理交给工作流引擎     ,且过程逻辑的变化对于核心业务逻辑不影响或者影响很少。

是否引入工作流引擎,取决于系统的业务是否复杂以及过程逻辑的变化性。如果过程逻辑相当复杂,或者过程逻辑经常变化,最好是引入工作流,分离业务逻辑和过程逻辑。相反业务简单且日后的变化甚小,那就没必要引入工作流了。引入工作流后系统的层次增加了,分层越多,各个层次间的沟通和协调就越复杂,作来一个PM这点是需要考虑的。

* 16. JDK的动态代理的实现主要的原理是共同实现了目标类的接口,然后通过父类的引用指向子类的对象来通过代理对象调用目标对象的方法然后在InvocationHandler实现类的invoke()方法中进行预处理或后置处理等。jdk动态代理核心是Proxy和InvocationHandler,Proxy用来创建代理类和代理类实例,Proxy类中的

newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)方法通过目标类的类加载器

和实现的接口的类对象来创建动态代理类,创建动态代理类实例,并将调用处理接口作为一个构造函数中的参数传入生成动态代理类对象,

,然后调用代理类中的方法的时候,其实内部实现的是InvocationHandler的实现类中的invoke方法。从而实现了动态代理。具体可查

看Proxy源码(newProxyInstance()方法)

 

17.Java中的Type类是所有类型的父接口,(Class是一个Type类型, Object是一个类对象,两者有完全不同的概念)

泛型的引入使得一部分错误可以提前到编译时期发现,极大地增强了代码的健壮性。但是我们知道 java 泛型在运行的时候是会进行

泛型擦除的,那我们要怎样得到在编译时期泛型的信息呢?java 为我们提供了 Type 接口,使用它,我们可以得到这些信息。

Type体系中类型的包括:原始类型(Class)、参数化类型(ParameterizedType)、数组类型(GenericArrayType)、

类型变量(TypeVariable)、基本类型(Class);

 

参数化类型(ParameterizedType),即泛型;例如:List<T>、Map<K,V>等带有参数化的对象;

类型变量(TypeVariable),即泛型中的变量;例如:T、K、V等变量,可以表示任何类;在这需要强调的是,TypeVariable代表着泛型中的变量,

而ParameterizedType则代表整个泛型;(TypeVariable => <D extends Object>D代表泛型中的变量, ParameterizedType代表整个泛型)

泛型数组类型(GenericArrayType),用来描述ParameterizedType、TypeVariable类型的数组;即List<T>[] 、T[]等;

Class 是Type的一个实现类,属于原始类型,是Java反射的基础,对Java类的抽象;

泛型表达式(或者通配符表达式)(WildcardType),即? extend Number、? super Integer这样的表达式;

WildcardType虽然是Type的子接口,但却不是Java类型中的一种。

具体细节可查看源码

18. springboot中的通过@ControllerAdvice和@ExceptionHandler实现处理controller层的异常,具体可查看官网和源码

19. @validated注解主要用于参数的校验,可查看https://blog.csdn.net/Mynewclass/article/details/79086372

@Null 限制只能为null

@NotNull 限制必须不为null

@AssertFalse 限制必须为false

@AssertTrue 限制必须为true

@DecimalMax(value) 限制必须为一个不大于指定值的数字

@DecimalMin(value) 限制必须为一个不小于指定值的数字

@Digits(integer,fraction) 限制必须为一个小数,且整数部分的位数不能超过integer,小数部分的位数不能超过fraction

@Future 限制必须是一个将来的日期

@Max(value) 限制必须为一个不大于指定值的数字

@Min(value) 限制必须为一个不小于指定值的数字

@Past 验证注解的元素值(日期类型)比当前时间早

@Pattern(value) 限制必须符合指定的正则表达式

@Size(max,min) 限制字符长度必须在min到max之间

@NotEmpty 验证注解的元素值不为null且不为空(字符串长度不为0、集合大小不为0)

@NotBlank 验证注解的元素值不为空(不为null、去除首位空格后长度为0),不同于@NotEmpty,@NotBlank只应用于字符串且在比较时会去除字符串的空格

@Email 验证注解的元素值是Email,也可以通过正则表达式和flag指定自定义的email格式

20. 枚举的类型的接收和请求的转换可以使用@JsonValue和@JSONField注解来完成,具体可查看fastJson

21. http协议下的文件传输是通过字节流来进行传输的,而对于java的序列化(使用ObjectOutputStream)和反序列化(使用ObjectInputStream)的理解就是:序列化就是将Java对象转换为字节序列的过程,反序列化就是将字节序列转换为Java对象的过程(只需要知道的是Serializable是在java.io包下,所以就是设计到io流的时候才会用到序列化和反序列化),使对象持久化和文件内容的传输都需要设计到io,而这就是序列化和反序列化的应用场景

22. where 后面不可接聚合函数,因为聚合函数是针对结果集进行的(对多个结果集进行计算后返回一条计算后的数据),但是where条件并不是在查询出结果集之后运行,所以聚合函数放在where语句中,会出现错误。sql语句的执行过程是:from-->where-->group by -->having --- >order by --> select;

 

23. 序列化和反序列化说到底就是一个编码一个解码的过程,将一个对象编码成一个二进制的字节序列,然后将一个二进制字节序列解码为对象。而设计Decoder 和Encoder又分为2中 HTTP协议的处理过程,TCP字节流 <---> HttpRequest/HttpResponse <---> 内部对象,就涉及这两种序列化,第一种是对象与字节序列直接的相互转换的序列化和反序列化,第二种层次更高,是对象与对象之间的序列化,(TCP字节流 <---> HttpRequest/HttpResponse)由Servlet容器(tomcat,nginx,等)帮我们处理,springMVC主要是对 (HttpRequest/HttpResponse <---> 内部对象)进行处理,SpringMVC的@RestController中的@ResponseBody注解来实现json数据序列化和反序列化的功能,核心是HttpMessageConverter类, 具体可查看https://www.cnblogs.com/page12/p/8166935.html

 

24.SSL介于应用层和TCP层之间。应用层数据不再直接传递给传输层,而是传递给SSL层,SSL层对从应用层收到的数据进行加密,并增加自己的SSL头(ssl是一种协议,ssh是一个脚本)

25.对称加密算法:在对称加密算法中,数据发信方将明文(原始数据)和加密密钥一起经过特殊加密算法处理后,使其变成复杂的加密密文发送出去。收信方收到密文后,若想解读原文,则需要使用加密用过的密钥及相同算法的逆算法对密文进行解密,才能使其恢复成可读明文,比如:客户端:(Base64.encoder(Strs + "加密的密钥"))= message TO 服务端(服务端需知道加密的密钥):(Base64.decoder(message))=>strs

26.非对称加密算法:使用的加密和解密的密钥是不同的,加密的公钥只有解密的私钥才能解密,反之亦然(RSA非对称加密)

现在的企业级开发中都是使用非对称加密算法来加密和解密对称加密算法的密钥(https://www.cnblogs.com/jiftle/p/7903762.html)

27. 在对sql进行查询的时候,有时候涉及多种情况时,多加思考,只要确定返回的结果集里面有自己想要的数据,即使返回的结果集中有多余的数据字段,字需要通过判断来取出自己想要的数据即可,(记住,返回的数据是从结果集中获取的)

28. 异常的捕获方法有两种,对于提供RESTful服务的应用,使用@ControllerAdvice和@ExceptionHandler注解; 对于使用模板渲染HTML的应用,实现HandlerExceptionResolver接口。SpringMVC为我们提供了一个通用的异常处理逻辑,即ResponseEntityExceptionHandler类,该类的handleException()方法上标注了@ExceptionHandler注解。此方法会判断 Exception 的类型,对于每一种类型,会交由对应的protected handleXXXX()方法处理,子类只需要重写对应的方法即可, 可查看https://blog.csdn.net/neosmith/article/details/51090509

 

29.spring中的的classpath和classpath*的区别:

classpath:只会到你的class路径中查找文件。

classpath*:不仅包含class路径,还包括jar文件中(class路径)进行查找。

30. bpm框架全称是(business process management), activiti的关于任务的完成都是采用命令模式来完成的,具体可多查看activiti源码(https://blog.csdn.net/bluejoe2000/article/details/41800889)

31. 在activiti中通常来讲,executionListener执行监听器的声明周期是包含taskListener任务监听器的声明周期的。如下所示:

 

ExecutionListener#start(启动)

TaskListener#create(创建)

TaskListener#{assignment}*(分配)

TaskListener#{complete, delete}(完成,删除)

ExecutionListener#end(结束)

 

32. aop中的joinPoint为织入点,JoinPoint对象封装了SpringAop中切面方法的信息,在切面方法中添加JoinPoint参数,

就可以获取到封装了该方法信息的JoinPoint对象.

访问目标方法即用jointpoint(@around用poceedingjointpoint)

1.获取他们的目标对象信息,如test.component@80387a这种,

2.还有获取带参方法的参数,如[Ljava.lang.Object;@183cfe9(想当然我们也可以用对象的arrays.toString()方法将其还原)

3.另外还有获取被增强的方法相关信息 如String test.component.test1(String)这种

方法名功能
Signature getSignature();

获取封装了署名信息的对象,在该对象中可以获取到目标方法名,所属类的Class等信息

(signature是信号,标识的意思):获取被增强的方法相关信息

Object[] getArgs();获取传入目标方法的参数对象
Object getTarget();获取被代理的对象
Object getThis();

获取代理对象

 

 

 

33. 在创建一个sdk的时候,如果需要在服务启动的时候,需要多个类在服务启动是被加载,使用@ComponentScan组件扫描注解来指定要扫描的包,对特定的类被加载以及读取配置文件中的内容可以使用@ConfigurationProperties注解来完成。

34.spring对Java在运行时获取泛型类型的ParameterizedType进行了封装为一个类为ParameterizedTypeReference,该类主要用于restTemplate中接收响应的数据的泛型接收。(该类的目的是支持捕获和传递泛型{@link Type}。为了捕获泛型类型并在运行时保留它,对于List<Object>这种无法直接通过restTemplate获取,可通过该类获取)

35. JWT(json web token):JWT适合一次性的命令认证,颁发一个有效期极短的JWT,即使暴露了危险也很小,由于每次操作都会生成新的JWT,因此也没必要保存JWT,真正实现无状态。

36.ps指令是(process status)进程状态的缩写,使用该执行可以查看当前正在运行的进程,top执行可以动态查看当前指正执行的进程,杀死进程可以使用 kill pid(12345)指令,使用free指令可以查看当前内存的使用情况。     

37. rpc服务(romote procedure call)远程过程调用,是一种信息传输协议,主要作用与分布式,rpc理论上包含了http协议,比如google最新推出的基于http2.0协议的gRPC的一个rpc框架,http服务是局域HTTP协议(应用在应用层上的),都是应用于网络间的数据传输,但是rpc理所当然的速度要优于http的. 网络传输的7层:(最后是通过io流以二进制字节码文件进行传输的)

  • 第一层:应用层。定义了用于在网络中进行通信和传输数据的接口;

  • 第二层:表示层。定义不同的系统中数据的传输格式,编码和解码规范等;

  • 第三层:会话层。管理用户的会话,控制用户间逻辑连接的建立和中断;

  • 第四层:传输层。管理着网络中的端到端的数据传输;

  • 第五层:网络层。定义网络设备间如何传输数据;

  • 第六层:链路层。将上面的网络层的数据包封装成数据帧,便于物理层传输;

  • 第七层:物理层。这一层主要就是传输这些二进制数据。

http协议主要包含前三层,也就是相当于应用层包含了前三层, http是作用于应用程序的协议,rpc一般的应用场景在于C/S架构模式中.(RPC采用客户机/服务器模式。请求程序就是一个客户机,而服务提供程序就是一个服务器。首先,客户机调用进程发送一个有进程参数的调用信息到服务进程,然后等待应答信息。在服务器端,进程保持睡眠状态直到调用信息到达为止。当一个调用信息到达,服务器获得进程参数,计算结果,发送答复信息,然后等待下一个调用信息,最后,客户端调用进程接收答复信息,获得进程结果,然后调用执行继续进行。)

 

38.传统的客户端与服务器通信是采用传统的IO通信,但设计到现在越来越多的高并发访问,传统的io通信已经无法满足当代的分布式高并发的应用程序,NIO,即New IO,也叫Non-blocking I/O(是同步的非阻塞式io流),而后又推出了异步的io(AIO)是在Java 1.4后推出的一种对IO通信的优化,但是其使用复杂,此时netty出现了,netty是对NIO进行封装的一种网络通信框架.具体学习可参考netty入门

io流(Blocking I/O)是阻塞式的,当read()和readLine()都会读取对端发送过来的数据,如果无数据可读,就会阻塞直到有数据可读。或者到达流的末尾,这个时候分别返回-1和null。因此为什么要在使用完流的时候要关闭流,如果不关闭流。一直处于阻塞状态,对于网络编程而言,就会一直占用端口,而后可能会造成内存溢出或内存泄漏等问题的出现。


39.SOA(Service-Oriented Architecture)面向服务架构,微服务架构是SOA的升级版,微服务架构更强调分布式的服务发现,负债均衡等

 

40.在Java中的Arrays.asList(T[] t)是将一个数组类型转换为List类型,底层是Arrays类中有一个ArrayList的子类,是一个数组类型,只是接受的类型从一个数组转变成了接口类型,并没有做到实际的从数组转换为集合(数据已经是数组),所以对接受后的List进行添加数据会抛运行时异常,对原来的数组的数据进行改变也会改变接受后的List的数据(重点)

 

41.java中的适配器模式是起到一个适配中间件的作用,类似于生活中的转换器,你去一个地方吃饭,都会有一个转换器,上面有很多接口,安卓的,ios的,快充的,连接的是充电宝,对应的不同的手机都可以连接该充电宝,而转化器就是起到了适配的作用。具体去看详细博客。

 

42.防止NPE是我们需要做到的, java8采用Optional类来防止NPE问题。在 JDK8 中,针对统计时间等场景,推荐使用 Instant 类

 

43.字符集和字符编码的区别是什么?举例说明, unicode是一个字符集.类似于现实生活中的数据库,用于存储世界上所有的文字集合,每个文字集合对应于一个标识符(类似于主键),是唯一的, 而目前的unicode编码可以涵盖100W以上的字符,(每个字符用4个字节来进行存储),而这个对于某些只是用ascii的国家(英文的字符用一个字节表示即可)来说,是大大的浪费了存储空间(高位都要补0),为了解决Unicode占用硬盘和流量大的问题产生了相关编码方式, 出现了utf-8,utf-16字符编码,utf-8(可变长编码)的出现解决了存储和传输效率上的难题,对于一个字节的英文字符还是采用1个字节进行传输,对于汉字大多都是3个字节,便用3个字节传输,关于utf-8与unicode字符集的转换可查看相关资料进行了解.网络上的文件或信息的交互都是通过比特流来实现的,utf-8对unicode字符进行编码传输,然后显示又进行转码达到正常显示.

 

44. http协议在网络上进行数据交互底层是使用tcp/udp来实现的(物理层为bit流),但是网络上的数据传输格式通常是采用xml和json(网络上传输的是数据,将数据从一端传输到另一端是通过文件(文本)的形式传输, tcp, udp将文件进行分割成各种包(package),以数据包传输.

 

45. 什么是序列化?

序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。(可以将对象序列化到流、磁盘、内存和网络等等)

 

46. %d,%c,%s,%x是程序汇编语言中的格式符,它们的含义:

1、%d表示按整型数据的实际长度输出数据。

2、%c用来输出一个字符。

3、%s用来输出一个字符串。

4、%x表示以十六进制数形式输出整数。

JDK1.5中,String类新增了一个很有用的静态方法String.format():
format(Locale l, String format, Object... args) 使用指定的语言环境、格式字符串和参数返回一个格式化字符串。
format(String format, Object... args) 使用指定的格式字符串和参数返回一个格式化字符串。

47. (NIO)所有缓冲区都有4个属性:capacity、limit、position、mark,并遵循:mark <= position <= limit <= capacity,下表格是对着4个属性的解释:

Capacity 容量,即可以容纳的最大数据量;在缓冲区创建时被设定并且不能改变
Limit 表示缓冲区的当前终点,不能对缓冲区超过极限的位置进行读写操作。且极限是可以修改的
Position 位置,下一个要被读或写的元素的索引,每次读写缓冲区数据时都会改变改值,为下次读写作准备
Mark 标记,调用mark()来设置mark=position,再调用reset()可以让position恢复到标记的位置
 

具体查看ByteBuffer常用方法

 

48. 数据库版本管理工具Flyway

49. 每个java对象都含有一个monitor(锁标记),也就是监听器,多线程同时访问某个对象时,线程只有获取了该对象的锁才能访问.

50.堆区:
1.存储的全部是对象,每个对象都包含一个与之对应的class的信息。(class的目的是得到操作指令)
2.jvm只有一个堆区(heap)被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身
栈区:
1.每个线程包含一个栈区,栈中只保存基础数据类型的对象和自定义对象的引用(不是对象),对象都存放在堆区中
2.每个栈中的数据(原始类型和对象引用)都是私有的,其他栈不能访问。
3.栈分为3个部分:基本类型变量区、执行环境上下文、操作指令区(存放操作指令)。
方法区:
1.又叫静态区,跟堆一样,被所有的线程共享。方法区包含所有的class和static变量。
2.方法区中包含的都是在整个程序中永远唯一的元素,如class,static变量。

 

51. 计算机CPU和内存的交互是最频繁的,内存是我们的高速缓存区,用户磁盘和CPU的交互,而CPU运转速度越来越快,磁盘远远跟不上CPU的读写速度,才设计了内存,用户缓冲用户IO等待导致CPU的等待成本,但是随着CPU的发展,内存的读写速度也远远跟不上CPU的读写速度,因此,为了解决这一纠纷,CPU厂商在每颗CPU上加入了高速缓存,用来缓解这种症状。 Java中通过多线程机制使得多个任务同时执行处理,所有的线程共享JVM内存区域main memory,而每个线程又单独的有自己的工作内存,当线程与内存区域进行交互时,数据从主存拷贝到工作内存,进而交由线程处理(操作码+操作数)。具体查看jvm内存模型

 

52. ubuntu18.04 下载fcitx未激活的解决方法是新建/修改 ~/.xprofile文件,添加一下内容:

export GTK_IM_MODULE=fcitx
export QT_IM_MODULE=fcitx
export XMODIFIERS="@im=fcitx"

然后重启计算机(以上操作不要使用root权限进行操作)

53. Base64的编码: base64顾名思义就是使用0~63个可见字符来对二进制进行编码(再加上作为垫字的“=”,实际上是65个字符),常用于网络传输,例如:邮件中只允许出现可见字符(对于回车,换行都无法在邮件中显示出来,就无法传输,通过base64编码可以实现这一点)。base64就是将3个8位的字节编码成4个六位的字节,在每个字节前面补0,也就是说将3个字节转换成了4个字节(每个字节的区间位0~63),实现了网络传输不同数据格式的文件,但是增加了传输的数据量,所以只适用于网络上的图片,视频等文件的传输(对其进行编码),然后解码,最后存储在硬盘中。Base64编码并不是真正的加密方式,它只是从二进制到字符的转换过程。base64是将3个字节作为一组,也就是24二进制位,拆分成32二进制位,每个6位前面补2个0,如果在解析一个不足3个字节的文件时,比如2个字节时,共16个字节,组合为6 + 6 + 4, 少了2位,用0补齐,对于还缺少一个6位用=号来进行代替。=号相当于00000000。

 

54. 线程池的核心类是(ThreadPoolExecutor),理解其中几个参数的概念。

55.Actuator是springboot中非常重要的功能,Actuator为开发人员提供了Spring Boot的运行状态信息,通过Actuator可以查看程序的运行状态的信息。(spring应用程序也可以通过shell进行链接使用)

 

56. AnnotationMetaData类主要对Class相关的多个注解进行获取和判断(关注spring中的MetaData)

57. BeanDefinitionRegistry ,该类的作用主要是向注册表中注册 BeanDefinition 实例,完成 注册的过程。

58.Integer中的进行大小对比的时候在[-128,127]之间的数都会判定为相等,因为他们使用的是相同的对象,Integer类中有一个IntegerCache类,该类在jvm初始化时,会将[-128,127]之间的对象都创建出来至于缓存中,在进行对象范围在[-128,127]之间时,会通过Integer.cache中获取对象.(具体查看源码)

59.synchronized关键字提供了一个锁机制,能够确保共享变量之间的互斥访问,防止数据出现不一致的情况,synchronized在jvm中包含2个指令,minitor enter 和 minitor exit,它可以保证在任何时候任何线程执行到minitor enter指令完成之前都必须从主内存(堆)中获取数据(每个线程都有自己独立的内存单元,里面包含线程栈,程序计数器等,每个线程操作变量时会拷贝一份变量到自己的栈中进行数据操作,然后再将结果赋予主存中的变量),而不是在缓存中,在monitor exit指令执行完成后,共享变量被更新后的值必须要刷入到主内存中.synchronized只可对方法和代码块进行修饰,不可对类或者变量进行修饰.

 

60.@import注解:在应用中,有时没有把某个类注入到IOC容器中,但在运用的时候需要获取该类对应的bean,此时就需要用到@Import注解
比如:先创建两个类,不用注解注入到IOC容器中,在应用的时候在导入到当前容器中。 相当于一种懒加载。

 

 

 

 

 

61. SpringBoot整合mybatis后是如何创建sqlsessionfactory 对象的呢,在mybatis-spring-boot-autoconfigure包中的MybatisAutoConfiguration类,他通过@EnableConfigurationProperties注解来实例化MybatisProperties类,并交由spring管理,自身通过spring。factories文件被spring发现通过反射来实例化并交由spring管理,在这里MybatisAutoConfiguration使用了@AutoConfigureAfter注解,注解中的值为DataSourceAutoConfiguration类,这是一个数据源自动配置类,含义就是定义类与类之间的加载顺序,在这里是DataSourceAutoConfiguration会先被加载并实例化完成后,在加载当前类。类创建成功后,因为MybatisAutoConfiguration配置了Configuration注解,因此该实例交由spring容器管理,在该类中的sqlSessionFactory()方法,会实例化SqlSessionFactory(会话工厂),同时在此方法中会创建一个Configuration全局配置对象(在configLocation为空的前提下,configLocation 使用来定位config.xml配置文件的相对路径,可在application.yml中进行配置后,会被spring读取到,这种情况下Configuration对象为空。)供后面sqlsessionfactorybuilder来使用。

 

@Bean
@ConditionalOnMissingBean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
......
factory.getObject();
}

 

 

在这个方法中首先会实例化一个SqlSessionFactoryBean 对象,该对象是mybatis-spring整合包中的类,这个类就是用来创建会话工厂然后将工厂实例交由spring管理的对象,最后该对象会调用一个getObject()f方法,该方法经过一系列的校验,最后会到达buildSqlSessionFactory()这个方法,这个方法是通过mybatis自身自带的构造器,SqlSessionFactoryBuilder构造器来创建,再此方法中,首先会对当前的Configuration对象是否为空进行校验,(Configuration在sqlsessionfactory()方法中已经被实例化了,只不过还没到解析阶段,因此很多参数都为空)在这里做了一个判断,如果configuration对象为空, configLocation不为空的情况下,会创建一个XmlConfigBuilder对象,此对象便是对xml文件进行解析的全局配置解析构造器,它有一个父类为BaseBuilder,这是mybatis解析构造器的基类,请注意,在这里仅仅只是创建了XmlConfigBuilder,但他并未调用自身的parse方法对当前的config.xml配置文件进行解析,如果两者都为空,则spring会默认创建一个configuration对象,然后在application.xml配置的mybatis的相关属性配置到该对象中, 如果是使用config.xml文件做解析的话,configuration对象时在XmlConfigBuilder对象的构造器中创建的,然后对xml文件进行解析完成后的所有属性包装在Configuration对象中,(如果要采用xml解析,我们只需要在application.yml文件中配置2个属性,一个是ConfigLocation,这个使用来解析config.xml文件的,一个是mapperLocation,这个使用来解析*Mapper.xml文件的)如果非xml解析,我们就是采用读取application.xml文件的相关mybatis配置来进行相关属性的注入至configuration 对象中,期间,会创建环境对象Environment,该对象主要是用来识别当前的环境类型,是否为开发环境,生成环境等, 以及用来管理事务和数据源,自此,我们的会话工厂就会被创建成功(这里的会话工厂是mybatis 默认的会话工厂(DefaultSqlSessionFactory))

protected SqlSessionFactory buildSqlSessionFactory() throws Exception {
  ......
    targetConfiguration.setEnvironment(new Environment(this.environment,
    this.transactionFactory == null ? new SpringManagedTransactionFactory() : this.transactionFactory,
    this.dataSource));
  ......
    return this.sqlSessionFactoryBuilder.build(targetConfiguration);
}

现在的我们基本上舍弃了使用xml文件的方式添加mybatis的配置类和使用xml文件来编写sql代码,基本上都是以注解的形式来代替,mybatis中的MapperRegistry中addMapper(Class<T> type)来创建MapperAnnotationBuilder类,然后通过此类来创建来解析*Mapper.xml文件或者解析接口文件中的注解配置,如果在classpath下包含了配置文件信息,则会对其进行解析,



 

 


 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值