关于spring:精讲响应式WebClient第5篇请求超时设置与异常处理

本文是精讲响应式WebClient第5篇,前篇的blog拜访地址如下: 精讲响应式webclient第1篇-响应式非阻塞IO与根底用法精讲响应式WebClient第2篇-GET申请阻塞与非阻塞调用办法详解精讲响应式WebClient第3篇-POST、DELETE、PUT办法应用精讲响应式WebClient第4篇-文件上传与下载本文来为大家介绍一下,当WebClient申请产生异样的时候,该如何解决。为了解说异样解决,咱们须要先制作出异样,所以咱们先为大家介绍:申请超时时长的设置。 一、申请超时时长的设置要想模仿超时异样,咱们首先要晓得超时时长的失常配置渠道是怎么样的。如下文代码所示: ChannelOption.CONNECT_TIMEOUT_MILLIS用来设置连贯超时时长,单位是毫秒ReadTimeoutHandler(5000, TimeUnit.MILLISECONDS)用来设置读数据超时时长,单位是毫秒WriteTimeoutHandler(5000, TimeUnit.MILLISECONDS)用来设置写数据超时时长,单位是毫秒//初始化一个WebClientprivate WebClient getWebClient(){ TcpClient tcpClient = TcpClient .create() .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000) .doOnConnected(connection -> { connection.addHandlerLast(new ReadTimeoutHandler(5000, TimeUnit.MILLISECONDS)); connection.addHandlerLast(new WriteTimeoutHandler(5000, TimeUnit.MILLISECONDS)); }); return WebClient.builder() .baseUrl("http://jsonplaceholder.typicode.com") .clientConnector(new ReactorClientHttpConnector(HttpClient.from(tcpClient))) .build();}当咱们把连贯超时时长设置为5(毫秒)的时候,则连贯必定会超时。轻易发送一个申请,超时之后会抛出ConnectTimeoutException 当咱们把读数据超市时长设置为5(毫秒)的时候,则数据读操作必定会超时。轻易发送一个申请,超时之后会抛出ReadTimeoutException 二、解决特定的异样上面咱们就以ConnectTimeoutException为例,进行异样解决 //制作异样,将超时工夫设置为5毫秒.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5)而后执行上面的GET申请,上文WebClient的baseurl为:"http://jsonplaceholder.typicode.com" ,该网站是一个收费提供HTTP服务端测试的网站。 @Testpublic void testSimple() throws Exception { Mono<String> mono = getWebClient() .get() // 发送GET 申请 .uri("/posts/1") //服务申请门路,基于baseurl .retrieve() // 获取响应体 .bodyToMono(String.class) //响应数据类型转换 //进行异样解决 .doOnError(ConnectTimeoutException.class, err -> { System.out.println("产生谬误:" +err.getMessage() ); }); System.out.println(mono.block());}上文中的doOnError是咱们本节为大家介绍的异样解决办法,用于解决ConnectTimeoutException,输入后果如下: ...

August 24, 2020 · 1 min · jiezi

关于spring:Spring里componentscan的工作原理

In Spring configuration xml file, we can define a package for tag component-scan, which tells Spring framework to search all classes within this specified package, to look for those classes which are annotated with @Named or @Component. I am very curious about how Spring framework achieves this scan, so I have made some debugging to figure it out. In this blog How to find the exact location where bean configuration file is parsed in Spring framework I have already found the location where the xml configuration file is parsed by Spring framework, so I can directly set breakpoint in found source code.Here the package to be scanned is parsed from xml file: ...

August 23, 2020 · 2 min · jiezi

关于spring:Spring框架里解析配置文件的准确位置

We can define bean configuration in xml and then can get instantiated bean instance with help of all kinds of containers for example ClassPathXmlApplicationContext as displayed below: The content of Beans.xml: <?xml version="1.0" encoding="UTF-8"?><!-- http://stackoverflow.com/questions/18802982/no-declaration-can-be-found-for-element-contextannotation-config --><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"> <bean id="helloWorld" class="main.java.com.sap.HelloWorld"> <property name="message" value="sss"/> <property name="testMin" value="2"/> <property name="phone" value="1"/> </bean></beans>Where can we set breakpoint to start? No hint. Here is a tip: we can make the Beans.xml invalid by deliberately changing te tag bean to beana, and relaunch application. Now exception is raised as expected: Click the hyperlink XmlBeanDefinitionReader.java:399, ...

August 23, 2020 · 1 min · jiezi

关于spring:精讲响应式WebClient第4篇文件上传与下载

本文是精讲响应式WebClient第4篇,前篇的blog拜访地址如下: 精讲响应式webclient第1篇-响应式非阻塞IO与根底用法精讲响应式WebClient第2篇-GET申请阻塞与非阻塞调用办法详解精讲响应式WebClient第3篇-POST、DELETE、PUT办法应用WebClient是从Spring 5开始提供的一个HTTP客户端库,为了应用WebClient进行文件上传和下载,须要咱们先编写服务端的反对文件上传和下载的程序。请参考我之前写的一篇文章:SpringBoot实现本地存储文件上传及提供HTTP拜访服务。依照此文实现学习之后,能够取得 一个以拜访服务URI为"/upload”的文件上传服务端点服务端点上传文件胜利后会返回一个HTTP连贯,能够用来下载文件。上面咱们就开始学习应用WebClient是HTTP客户端库,进行文件的上传与下载。 一、文件上传在本地8888端口搭建了一个文件上传接管的服务端,服务端点为“/upload”。上传本地磁盘中的一个文件"D:\data\local\splash.png" @SpringBootTestclass UpDownLoadTests { //创立webClient private WebClient webClient = WebClient.builder() .baseUrl("http://localhost:8888/") .build(); @Test void testUpload() { // 待上传的文件(存在客户端本地磁盘) String filePath = "D:\\data\\local\\splash.png"; // 封装申请参数 FileSystemResource resource = new FileSystemResource(new File(filePath)); MultiValueMap<String, Object> param = new LinkedMultiValueMap<>(); param.add("uploadFile", resource); //服务端MultipartFile uploadFile //param.add("param1", "test"); //服务端如果承受额定参数,能够传递 // 发送申请 Mono<String> mono = webClient .post() // POST 申请 .uri("/upload") // 申请门路 .contentType(MediaType.APPLICATION_FORM_URLENCODED) .body(BodyInserters.fromMultipartData(param)) .retrieve() // 获取响应体 .bodyToMono(String.class); //响应数据类型转换 // 输入后果 System.out.println(mono.block()); }}输入打印后果如下: ...

August 23, 2020 · 1 min · jiezi

关于spring:如何判断字符串为空

java中有多种判断String对象思否为空的办法,本文来梳理一下. java原生办法在java原生的语法中,String对象有一个API是isEmpty(),该办法会判断String对象是否为空,这里的isEmpty()齐全等同于String.length()==0, 然而如果这是你的String对象是null呢?--String.isEmpty()就会报空指针异样; 所以从平安方面来思考的话,在java原生办法中能够用String==null||String.isEmpty()来判断. 工具类判断办法org.apache.commons.lang3一种是org.apache.commons.lang3包下的 StringUtils.isEmpty(CharSequence cs); //org.apache.commons.lang3包下的StringUtils类,判断是否为空的办法参数是字符序列类,也就是String类型能够点进底层看一下源码: public static boolean isEmpty(final CharSequence cs) { return cs == null || cs.length() == 0;}org.springframework.util另一种是org.springframework.util包下的 StringUtils.isEmpty(Object str); //而org.springframework.util包下的参数是Object类,也就是不仅仅能判断String类型,还能判断其余类型,比方Long等类型能够点进底层看一下源码: public static boolean isEmpty(Object str) { return (str == null || "".equals(str));}从判断为空参数的范畴以及底层的判断根据,咱们能够看到基本上判断对象是否为空,StringUtils.isEmpty(Object str)这个办法都能搞定,并且判断的范畴更广. 所以咱们平时应用org.springframework.util包下的StringUtils.isEmpty()就能够.

August 22, 2020 · 1 min · jiezi

关于spring:精讲响应式WebClient第3篇POSTDELETEPUT方法使用

本文是精讲响应式WebClient第3篇,前篇的blog拜访地址如下: 精讲响应式webclient第1篇-响应式非阻塞IO与根底用法精讲响应式WebClient第2篇-GET申请阻塞与非阻塞调用办法详解一、RESTful格调与HTTP method相熟RESTful格调的敌人,应该理解RESTful格调API应用HTTP method表白对资源的操作。 罕用HTTP办法RESTful格调语义(操作)GET查问、获取数据POST新增、提交数据DELETE删除数据PUT更新、批改数据在上一篇文章中咱们曾经为大家介绍了如何应用WebClient作为Http客户端发送GET申请与进行响应后果的接管。本节来为大家介绍POST、DELETE、PUT。 POST等其余的办法在与GET办法在应用如下办法的时候是统一的: block()阻塞获取响应后果的办法,subscribe()非阻塞异步后果订阅办法retrieve()获取HTTP响应体,exchange()除了获取HTTP响应体,还能够获取HTTP 状态码、headers、cookies等HTTP报文信息。应用Mono接管单个对象的响应后果,应用Flux接管汇合类对象的响应后果。占位符语法传参形式所以想理解以上信息,请去参考: 精讲响应式WebClient第2篇-GET申请阻塞与非阻塞调用办法详解。 本文只介绍POST、DELETE、PUT在应用过程中与GET不一样的中央。 为了不便后续开发测试,首先介绍一个网站给大家。JSONPlaceholder是一个提供收费的在线REST API的网站,咱们在开发时能够应用它提供的url地址测试下网络申请以及申请参数。或者当咱们程序须要获取一些模仿数据、模仿图片时也能够应用它。二、Post申请发送JSON字符串、对象、表单数据2.1.应用Post办法向服务端发送JSON字符串数据public class OtherTest { //创立webClient private WebClient webClient = WebClient.builder() .baseUrl("http://jsonplaceholder.typicode.com") .build(); @Test public void testPostJsonStr() { // 提交给服务端的JSON字符串 String jsonStr = "{\"userId\": 1,\"title\": \"zimugtest\",\"body\": \"字母哥进行测试\"}"; // 发送申请 Mono<String> mono = webClient .post() // POST 申请 .uri("/posts") // 申请门路 .contentType(MediaType.APPLICATION_JSON) //JSON数据类型 .body(BodyInserters.fromValue(jsonStr)) //JSON字符串数据 .retrieve() // 获取响应体 .bodyToMono(String.class); //响应数据类型转换 // 输入后果 System.out.println(mono.block()); }}响应后果打印如下,"http://jsonplaceholder.typicode.com/posts/1" 服务的申请数据就是响应数据。响应后果同样是一个JSON字符串: 2.2.将对象以JSON数据模式发送服务端 @Test public void testPostJson() { //构建申请发送对象 PostDTO postDTO = new PostDTO(); postDTO.setUserId(110); postDTO.setTitle("zimug-test"); postDTO.setBody("字母哥进行Post测试"); //发送申请 Mono<PostDTO> mono = webClient .post() // 发送POST 申请 .uri("/posts") //服务申请门路,基于baseurl .contentType(MediaType.APPLICATION_JSON) //以JSON数据格式 .bodyValue(postDTO) //发送申请体,对象模式 .retrieve() // 获取响应体 .bodyToMono(PostDTO.class); //响应数据类型转换 // 输入后果 System.out.println("=====" + mono.block()); }响应后果打印如下,应用PostDTO接管响应后果。因为 "http://jsonplaceholder.typicode.com/posts/1" 服务的申请数据就是响应数据。打印后果是PostDTO对象的toString()办法 ...

August 22, 2020 · 1 min · jiezi

关于spring:关于AOP思想建议你看看这份五年开发总结的笔记写的太详细了

前言OOP(Object Oriented Programing)面向对象编程 以对象为根本单位进行程序开发,通过对象间的彼此协同,互相协调,实现程序的构建 POP(Producer Oriented Programing)面向过程(办法,函数)编程 以过程为根本单位的程序开发,通过彼此间协同,互相调用,实现程序的构建 动态代理存在的问题//实现雷同的接口public class UserServiceProxy implements UserService { //创立原始对象 private UserServiceImpl userService = new UserServiceImpl(); public void register(User user) { //实现额定性能 System.out.println("-------------------"); userService.register(user); } public boolean login(String name, String password) { System.out.println("____________________"); return userService.login(name,password); }}每一个原始类都会手工编写一个代理类 动态类文件数目过多,不利于项目管理代码可维护性差概述 上图展现了一个被划分的典型利用,每个模块的外围性能都是为特定业务畛域提供服务,然而这些模块都须要相似的辅助性能,例如平安和事务管理。 如果要重用通用性能的话,最常见的面向对象技术是继承或者委托。然而,如果在整个利用中都应用雷同的基类,继承往往会导致一个软弱的对象体系,而应用委托可能须要对委托对象进行简单的调用。 切面提供了取代继承和委托的另一种可选计划,而且在很多场景下更清晰简洁,在应用面向切面编程时,咱们依然在一个中央定义通用性能,然而能够通过申明的形式定义这个性能要以何种形式在何处利用,而无需批改受影响的类,横切关注点模块化为非凡的类,这些类被称为切面(aspect)。这样做有两个益处:首先,当初每个关注点都集中在一个中央,而不是扩散到多处代码;其次,服务模块更简洁,因为它们只蕴含次要关注点(或者外围性能)的代码,而主要关注点的代码被移转到切面中了。 AOP不可能取代 OOP,它只是OOP的无意补充Spring中的AOPAOP:实质上就是 Spring动静代理开发,有益于原始类的保护Spring AOP中的动静代理次要有两种形式,JDK动静代理和CGLIB动静代理。JDK动静代理通过反射来接管被代理的类,并且要求被代理的类必须实现一个接口。JDK动静代理的外围是InvocationHandler接口和Proxy类。 如果指标类没有实现接口,那么Spring AOP会抉择应用CGLIB来动静代理指标类。CGLIB(Code Generation Library),是一个代码生成的类库,能够在运行时动静的生成某个类的子类,留神,CGLIB是通过继承的形式做的动静代理,因而如果某个类被标记为final,那么它是无奈应用CGLIB做动静代理的,诸如private的办法也是不能够作为切面的。 JDK动静代理的实现代理创立三要素:1 原始对象 2 额定性能 3 代理对象实现雷同的接口 JDK动静代理的外围是InvocationHandler接口和Proxy类。 public static void main(String[] args) { //创立原始对象 UserService userService = new UserServiceImpl(); //JDK创立动静代理 Proxy.newProxyInstance(ClassLoader ,interfaces, invocationHandler)}public interface InvocationHandler { //用于书写额定性能 额定性能:原始办法执行前后 抛出异样 // 参数:Proxy 疏忽掉,示意的是代理对象 //method 额定性能所减少给的那个原始办法 //Object[] args 原始办法的参数 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;}interfaces:原始对象所实现的接口userService.getClass().getInterfaces() ...

August 21, 2020 · 2 min · jiezi

关于spring:精讲响应式WebClient第2篇GET请求阻塞与非阻塞调用方法详解

本文是精讲响应式WebClient第2篇,前篇的blog拜访地址如下: 精讲响应式webclient第1篇-响应式非阻塞IO与根底用法在上一篇文章为大家介绍了响应式IO模型和WebClient的根本用法。本节来持续深刻的为大家介绍:如何应用WebClient作为Http客户端发送GET申请与进行响应后果的接管。 一、block()阻塞式获取响应后果WebClient客户端既反对同步异步、阻塞与非阻塞IO,咱们先来为大家介绍一下同步阻塞式的编程形式。即:在申请发送之后应用block()办法,阻塞以后线程期待获取响应后果。 1.1.应用Mono接管单个对象创立测试用例,成员变量WebClient,以 "http://jsonplaceholder.typicode.com" 为拜访服务根底门路,该网站是一个收费提供RESTful API进行接口测试的一个网站。 public class GetTest { //创立webClient private WebClient webClient = WebClient.builder() .baseUrl("http://jsonplaceholder.typicode.com") .build(); @Test public void testMono() { Mono<PostDTO> mono = webClient .get() // 发送GET 申请 .uri("/posts/1") //服务申请门路,基于baseurl .retrieve() // 获取响应体 .bodyToMono(PostDTO.class); //响应数据类型转换 System.out.println(mono.block()); }}get() 办法示意应用HTTP GET methoduri() 指定服务接口门路,以baseurl为根底retrieve() 获取响应体,即HTTP bodybodyToMono()将响应体转换为一个对象,Mono英文是单声道、单体的意思,用于接管单个对象通过浏览器拜访 "http://jsonplaceholder.typicode.com/posts/1" 失去JSON响应后果,和咱们通过程序打印出的响应后果数据内容统一。程序控制台截图如下: 接管响应后果的java POJO实体对象如下: import lombok.Data;@Datapublic class PostDTO { private int userId; private int id; private String title; private String body;}1.2.应用Flux接管汇合对象拜访http://jsonplaceholder.typicode.com/posts 能够取得JSON数组形式的申请后果如图(一共100条我截图截取3条记录): ...

August 21, 2020 · 2 min · jiezi

关于spring:Spring事务原理

编程事务 给ORM框架用的两头判断是否有连贯的层它为什么能实现平安线程平安重点一 事务切面

August 20, 2020 · 1 min · jiezi

关于spring:精讲响应式webclient第1篇响应式非阻塞IO与基础用法

笔者在之前曾经写了一系列的对于RestTemplate的文章,如下: 精讲RestTemplate第1篇-在Spring或非Spring环境下如何应用精讲RestTemplate第2篇-多种底层HTTP客户端类库的切换精讲RestTemplate第3篇-GET申请应用办法详解精讲RestTemplate第4篇-POST申请办法应用详解精讲RestTemplate第5篇-DELETE、PUT等申请办法应用详解精讲RestTemplate第6篇-文件上传下载与大文件流式下载精讲RestTemplate第7篇-自定义申请失败异样解决精讲RestTemplate第8篇-申请失败主动重试机制精讲RestTemplate第9篇-如何通过HTTP Basic Auth认证精讲RestTemplate第10篇-应用代理作为跳板发送申请RestTemplate作为spring-web我的项目的一部分,在Spring 3.0版本开始被引入。依据Spring官网文档及源码中的介绍,RestTemplate在未来的版本中它可能会被弃用, 作为代替,Spring官网已在Spring 5中引入了WebClient作为非阻塞式Reactive HTTP客户端。 一、什么是响应式非阻塞IO在开始为大家介绍webClient之前有必要为大家介绍一下响应式非阻塞IO与传统IO之前的区别。咱们先留下一个问题:webClient发送与接管单个HTTP申请比RestTemplate更快么?答案是否定的。 看到这里有的同学曾经蒙了,既然webClient没有更快,那官网为什么还举荐应用它?听我往下讲。 1.1.传统阻塞式IO模型笔者用绝对艰深的话为大家阐明一下阻塞IO与非阻塞IO之间的区别。咱们以软件开发团队的工作形式来做一个比喻。作为软件开发人员,咱们必定晓得软件开发的根本流程: 我的项目立项与可行性研究需要剖析与设计代码开发迭代测试上线及配置管理、运维 在以Spring MVC或者struct为代表的框架都是基于sevlet的,其底层IO模型是阻塞IO模型。这种模型就如同你是公司的一个开发人员,下面的所有的5项工作全都由你一个人实现。如果公司有10集体,最多就只能同时进行10个需要。客户需要增多了也没有方法,只能让他们等着。如下图:一个申请占用一个线程,当线程池内的线程都被占用后新来的申请就只能期待。 1.2.响应式IO模型spring 社区为了解决Spring MVC的阻塞模型在高并发场景下的性能瓶颈的问题,推出了Spring WebFlux,WebFlux底层实现是久经考验的netty非阻塞IO通信框架。该框架的申请解决与线程交互关系图如下: boosGroup用于Accetpt连贯建设事件并散发申请, workerGroup用于解决I/O读写事件。netty我就不细说了,还是用艰深的形式给大家讲一下:如果艰深的将上图中的各个工作池、线程池的组合比做一个软件开发公司,那么: 我的项目立项及可研,由公司项目经理及参谋来实现需要剖析与设计,由产品经理和架构师来实现代码研发,由项目经理率领开发人员来实现迭代测试,由测试团队来实现上线及配置管理、运维,可能由专门的devops团队来实现这样一个公司内的所有人实现分工,就能在无限的资源的状况下,去接触更多的客户,谈更多的需要,正当的调配人力资源,达到并发解决能力最大化的极限程度。相比于一个员工从头到位的负责一个我的项目,它的组织性更强,分工更明确,正当的利用闲暇资源,业余的人最业余的事。 这种人力资源的正当利用及组织形式和非阻塞IO模型有殊途同归之处,通过正当的将申请解决线程及工作进行分类,正当的利用零碎的内存、CPU资源,达到单位工夫内解决能力的最大化就是异步非阻塞IO的外围用意! 回到上文给大家留下的问题,webClient解决单个HTTP申请的响应时长并不比RestTemplate更快,然而它解决并发的能力更强。所以响应式非阻塞IO模型的外围意义在于:进步了单位工夫内无限资源下的服务申请的并发解决能力,而不是缩短了单个服务申请的响应时长。 二、WebClient 的劣势上文为大家介绍完IO模型之后,我想大家曾经能够明确了。与RestTemplate相比,WebClient劣势如下: 非阻塞响应式IO,单位工夫内无限资源下反对更高的并发量反对应用Java 8 lambda表达式函数同时反对同步、异步与Streaming流式传输场景三、我的项目引入WebClient应用WebClient须要引入如下的Jar(能够在蕴含spring-boot-starter-web的Spring Boot我的项目中引入) <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId></dependency>那么问题又来了,相熟Spring 开发的敌人应该都晓得。spring-boot-starter-webflux和spring-boot-starter-web代表的是两套技术栈 spring-boot-starter-web能够实现目前比拟成熟的基于servlet技术栈的Spring Boot利用spring-boot-starter-webflux能够实现的是底层基于netty的响应式编程的技术栈的Spring Boot利用二者能够共存么?答案是: 作为服务端实现Spring Boot利用而言,二者在利用角度当然是不能共存的。截止20200820我写稿的工夫,如果在一个我的项目外面将二者都引入了,开发服务端利用其实应用的还是spring-boot-starter-web的基于servlet的技术栈。作为HTTP客户端而言,如果咱们只是要应用WebClient。无论怎样,引入spring-boot-starter-webflux就对了。四、WebClient 实例创立与根底用法创立WebClient有如下三种形式,咱们来一一为大家介绍。 WebClient.create()WebClient.create(String baseUrl):指定了baseUrl,应用该客户端发送申请都基于baseUrlWebClient.builder()返回一个WebClient.Builder,该对象能够做链式调用,传递更多的参数。为了不便后续开发测试,首先介绍一个网站给大家。JSONPlaceholder是一个提供收费的在线REST API的网站,咱们在开发时能够应用它提供的url地址测试下网络申请以及申请参数。或者当咱们程序须要获取一些模仿数据、模仿图片时也能够应用它。4.1. WebClient.create()创立WebClient发送GET申请,接管String类型单个Mono对象(Mono英文:单声道、单体)。 public class SimpleTest { @Test void testSimple() { WebClient webClient = WebClient.create(); Mono<String> mono = webClient .get() // 发送GET 申请 .uri("http://jsonplaceholder.typicode.com/posts/1") // 申请门路 .retrieve() // 获取响应后果 .bodyToMono(String.class); //响应数据类型转换 System.out.println("=====" + mono.block()); }}mono.block()办法依然是阻塞式的数据响应接管形式,响应式的编程办法咱们前面文章会为大家介绍。 ...

August 20, 2020 · 1 min · jiezi

关于spring:Spring-水滴石穿四-工厂实现之bean工厂接口-ConfigurableListableBeanFactory

概述这个接口提供了DefaultListableBeanFactory的许多性能,本节次要剖析这个接口提供的性能,实现前面在剖析,先看其接口加强体系。 接口体系能够看到这里除了继承咱们第二节中提到的三大工厂接口外,还继承了一个单例注册接口和可配置的工厂接口,咱们接下来先看看这俩个接口提供了什么性能 SingletonBeanRegistry这个接口正如其名,提供单例的治理性能,包含注册,获取等性能 public interface SingletonBeanRegistry { //注册单例 void registerSingleton(String beanName, Object singletonObject); //获取单例 @Nullable Object getSingleton(String beanName); //校验是否存在单例 boolean containsSingleton(String beanName); //获取所有单例名 String[] getSingletonNames(); //获取所有单例的数目 int getSingletonCount(); //返回一个单例互斥对象 Object getSingletonMutex();ConfigurableBeanFactory这个接口就是加强bean工厂的可配置能力,具体看正文 public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, SingletonBeanRegistry { //范畴标识符,能够调用registerScope办法减少 String SCOPE_SINGLETON = "singleton"; String SCOPE_PROTOTYPE = "prototype"; //设置父工厂 void setParentBeanFactory(BeanFactory parentBeanFactory) throws IllegalStateException; //设置和获取bean的类加载器 void setBeanClassLoader(@Nullable ClassLoader beanClassLoader); @Nullable ClassLoader getBeanClassLoader(); //设置和获取一个长期类加载器 void setTempClassLoader(@Nullable ClassLoader tempClassLoader); @Nullable ClassLoader getTempClassLoader(); //设置和获取是否缓存bean的元数据 void setCacheBeanMetadata(boolean cacheBeanMetadata); boolean isCacheBeanMetadata(); //设置和获取bean定义的解析策略 void setBeanExpressionResolver(@Nullable BeanExpressionResolver resolver); @Nullable BeanExpressionResolver getBeanExpressionResolver(); //spring 3.0提供的新性能 设置和获取转换服务解决属性值,能够作为属性编辑器的一个代替 void setConversionService(@Nullable ConversionService conversionService); @Nullable ConversionService getConversionService(); //减少一个自定义属性处理器工厂,这个办法防止了同步,举荐应用 void addPropertyEditorRegistrar(PropertyEditorRegistrar registrar); //注册一个自定义属性处理器来解决指定类型的属性,留神这个自定义属性处理器是共用的,因而须要应用同步关键字保障线程平安,为了防止同步能够应用addPropertyEditorRegistrar办法 void registerCustomEditor(Class<?> requiredType, Class<? extends PropertyEditor> propertyEditorClass); //用曾经注册的属性处理器初始化属性处理器工厂 void copyRegisteredEditorsTo(PropertyEditorRegistry registry); //设置一个类型转化器解决属性值,这会重写默认的属性处理器机制 void setTypeConverter(TypeConverter typeConverter); //获取类型转换器,这个通常不是线程平安的,如果默认的属性处理器机制被激活,个别返回的这个类型转换器会唤醒所有曾经注册的属性处理器 TypeConverter getTypeConverter(); //减少一个string解析器来解决内嵌值,比方注解属性 void addEmbeddedValueResolver(StringValueResolver valueResolver); boolean hasEmbeddedValueResolver(); @Nullable String resolveEmbeddedValue(String value); //减少一个bean后置处理器,在bean创立时将以它们注册时候的顺序调用 void addBeanPostProcessor(BeanPostProcessor beanPostProcessor); int getBeanPostProcessorCount(); //注册范畴,还记得默认的单例和原型范畴吗? void registerScope(String scopeName, Scope scope); String[] getRegisteredScopeNames(); @Nullable Scope getRegisteredScope(String scopeName); //提供一个平安拜访上下文 AccessControlContext getAccessControlContext(); //从其余bean工厂 copy配置来初始化本人 void copyConfigurationFrom(ConfigurableBeanFactory otherFactory); //注册别名,能够运行时调用,因而须要同步 void registerAlias(String beanName, String alias) throws BeanDefinitionStoreException; //应用指定的string解析器解决别名 void resolveAliases(StringValueResolver valueResolver); //合并bean定义,因为咱们是父子工厂,所以必要的时候须要合并 BeanDefinition getMergedBeanDefinition(String beanName) throws NoSuchBeanDefinitionException; //校验是否是个工厂bean boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException; //设置bean正在创立的状态,只限于容器外部应用 void setCurrentlyInCreation(String beanName, boolean inCreation); boolean isCurrentlyInCreation(String beanName); //注册依赖的bean void registerDependentBean(String beanName, String dependentBeanName); //获取依赖指定bean的所有bean String[] getDependentBeans(String beanName); //获取指定bean的所有依赖bean,留神与下面的区别 String[] getDependenciesForBean(String beanName); //销毁给定的bean,通常是原型bean void destroyBean(String beanName, Object beanInstance); void destroyScopedBean(String beanName); //销毁所有的单例,个别是容器敞开时调用 void destroySingletons();}

August 19, 2020 · 1 min · jiezi

关于spring:Spring-水滴石穿三-工厂实现之bean定义注册BeanDefinitionRegistry

BeanDefinitionRegistry接口这个接口扩大了上文提到的别名注册接口,提供了bean定义的注册,登记等性能 public interface BeanDefinitionRegistry extends AliasRegistry { //注册bean定义,可能抛出异样 void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException; //登记bean定义,可能抛出异样 void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException; //获取bean定义 BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException; //是否蕴含bean定义 boolean containsBeanDefinition(String beanName); //获取所有bean定义的名字 String[] getBeanDefinitionNames(); //返回bean定义的总数 int getBeanDefinitionCount(); //是否给定的bean在应用了 boolean isBeanNameInUse(String beanName);}DefaultListableBeanFactory实现尽管还有一些别的实现,但咱们beanFactory的剖析整个都是基于DefaultListableBeanFactory的继承体系来剖析的,能够看到这个类间接实现了咱们的bean定义注册接口,上面剖析它的相干实现 与bean定义无关的属性private volatile List<String> beanDefinitionNames = new ArrayList<>(256);private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);registerBeanDefinitionpublic void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { if (beanDefinition instanceof AbstractBeanDefinition) { try { //验证bean定义 ((AbstractBeanDefinition) beanDefinition).validate(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", ex); } } BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName); if (existingDefinition != null) { //是否容许bean定义重写是能够配置的 if (!isAllowBeanDefinitionOverriding()) { throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition); } this.beanDefinitionMap.put(beanName, beanDefinition); } else { //是否曾经创立了bean if (hasBeanCreationStarted()) { // Cannot modify startup-time collection elements anymore (for stable iteration) synchronized (this.beanDefinitionMap) { this.beanDefinitionMap.put(beanName, beanDefinition); List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1); updatedDefinitions.addAll(this.beanDefinitionNames); updatedDefinitions.add(beanName); this.beanDefinitionNames = updatedDefinitions; removeManualSingletonName(beanName); } } else { // Still in startup registration phase this.beanDefinitionMap.put(beanName, beanDefinition); this.beanDefinitionNames.add(beanName); //移除手动单例名字,将注册的bean定义优先级更高 removeManualSingletonName(beanName); } //无论如何,冻结已解冻的bean定义 this.frozenBeanDefinitionNames = null; } //如果原本就存在bean定义,或者这个bean曾经处于创立中了,须要重置bean定义 if (existingDefinition != null || containsSingleton(beanName)) { resetBeanDefinition(beanName); } else if (isConfigurationFrozen()) { clearByTypeCache(); } }有几个要留神的中央1.((AbstractBeanDefinition) beanDefinition).validate() ...

August 19, 2020 · 2 min · jiezi

关于spring:Angular自定义管道pipes过滤器

一、状态类型转对象的特定值1、自定义管道过滤器StatusFilterPipe.tsimport { Pipe, PipeTransform } from '@angular/core';export class PipeVo { value: string; label: string;}@Pipe({ name: 'statusFilter', pure: false})export class StatusFilterPipe implements PipeTransform { transform(items: string, filter: PipeVo[]): any { if ((items !== '0' && !items) || !filter) { return items; } for (const one of filter){ if (items === one.value || one.value.toString() === items.toString()){ return one.label; } } return '未知'; }}2、在shared.module.ts中将编写的过滤器共享进来const DIRECTIVES = [ StatusFilterPipe, ReplaceFilterPipe, DebounceInputDirective // input防抖];@NgModule({ declarations: [ // your components ...COMPONENTS, ...DIRECTIVES, ...WIDGETS ],})3、应用<sv label="操作记录" col="2">{{selectedLog.operatorType | statusFilter: dic_sys_log_type_operator_options}}</sv>阐明: ...

August 19, 2020 · 1 min · jiezi

关于spring:LinkedBlockingQueue-和-ConcurrentLinkedQueue的区别

1. 简略的开篇LinkedBlockingQueue 和 ConcurrentLinkedQueue 是 Java 高并发场景中最常应用的队列。只管这两个队列常常被用作并发场景的数据结构,但它们之间仍有轻微的特色和行为差别。在这篇文章中,我将和大家一起探讨这两者之间的异同点。欢送大家在留言探讨~ 2. LinkedBlockingQueue首先 LinkedBlockingQueue 是一个 “可选且有界” 的阻塞队列实现,你能够依据须要指定队列的大小。接下来,我将创立一个LinkedBlockingQueue,它最多能够蕴含100个元素: BlockingQueue<Integer> boundedQueue = new LinkedBlockingQueue<>(100);当然,咱们也能够通过不指定大小,来创立一个无界的 LinkedBlockingQueue: BlockingQueue<Integer> unboundedQueue = new LinkedBlockingQueue<>();无界队列示意在创立时未指定队列的大小。因而,队列能够随着元素的增加而动静增长。然而,如果没有残余内存,则队列将抛出 java.lang.OutOfMemory 谬误。 这里留下一个问题给大家思考: 创立无界队列是好还是坏呢? 咱们还能够从现有的汇合来创立 LinkedBlockingQueue: Collection<Integer> listOfNumbers = Arrays.asList(1,2,3,4,5);BlockingQueue<Integer> queue = new LinkedBlockingQueue<>(listOfNumbers);LinkedBlockingQueue 实现了BlockingQueue接口,该接口为它提供了阻塞性质。 阻塞队列示意如果拜访线程已满(当队列有界时)或变为空,则队列将阻塞该线程。如果队列已满,则增加新元素将阻塞拜访线程,除非新元素有可用空间。相似地,如果队列为空,则拜访元素会阻塞调用线程: ExecutorService executorService = Executors.newFixedThreadPool(1);LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue<>();executorService.submit(() -> {  try {    queue.take();  }   catch (InterruptedException e) {    // exception handling  }});在下面的代码片段中,咱们正在拜访一个空队列。因而,take() 办法阻塞调用线程。 LinkedBlockingQueue 的阻塞个性与一些开销相干。这个代价是因为每个put或take操作在生产者线程或使用者线程之间都是锁争用的。因而,在许多生产者和消费者的状况下,put和take 动作可能会慢一些。 3. ConcurrentLinkedQueue首先申明,ConcurrentLinkedQueue 是一个无边界、线程平安且无阻塞的队列 创立一个空的 ConcurrentLinkedQueue: ...

August 19, 2020 · 1 min · jiezi

关于spring:总是说spring难学来看完这些spring的注解及其解释真香

前言用过spring的人都晓得,spring简略的通过注解就能够实现很多事件,但这些货色是如何实现的呢以及如何利用到咱们本人的代码中?接下来,让咱们一起开启注解的旅程。 1. @Controller标识一个该类是Spring MVC controller处理器,用来创立解决http申请的对象. @Controllerpublic class TestController { @RequestMapping("/test") public String test(Map<String,Object> map){ return "hello"; }}2. @Component、@Repository、@Service、@Controller作用等价雷同的区别:如果 Web 应用程序采纳了经典的三层分层构造的话,最好在长久层、业务层和管制层别离采纳 @Repository、@Service 和 @Controller 对分层中的类进行正文,而用 @Component 对那些比拟中立的类进行正文。 用来拆卸bean,次要用于标注业务层组件,通过注解的形式将该类退出到spring 中进行治理。 @Servicepublic interface UserService { User login(String username,String password); }//当把注解写在接口上时,spring容器会注入失败。//注解写在类上 注入不会失败。@Servicepublic class UserServiceImpl implements UserService{ @Autowired private UserMapper userMapper;}@Controller@RequestMapping("user")public class UserController { @Autowired private UserService userService}3. @Autowired用来拆卸bean,能够写在字段上,也能够写在办法上。默认状况下必须要求依赖对象必须存在,如果要容许null值,能够设置它的required属性为false,例如:@Autowired(required=false) 4. @RequestMapping类定义处:提供初步的申请映射信息,绝对于 WEB 利用的根目录。办法处:提供进一步的细分映射信息,绝对于类定义处的 URL。说白了,就是例如(“user”)网站上拜访localhost:8080/user.html就能够拜访这个办法和html页面。 5. @RequestParam用于将申请参数区数据映射到性能解决办法的参数上例如: public Resp test(@RequestParam Integer id){ return Resp.success(customerInfoService.fetch(id));}这个id就是要接管从接口传递过去的参数id的值的,如果接口传递过去的参数名和你接管的不统一,也能够如下: ...

August 19, 2020 · 2 min · jiezi

关于spring:厉害这份阿里面试官-甩出的Spring源码笔记GitHub上已经爆火

前言时至今日,Spring 在 Java 生态系统与待业市场上,面试出镜率之高,投产规模之广,无出其右。随着技术的倒退,Spring 从来日的 IoC 框架,已倒退成 Cloud Native 基础设施,衍生出大量 Spring 技术栈,如大家熟知的 Spring Boot、Spring Cloud 和 Spring Security 等。毋庸置疑,Spring 早已成为 Java 后端开发事实上的行业标准,有数的公司抉择 Spring 作为根底的开发框架,大部分Java 后端程序员在日常工作中也会接触到 Spring ,因而,如何用好 Spring ,也就成为 Java 程序员的必修课之一!明天,咱们要分享的就是阿里面试官丢进去的Spring源码笔记,这份笔记在GitHub上热度曾经标星81.6k了,由此可见这份笔记对同行们的重要性,也意味着的确给咱们的技术带来很大的晋升! 上面将这份文档的内容以图片的模式展示进去,但篇幅无限只能展现局部,如果你须要“高清残缺的pdf版”,能够关注我的公众号:前程有光即可收费支付。 一、spring概述Spring 简介Spring 倒退历程Spring 的劣势Spring 的核⼼构造Spring 框架版本 二、核心思想什么是IoC?什么是AOPAOP在解决什么问题 三、⼿写实现 IoC 和 AOP银⾏转账案例界⾯银⾏转账案例表构造银⾏转账案例代码调⽤关系银⾏转账案例要害代码银⾏转账案例代码问题剖析问题解决思路案例代码革新 四、 Spring IOC 应⽤Spring IoC根底BeanFactory与ApplicationContext区别FactoryBean 和 BeanFactorylazy-Init 提早加载Spring IOC⾼级个性 五、 Spring IOC源码深度分析Spring IoC容器初始化主体流程Spring IoC的容器体系Bean⽣命周期要害机会点Spring IoC容器初始化主流程BeanFactory创立流程 六、Spring AOP 应⽤AOP 相干术语Spring中AOP的代理抉择Spring中AOP的配置⽅式Spring中AOP实现XML 模式 七、 Spring AOP源码深度分析代理对象创立流程Spring申明式事务管制加载事务管制组件 ...

August 18, 2020 · 1 min · jiezi

关于spring:精讲RestTemplate第10篇使用代理作为跳板发送请求

本文是精讲RestTemplate第10篇,前篇的blog拜访地址如下: 精讲RestTemplate第1篇-在Spring或非Spring环境下如何应用精讲RestTemplate第2篇-多种底层HTTP客户端类库的切换精讲RestTemplate第3篇-GET申请应用办法详解精讲RestTemplate第4篇-POST申请办法应用详解精讲RestTemplate第5篇-DELETE、PUT等申请办法应用详解精讲RestTemplate第6篇-文件上传下载与大文件流式下载精讲RestTemplate第7篇-自定义申请失败异样解决精讲RestTemplate第8篇-申请失败主动重试机制精讲RestTemplate第9篇-如何通过HTTP Basic Auth认证本节咱们要为大家介绍一下,如何在应用RestTemplate发送申请的时候应用代理Proxy。至于为什么要应用代理,给大家举一个简略的例子:一些做过爬虫的同学可能都晓得,当爬虫高频的屡次拜访一个网站数据,可能导致申请客户端Ip被封闭的可能。很多状况下,做爬虫的企业就保护一个代理IP池,每发送一次申请,就更换一次IP。代理Proxy作为跳板成为服务的间接访问者,代理使用者(真正的客户端)是间接拜访服务。这样在服务端看来,每次申请是代理收回的,从代理IP池中始终更换代理发送申请,这样可能升高IP封闭的可能。 咱们本节就来为大家介绍,作为一个代理使用者,该如何应用RestTemplate发送申请的时候应用代理Proxy。 一、搭建一个代理服务器笔者只从常识的层面去解说应用办法,所以不做蝇营狗苟的勾当。代理服务器还是由我本人来搭建用来测试,在我的一个CentOS服务器上安装tinyproxy,tinyproxy能够提供代理服务。 # 装置tinyproxy 命令sudo yum install tinyproxy -y编辑tinyproxy的配置文件vim /etc/tinyproxy/tinyproxy.conf。为该代理配置容许拜访的使用者客户端ip,也就是我家的ip,所以这个代理服务只能我用,其他人用不了。 # 代理服务端口Port 1080# 容许哪个客户端应用该代理程序?Allow xxx.xxx.xxx.xxx启动tinyproxy提供代理服务,最好检查一下防火墙是否凋谢了1080端口。 systemctl start tinyproxy.service二、用于测试的服务端咱们这次要拜访的服务端是:http://www.httpbin.org, 这个网站是提供在线的HTTP拜访服务的网站。咱们能够用它进行测试。http://www.httpbin.org/ip是咱们本次要拜访的服务,响应后果是访问者的IP。我在家里应用电脑拜访这个服务的时候后果如下:上图没有应用代理,所以返回的是我家的ip。如果我应用代理拜访,返回后果应该是proxy代理服务器的ip地址。 三、代理使用者RestTemplate我的第一大节中的代理服务器的ip是88.99.10.251,tinyproxy代理服务端口1080。下文代码通过SimpleClientHttpRequestFactory设置拜访代理 @SpringBootTestclass ProxyTests { @Resource private RestTemplate restTemplate; @Test void testProxyIp() { String url = "http://www.httpbin.org/ip"; SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); requestFactory.setProxy( new Proxy( Proxy.Type.HTTP, new InetSocketAddress("88.99.10.251", 1080) //设置代理服务 ) ); restTemplate.setRequestFactory(requestFactory); //发送申请 String result = restTemplate.getForObject(url, String.class); System.out.println(result); //打印响应后果 }}代理类型能够是HTTP也能够是SOCKS。下图是 "http://www.httpbin.org/ip" 的申请响应后果,返回的是代理服务器的ip,而不是我家里的ip。阐明咱们为RestTemplate 设置的代理失效了。 ...

August 18, 2020 · 1 min · jiezi

关于spring:IOC之bean的创建spring525

一、问题剖析1.spring容器的启动过程,启动期间都做了什么?什么时候创立单实例bean?2.ioc是如何创立这些单实例bean,是如何治理的?保留在哪里? 二、Debug剖析ClassPathXmlApplicationContext的继承树 1.创立spring容器,读取配置文件,类门路下加载配置文件 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");2.最先加载的应该是动态初始化块,它会随着类的加载而加载 static {//在WebLogic 8.1中,在应用程序敞开时,紧急加载ContextCLosedEvent类以防止奇怪的类加载器问题。 ContextClosedEvent.class.getName();}3.调用ClassPathXmlApplicationContext的构造方法 /** * 创立一个新的classPathXmlApplicationcontext,从给定的XML文件加载定义,并主动刷新该ontext。 * @param applicationContext.xml * 如果上下文创立失败,@抛出BeansException */public ClassPathXmlApplicationContext(String configLocation) throws BeansException {//调用类中其余结构 this(new String[] {configLocation}, true, null);}4.参数解析 参数名参数值String[] configLocationsqpplicationContext.xmlrefreshtrueparentnull/** * 创立一个新的classPathXmlApplicationContextwith给定的父类,从给定的XML文件加载定义。 * @param configLocations 资源地位数组 * @param refresh 是否主动刷新上下文 * 加载所有bean定义并创立所有单例。或者,在进一步的configuri之后手动调用刷新康泰克斯的 * @param 父上下文后手动调用刷新 * 如果上下文创立失败,@抛出BeansException * @see #refresh() */public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException { // 1.初始化父类 super(parent); // 2.设置本地的配置信息 setConfigLocations(configLocations); // 3.实现Spring容器的初始化 if (refresh) { //true 进入refresh办法 refresh(); //所有单实例创立实现 }}5.refresh()解析 ...

August 17, 2020 · 6 min · jiezi

关于spring:angular密码和确认密码的校验

确认明码 <input nz-input formControlName="password" (ngModelChange)="passwordChange($event)" [(ngModel)]="resetPassWordVo.password" required type="password" autocomplete="off"><input nz-input formControlName="confirmPassword" (ngModelChange)="passwordChange($event)" [(ngModel)]="resetPassWordVo.confirmPassword" required type="password" autocomplete="off">passwordChange(value: string){ const confirmPasswordErrors = this.userPassForm.get('confirmPassword').errors; const passwordErrors = this.userPassForm.get('password').errors; if (confirmPasswordErrors && (confirmPasswordErrors.hasOwnProperty('pattern') || confirmPasswordErrors.hasOwnProperty('password') )){ return; } if ( passwordErrors && (passwordErrors.hasOwnProperty('pattern') || passwordErrors.hasOwnProperty('password'))){ return; } if (!this.resetPassWordVo.password || this.resetPassWordVo.password === '' ){ return; } if (!this.resetPassWordVo.confirmPassword || this.resetPassWordVo.confirmPassword === '' ){ return; } // 上边的校验通过后 if (this.resetPassWordVo.password === value || this.resetPassWordVo.confirmPassword === value){ this.userPassForm.get('password').setErrors(null); this.userPassForm.get('confirmPassword').setErrors(null); }else{ this.userPassForm.get('password').setErrors({ passwordDiff: '两次输出的明码不统一!'}); this.userPassForm.get('confirmPassword').setErrors({ passwordDiff: '两次输出的明码不统一!'}); } }集体博客 蜗牛

August 17, 2020 · 1 min · jiezi

关于spring:angular密码和确认密码的校验

确认明码 <input nz-input formControlName="password" (ngModelChange)="passwordChange($event)" [(ngModel)]="resetPassWordVo.password" required type="password" autocomplete="off"><input nz-input formControlName="confirmPassword" (ngModelChange)="passwordChange($event)" [(ngModel)]="resetPassWordVo.confirmPassword" required type="password" autocomplete="off">passwordChange(value: string){ const confirmPasswordErrors = this.userPassForm.get('confirmPassword').errors; const passwordErrors = this.userPassForm.get('password').errors; if (confirmPasswordErrors && (confirmPasswordErrors.hasOwnProperty('pattern') || confirmPasswordErrors.hasOwnProperty('password') )){ return; } if ( passwordErrors && (passwordErrors.hasOwnProperty('pattern') || passwordErrors.hasOwnProperty('password'))){ return; } if (!this.resetPassWordVo.password || this.resetPassWordVo.password === '' ){ return; } if (!this.resetPassWordVo.confirmPassword || this.resetPassWordVo.confirmPassword === '' ){ return; } // 上边的校验通过后 if (this.resetPassWordVo.password === value || this.resetPassWordVo.confirmPassword === value){ this.userPassForm.get('password').setErrors(null); this.userPassForm.get('confirmPassword').setErrors(null); }else{ this.userPassForm.get('password').setErrors({ passwordDiff: '两次输出的明码不统一!'}); this.userPassForm.get('confirmPassword').setErrors({ passwordDiff: '两次输出的明码不统一!'}); } }集体博客 蜗牛

August 17, 2020 · 1 min · jiezi

关于spring:ES-评分去除词频去除简索源对score的影响

1、词频 词在文档中呈现的频度是多少? 频度越高,权重 _越高_;批改为词频对得分没有影响:tf(t in d) = √frequency 词 t 在文档 d 的词频( tf )是该词在文档中呈现次数的平方根。index{"mappings": { "doc": { "properties": { "text": { "type": "string", "index_options": "docs" }}}}}设置为 docs 能够禁用词频统计及词频地位,这个映射的字段不会计算词的呈现次数,对于短语或近似查问也不可用。要求准确查问的 not_analyzed 字符串字段会默认应用该设置。2、文档长度归一字段越短,字段的权重 越高 。如果词呈现在相似题目 title 这样的字段,要比它呈现在内容 body 这样的字段中的相关度更高。字段长度的归一值公式如下:norm(d) = 1 / √numTermsindex{"mappings": { "doc": { "properties": { "text": { "type": "string", "norms": { "enabled": false } }}}}

August 17, 2020 · 1 min · jiezi

关于spring:使用Java-API进行targz文件及文件夹压缩解压缩

在java(JDK)中咱们能够应用ZipOutputStream去创立zip压缩文件,(参考我之前写的文章 应用java API进行zip递归压缩文件夹以及解压 ),也能够应用GZIPOutputStream去创立gzip(gz)压缩文件,然而java中没有一种官网的API能够去创立tar.gz文件。所以咱们须要应用到第三方库Apache Commons Compress去创立.tar.gz文件。 在pom.xml中,咱们能够通过如下的maven坐标引入commons-compress。 <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-compress</artifactId> <version>1.20</version></dependency>解释阐明 tar文件精确的说是打包文件,将文件打包到一个tar文件中,文件名后缀是.tarGzip是将文件的存储空间压缩保留,文件名后缀是.gztar.gz或.tgz通常是指将文件打包到一个tar文件中,并将它应用Gzip进行压缩。如果您浏览完本文感觉对您有帮忙的话,请给我一个赞,您的反对是我不竭的创作能源! 一、将两个文件打包到tar.gz上面的这个例子是将2个文件打包为tar.gz压缩文件。下文代码中的流操作应用了try-with-resources语法,所以不必写代码手动的close流。 import org.apache.commons.compress.archivers.tar.TarArchiveEntry;import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream;import org.junit.jupiter.api.Test;import java.io.BufferedOutputStream;import java.io.IOException;import java.io.OutputStream;import java.nio.file.Files;import java.nio.file.Path;import java.nio.file.Paths;import java.util.Arrays;import java.util.List;public class TarGzTest { @Test void testFilesTarGzip() throws IOException { //输出文件,被压缩文件 Path path1 = Paths.get("/home/test/file-a.xml"); Path path2 = Paths.get("/home/test/file-b.txt"); List<Path> paths = Arrays.asList(path1, path2); //输入文件压缩后果 Path output = Paths.get("/home/test/output.tar.gz"); //OutputStream输入流、BufferedOutputStream缓冲输入流 //GzipCompressorOutputStream是gzip压缩输入流 //TarArchiveOutputStream打tar包输入流(蕴含gzip压缩输入流) try (OutputStream fOut = Files.newOutputStream(output); BufferedOutputStream buffOut = new BufferedOutputStream(fOut); GzipCompressorOutputStream gzOut = new GzipCompressorOutputStream(buffOut); TarArchiveOutputStream tOut = new TarArchiveOutputStream(gzOut)) { //遍历文件list for (Path path : paths) { //该文件不是目录或者符号链接 if (!Files.isRegularFile(path)) { throw new IOException("Support only file!"); } //将该文件放入tar包,并执行gzip压缩 TarArchiveEntry tarEntry = new TarArchiveEntry( path.toFile(), path.getFileName().toString()); tOut.putArchiveEntry(tarEntry); Files.copy(path, tOut); tOut.closeArchiveEntry(); } //for循环实现之后,finish-tar包输入流 tOut.finish(); } }}将file-a.xml和file-b.txt打包到output.tar文件中,并应用gzip对这个tar包进行压缩。能够应用如下命令查看tar包外面蕴含的文件。 ...

August 17, 2020 · 2 min · jiezi

关于spring:精讲RestTemplate第9篇如何通过HTTP-Basic-Auth认证

本文是精讲RestTemplate第9篇,前篇的blog拜访地址如下: 精讲RestTemplate第1篇-在Spring或非Spring环境下如何应用精讲RestTemplate第2篇-多种底层HTTP客户端类库的切换精讲RestTemplate第3篇-GET申请应用办法详解精讲RestTemplate第4篇-POST申请办法应用详解精讲RestTemplate第5篇-DELETE、PUT等申请办法应用详解精讲RestTemplate第6篇-文件上传下载与大文件流式下载精讲RestTemplate第7篇-自定义申请失败异样解决精讲RestTemplate第8篇-申请失败主动重试机制服务提供方通常会通过肯定的受权、鉴权认证逻辑来爱护API接口。其中比较简单、容易实现的形式就是应用HTTP 的Basic Auth来实现接口拜访用户的认证。咱们本节就来为大家介绍一下,在服务端退出Basic Auth认证的状况下,该如何应用RestTemplate拜访服务端接口。 一、HttpBasic认证原理阐明 首先,HttpBasic模式要求传输的用户名明码应用Base64模式进行加密。如果用户名是 "admin"  ,明码是“ admin”,则将字符串"admin:admin"应用Base64编码算法加密。加密后果可能是:YWtaW46YWRtaW4=。而后,在Http申请中应用authorization作为一个HTTP申请头Header name,“Basic YWtaW46YWRtaW4=“作为Header的值,发送给服务端。(留神这里应用Basic+空格+加密串)服务器在收到这样的申请时,达到BasicAuthenticationFilter过滤器,将提取“authorization”的Header值,并应用用于验证用户身份的雷同算法Base64进行解码。解码后果与登录验证的用户名明码匹配,匹配胜利则能够持续过滤器后续的拜访。二、HTTP Basic Auth服务端实现如果你想本人搭建一个服务端,那么如何为Spring Boot 服务增加Basic Auth认证?请参考我的另外一篇文章:《Spring Security系列之Http Basic Auth登录认证模式》 。 当然咱们也能够不必本人去搭建服务端,给大家介绍一个提供收费在线的RESTful接口服务的网站:httpbin.com。这个网站为咱们提供了Basic Auth认证测试服务接口。如果咱们只是为了学习RestTemplate,间接用这个网站提供的服务就能够了。 浏览器拜访地址:http://www.httpbin.org/#/Auth/get_basic_auth__user___passwd_ ,这个接口服务是通过OpenAPI(swagger)实现的,所以能够进行在线的拜访测试。所以能够先通过页面操作测试一下,再开始上面学习应用RestTemplate拜访服务端接口。 三、申请头形式携带认证信息在HTTP申请头中携带Basic Auth认证的用户名和明码,具体实现参考下文代码正文: @SpringBootTestclass BasicAuthTests { @Resource private RestTemplate restTemplate; @Test void testBasicAuth() { //该url上携带用户名明码是httpbin网站测试接口的要求, //实在的业务是不须要在url上体现basic auth用户名明码的 String url = "http://www.httpbin.org/basic-auth/admin/adminpwd"; //在申请头信息中携带Basic认证信息(这里才是理论Basic认证传递用户名明码的形式) HttpHeaders headers = new HttpHeaders(); headers.set("authorization", "Basic " + Base64.getEncoder() .encodeToString("admin:adminpwd".getBytes())); //发送申请 HttpEntity<String> ans = restTemplate .exchange(url, HttpMethod.GET, //GET申请 new HttpEntity<>(null, headers), //退出headers String.class); //body响应数据接管类型 System.out.println(ans); } }测试用例执行胜利,阐明RestTemplate 正确的携带了Basic 认证信息,失去失常的响应后果:200。 ...

August 16, 2020 · 1 min · jiezi

关于spring:Spring实践问题集合1

注:每个汇合的问题数为10-15个。 @Value注解如何设置默认值原文起源:Spring @Value 设置默认值 //字符串:设置默认值@Value("${some.key:my default value}")private String stringWithDefaultValue;//默认值为空@Value("${some.key:}")private String stringWithBlankDefaultValue;//根本类型@Value("${some.key:true}")private boolean booleanWithDefaultValue;@Value("${some.key:42}")private int intWithDefaultValue;//数组@Value("${some.key:one,two,three}")private String[] stringArrayWithDefaults;@Value("${some.key:1,2,3}")private int[] intArrayWithDefaults;SpringBoot 启动报错: org.apache.catalina.LifecycleException: Protocol handler start failed原文起源:spring boot 启动报错org.apache.catalina.LifecycleException: Protocol handler start failed 报错起因:默认的端口8080曾经被占用了,批改一下端口即可。

August 16, 2020 · 1 min · jiezi

关于spring:精讲RestTemplate第8篇请求失败自动重试机制

本文是精讲RestTemplate第8篇,前篇的blog拜访地址如下: 精讲RestTemplate第1篇-在Spring或非Spring环境下如何应用精讲RestTemplate第2篇-多种底层HTTP客户端类库的切换精讲RestTemplate第3篇-GET申请应用办法详解精讲RestTemplate第4篇-POST申请办法应用详解精讲RestTemplate第5篇-DELETE、PUT等申请办法应用详解精讲RestTemplate第6篇-文件上传下载与大文件流式下载精讲RestTemplate第7篇-自定义申请失败异样解决在上一节咱们为大家介绍了,当RestTemplate发动近程申请异样时的自定义解决办法,咱们能够通过自定义的形式解析出HTTP Status Code状态码,而后依据状态码和业务需要决定程序下一步该如何解决。本节为大家介绍另外一种通用的异样的解决机制:那就是主动重试。也就是说,在RestTemplate发送申请失去非200状态后果的时候,距离肯定的工夫再次发送n次申请。n次申请都失败之后,最初抛出HttpClientErrorException。在开始本节代码之前,将上一节的RestTemplate自定义异样解决的代码正文掉,否则主动重试机制不会失效。如下(参考上一节代码): //restTemplate.setErrorHandler(new MyRestErrorHandler());一、Spring Retry配置失效通过maven坐标引入spring-retry,spring-retry的实现依赖于面向切面编程,所以引入aspectjweaver。以下配置过程都是基于Spring Boot利用。 <dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> <version>1.2.5.RELEASE</version></dependency><dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId></dependency>在Spring Boot 利用入口启动类,也就是配置类的下面加上@SpringRetry注解,示意让重试机制失效。 二、应用案例写一个模仿的业务类RetryService ,在其外面注入RestTemplate 。RestTemplate 实例化Bean配置参考: 《精讲RestTemplate第1篇-在Spring或非Spring环境下如何应用》 和 《精讲RestTemplate第2篇-多种底层HTTP客户端类库的切换》 进行实现。将正确的申请服务地址由“/posts/1”改成“/postss/1”。服务不存在所以抛出404异样,是为了触发重试机制。@Servicepublic class RetryService { @Resource private RestTemplate restTemplate; private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); @Retryable(value = RestClientException.class, maxAttempts = 3, backoff = @Backoff(delay = 5000L,multiplier = 2)) public HttpStatus testEntity() { System.out.println("发动近程API申请:" + DATE_TIME_FORMATTER.format(LocalDateTime.now())); String url = "http://jsonplaceholder.typicode.com/postss/1"; ResponseEntity<String> responseEntity = restTemplate.getForEntity(url, String.class); return responseEntity.getStatusCode(); // 获取响应码 }}@Retryable注解的办法在产生异样时会重试,参数阐明: ...

August 15, 2020 · 1 min · jiezi

关于spring:精讲RestTemplate第7篇自定义请求失败异常处理

本文是精讲RestTemplate第7篇,前篇的blog拜访地址如下: 精讲RestTemplate第1篇-在Spring或非Spring环境下如何应用精讲RestTemplate第2篇-多种底层HTTP客户端类库的切换精讲RestTemplate第3篇-GET申请应用办法详解精讲RestTemplate第4篇-POST申请办法应用详解精讲RestTemplate第5篇-DELETE、PUT等申请办法应用详解精讲RestTemplate第6篇-文件上传下载与大文件流式下载一、异常现象在应用RestTemplate进行近程接口服务调用的时候,当申请的服务出现异常:超时、服务不存在等状况的时候(响应状态非200、而是400、500HTTP状态码),就会抛出如下异样: 该异样我是模仿进去的,将正确的申请服务地址由“/posts/1”改成“/postss/1”。服务不存在所以抛出404异样。 @Testpublic void testEntity() { String url = "http://jsonplaceholder.typicode.com/postss/1"; ResponseEntity<String> responseEntity = restTemplate.getForEntity(url, String.class); //这行抛出异样 //上面两行代码执行不到 HttpStatus statusCode = responseEntity.getStatusCode(); // 获取响应码 System.out.println("HTTP 响应状态:" + statusCode);}异样抛出之后,程序前面的代码就执行不到了,无奈进行前面的代码执行。理论的业务开发中,有的时候咱们更冀望的后果是:不论你服务端是超时了还是服务不存在,咱们都应该取得最终的申请后果(HTTP申请后果状态400、500),而不是取得一个抛出的异样。 二、源码解析-默认实现首先我要说一个论断:RestTemplate申请后果异样是能够自定义解决的。在开始进行自定义的异样解决逻辑之前,咱们有必要看一下异样解决的默认实现。也就是:为什么会产生下面大节提到的景象? ResponseErrorHandler是RestTemplate申请后果的异样处理器接口 接口的第一个办法hasError用于判断HttpResponse是否是异样响应(通过状态码)接口的第二个办法handleError用于解决异样响应后果(非200状态码段)DefaultResponseErrorHandler是ResponseErrorHandler的默认实现所以咱们就来看看DefaultResponseErrorHandler是如何来解决异样响应的?从HttpResponse解析出Http StatusCode,如果状态码StatusCode为null,就抛出UnknownHttpStatusCodeException异样。 如果StatusCode存在,则解析出StatusCode的series,也就是状态码段(除了200段,其余全是异样状态码),解析规定是StatusCode/100取整。 public enum Series { INFORMATIONAL(1), // 1xx/100 SUCCESSFUL(2), // 2xx/100 REDIRECTION(3), // 3xx/100 CLIENT_ERROR(4), // 4xx/100 ,客户端异样 SERVER_ERROR(5); // 5xx/100 ,服务端异样}进一步针对客户端异样和服务端异样进行解决,解决的办法是抛出HttpClientErrorException。也就是第一大节呈现的异样的起因 三、RestTemplate自定义异样解决所以咱们要实现自定义异样,实现ResponseErrorHandler 接口就能够。 public class MyRestErrorHandler implements ResponseErrorHandler { /** * 判断返回后果response是否是异样后果 * 次要是去查看response 的HTTP Status * 仿造DefaultResponseErrorHandler实现即可 */ @Override public boolean hasError(ClientHttpResponse response) throws IOException { int rawStatusCode = response.getRawStatusCode(); HttpStatus statusCode = HttpStatus.resolve(rawStatusCode); return (statusCode != null ? statusCode.isError(): hasError(rawStatusCode)); } protected boolean hasError(int unknownStatusCode) { HttpStatus.Series series = HttpStatus.Series.resolve(unknownStatusCode); return (series == HttpStatus.Series.CLIENT_ERROR || series == HttpStatus.Series.SERVER_ERROR); } @Override public void handleError(ClientHttpResponse response) throws IOException { // 外面能够实现你本人遇到了Error进行正当的解决 //TODO 将接口申请的异样信息长久化 }}将MyRestErrorHandler 在RestTemplate实例化的时候进行注册。参考: 《精讲RestTemplate第1篇-在Spring或非Spring环境下如何应用》 和 《精讲RestTemplate第2篇-多种底层HTTP客户端类库的切换》 进行实现 ...

August 14, 2020 · 1 min · jiezi

关于spring:后端程序员必备的-Linux-基础知识常见命令近万字总结

大家好!我是 Guide 哥,Java 后端开发。一个会一点前端,喜爱烹饪的自在少年。 明天这篇文章中简略介绍一下一个 Java 程序员必知的 Linux 的一些概念以及常见命令。 如果文章有任何须要改善和欠缺的中央,欢送在评论区指出,共同进步!笔芯! 1. 从意识操作系统开始 正式开始 Linux 之前,简略花一点点篇幅科普一下操作系统相干的内容。 1.1. 操作系统简介我通过以下四点介绍什么是操作系统: 操作系统(Operating System,简称 OS)是治理计算机硬件与软件资源的程序,是计算机的基石。操作系统实质上是一个运行在计算机上的软件程序 ,用于治理计算机硬件和软件资源。 举例:运行在你电脑上的所有应用程序都通过操作系统来调用零碎内存以及磁盘等等硬件。操作系统存在屏蔽了硬件层的复杂性。 操作系统就像是硬件应用的负责人,兼顾着各种相干事项。操作系统的内核(Kernel)是操作系统的外围局部,它负责零碎的内存治理,硬件设施的治理,文件系统的治理以及应用程序的治理。内核(Kernel)在后文中会提到。 1.2. 操作系统简略分类1.2.1. Windows目前最风行的集体桌面操作系统 ,不做多的介绍,大家都分明。界面简略易操作,软件生态十分好。 玩玩电脑游戏还是必须要有 Windows 的,所以我当初是一台 Windows 用于玩游戏,一台 Mac 用于平时日常开发和学习应用。 1.2.2. Unix最早的多用户、多任务操作系统 。前面崛起的 Linux 在很多方面都参考了 Unix。 目前这款操作系统曾经逐步逐步退出操作系统的舞台。 1.2.3. LinuxLinux 是一套收费应用、开源的类 Unix 操作系统。 Linux 存在着许多不同的发行版本,但它们都应用了 Linux 内核 。 严格来讲,Linux 这个词自身只示意 Linux 内核,在 GNU/Linux 零碎中,Linux 理论就是 Linux 内核,而该零碎的其余部分次要是由 GNU 工程编写和提供的程序组成。独自的 Linux 内核并不能成为一个能够失常工作的操作系统。很多人更偏向应用 “GNU/Linux” 一词来表白人们通常所说的 “Linux”。 ...

August 13, 2020 · 4 min · jiezi

关于spring:SSM关联查询常用的两种方式

0th接简洁版SSM08,这个案例没有解决多对一的关联查问 1th 第一种形式拼sql,批改原来的sql 原sql <!-- sql 要留神测试 --> <select id="selectEmp" resultType="Emp"> select e.*, d.departname departname2 from emp e where 1=1 <if test="empname!=null and empname!='' "> and e.empname like '%${empname}%' </if> order by empid desc </select>为关联查问批改后sql <!-- sql 要留神测试 --> <select id="selectEmp" resultType="Emp"> select e.*, d.departname departname2 from emp e left outer join depart d on e.departid=d.departid where 1=1 <if test="empname!=null and empname!='' "> and e.empname like '%${empname}%' </if> order by empid desc </select>Emp bean里减少departname2字段和setter,getter办法 ...

August 13, 2020 · 1 min · jiezi

关于spring:精讲RestTemplate第6篇文件上传下载与大文件流式下载

本文是精讲RestTemplate第6篇,前篇的blog拜访地址如下: 精讲RestTemplate第1篇-在Spring或非Spring环境下如何应用精讲RestTemplate第2篇-多种底层HTTP客户端类库的切换精讲RestTemplate第3篇-GET申请应用办法详解精讲RestTemplate第4篇-POST申请办法应用详解精讲RestTemplate第5篇-DELETE、PUT等申请办法应用详解RestTemplate是HTTP客户端库,所以为了应用RestTemplate进行文件上传和下载,须要咱们先编写服务端的反对文件上传和下载的程序。请参考我之前写的一篇文章:SpringBoot实现本地存储文件上传及提供HTTP拜访服务 。依照此文实现学习之后,能够取得 一个以拜访服务URI为"/upload”的文件上传服务端点服务端点上传文件胜利后会返回一个HTTP连贯,能够用来下载文件。上面咱们就开始学习应用RestTemplate是HTTP客户端库,进行文件的上传与下载。 一、文件上传写一个单元测试类,来实现RestTemplate文件上传性能,具体实现细节参考代码正文 @SpringBootTestclass UpDownLoadTests { @Resource private RestTemplate restTemplate; @Test void testUpload() { // 文件上传服务上传接口 String url = "http://localhost:8888/upload"; // 待上传的文件(存在客户端本地磁盘) String filePath = "D:\\data\\local\\splash.png"; // 封装申请参数 FileSystemResource resource = new FileSystemResource(new File(filePath)); MultiValueMap<String, Object> param = new LinkedMultiValueMap<>(); param.add("uploadFile", resource); //服务端MultipartFile uploadFile //param.add("param1", "test"); //服务端如果承受额定参数,能够传递 // 发送申请并输入后果 System.out.println("--- 开始上传文件 ---"); String result = restTemplate.postForObject(url, param, String.class); System.out.println("--- 拜访地址:" + result); }}输入后果如下: --- 开始上传文件 ------ 拜访地址:http://localhost:8888/2020/08/12/028b38f1-3f9b-4088-9bea-1af8c18cd619.png文件上传之后,能够通过下面的拜访地址,在浏览器拜访。或者通过RestTemplate客户端进行下载。 ...

August 12, 2020 · 1 min · jiezi

关于spring:SpringBoot实现本地存储文件上传及提供HTTP访问服务

笔者打算为大家介绍分布式文件系统,用于存储利用的图片、word、excel、pdf等文件。在开始介绍分布式文件系统之前,为大家介绍一下应用本机存储来寄存文件资源。二者的外围实现过程是一样的: 上传文件,保留文件(本节是本地磁盘)返回文件HTTP拜访服务门路给前端,进行上传之后的成果展现一、温习服务端接管上传的目标是提供文件的拜访服务,那么对于SpringBoot而言,有哪些能够提供文件拜访的动态资源目录呢? classpath:/META-INF/resources/ ,classpath:/static/ ,classpath:/public/ ,classpath:/resources/这是之前咱们为大家介绍的内容,从这里看出这里的动态资源都在classpath下。那么就呈现问题: 利用的文件资源不能和我的项目代码离开存储(你见过往github上传代码,还附带我的项目文件数据的么?)我的项目打包艰难,当上传的文件越来越多,我的项目的打包jar越来越大。代码与文件数据不能离开存储,就意味着文件数据的备份将变得复杂二、文件上传目录自定义配置怎么解决上述问题?别忘记了spring boot 为咱们提供了应用spring.resources.static-locations配置自定义动态文件的地位。 web: upload-path: D:/data/spring: resources: static-locations: classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/,file:${web.upload-path}配置web.upload-path为与我的项目代码拆散的动态资源门路,即:文件上传保留根门路配置spring.resources.static-locations,除了带上Spring Boot默认的动态资源门路之外,加上file:${web.upload-path}指向内部的文件资源上传门路。该门路下的动态资源能够间接对外提供HTTP拜访服务。三、文件上传的Controller实现详情看代码正文 @RestControllerpublic class FileUploadController { //绑定文件上传门路到uploadPath @Value("${web.upload-path}") private String uploadPath; SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd/"); @PostMapping("/upload") public String upload(MultipartFile uploadFile, HttpServletRequest request) { // 在 uploadPath 文件夹中通过日期对上传的文件归类保留 // 比方:/2019/06/06/cf13891e-4b95-4000-81eb-b6d70ae44930.png String format = sdf.format(new Date()); File folder = new File(uploadPath + format); if (!folder.isDirectory()) { folder.mkdirs(); } // 对上传的文件重命名,防止文件重名 String oldName = uploadFile.getOriginalFilename(); String newName = UUID.randomUUID().toString() + oldName.substring(oldName.lastIndexOf("."), oldName.length()); try { // 文件保留 uploadFile.transferTo(new File(folder, newName)); // 返回上传文件的拜访门路 String filePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + format + newName; return filePath; } catch (IOException e) { throw new CustomException(CustomExceptionType.SYSTEM_ERROR); } }}四、写一个模仿的文件上传页面,进行测试把该upload.html文件放到classpath:public目录下,对外提供拜访。 ...

August 11, 2020 · 1 min · jiezi

关于spring:看阿里P7怎么讲MyBatis从MyBatis的理解以及配置和实现全帮你搞懂

前言MyBatis 是一款优良的长久层框架,一个半 ORM(对象关系映射)框架,它反对定制化 SQL、存储过程以及高级映`射。MyBatis 防止了简直所有的 JDBC 代码和手动设置参数以及获取后果集。MyBatis 能够应用简略的 XML 或注解来配置和映射原生类型、接口和 Java 的 POJO(Plain Old Java Objects,一般老式 Java 对象)为数据库中的记录。 MyBatis的作用MyBatis作用是在长久层也就是拜访数据库的操作,以前咱们拜访数据库是用JDBC来拜访数据库,JDBC拜访数据库须要写很多反复的代码,如果数据库拜访很多还须要对数据库连贯进行不停的关上连贯和敞开连贯,很耗费零碎性能MyBatis封装了JDBC底层拜访数据库的代码,让咱们程序猿只须要关怀如何去写好SQL就好,不在须要去写JDBC底层的代码 MyBatis的优缺点长处MyBatis封装了JBDC底层拜访数据库的细节,使咱们程序猿不须要与JDBC API打交道,就能够拜访数据库MyBatis简略易学,程序猿间接编写SQL语句,适宜于对SQL语句性能要求比拟高的我的项目SQL语句封装在配置文件中,便于对立治理与保护,升高了程序的耦合度SQL代码从程序代码中彻底分离出来,可重用提供了动静SQL标签,反对编写动静SQL提供映射标签,反对对象与数据库的ORM字段关系映射毛病过于依赖数据库SQL语句,导致数据库移植性差,更换数据库,如果SQL语句有差别,SQL语句工作量大因为xml里标签id必须惟一,导致DAO中办法不反对办法重载MyBatis的配置文件properties元素properties元素形容的都是内部化,可代替的属性个别用来配置连贯数据源,咱们能够应用property子节点来配置也能够应用资源门路援用 应用property子节点来配置 <properties> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql:///mybatis"/> <property name="username" value="root"/> <property name="password" value="root"/> </properties>应用资源门路援用 <properties resource="jdbcConfig.properties"/>jdbcConfig.properties外面的属性 driver=com.mysql.jdbc.Driverurl=jdbc:mysql://127.0.0.1:3306/testusername=rootpassword=123456连贯数据源的配置 <dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource>如果应用property子节点来配置和应用资源门路援用都用了,这个时候MyBatis会调用哪个勒?MyBatis会调用资源门路援用的属性值,因为资源门路援用的优先级高于property子节点的优先级 settings元素settings是 MyBatis 中极为重要的调整设置,它们会扭转 MyBatis 的运行时行为 <settings> <!-- 全局映射器启用缓存 --> <setting name="cacheEnabled" value="true"/> <!-- 查问时,敞开关联对象即时加载以进步性能 --> <setting name="lazyLoadingEnabled" value="true"/> <!-- 设置关联对象加载的状态,此处为按需加载字段 (加载字段由 SQL指 定 ),不会加载关联表的所有字段,以进步性能 --> <setting name="aggressiveLazyLoading" value="false"/> <!-- 对于未知的 SQL查问,容许返回不同的后果集以达到通用的成果 --> <setting name="multipleResultSetsEnabled" value="true"/> <!-- 容许应用列标签代替列名 --> <setting name="useColumnLabel" value="true"/> <!-- 容许应用自定义的主键值 (比方由程序生成的 UUID 32位编码作为键值 ),数据表的 PK生成策略将被笼罩 --> <setting name="useGeneratedKeys" value="true"/> <!-- 给予被嵌套的 resultMap以字段 -属性的映射反对 --> <setting name="autoMappingBehavior" value="FULL"/> <!-- 对于批量更新操作缓存 SQL以进步性能 --> <setting name="defaultExecutorType" value="BATCH"/> <!-- 数据库超过 25000秒仍未响应则超时 --> <setting name="defaultStatementTimeout" value="25000"/> </settings>typeAliases元素typeAliases元素的作用是给JavaBean取别名,不便咱们在mappeer配置文件中应用 ...

August 10, 2020 · 3 min · jiezi

关于spring:看阿里P7怎么讲MyBatis从MyBatis的理解以及配置和实现全帮你搞懂

前言MyBatis 是一款优良的长久层框架,一个半 ORM(对象关系映射)框架,它反对定制化 SQL、存储过程以及高级映`射。MyBatis 防止了简直所有的 JDBC 代码和手动设置参数以及获取后果集。MyBatis 能够应用简略的 XML 或注解来配置和映射原生类型、接口和 Java 的 POJO(Plain Old Java Objects,一般老式 Java 对象)为数据库中的记录。 MyBatis的作用MyBatis作用是在长久层也就是拜访数据库的操作,以前咱们拜访数据库是用JDBC来拜访数据库,JDBC拜访数据库须要写很多反复的代码,如果数据库拜访很多还须要对数据库连贯进行不停的关上连贯和敞开连贯,很耗费零碎性能MyBatis封装了JDBC底层拜访数据库的代码,让咱们程序猿只须要关怀如何去写好SQL就好,不在须要去写JDBC底层的代码 MyBatis的优缺点长处MyBatis封装了JBDC底层拜访数据库的细节,使咱们程序猿不须要与JDBC API打交道,就能够拜访数据库MyBatis简略易学,程序猿间接编写SQL语句,适宜于对SQL语句性能要求比拟高的我的项目SQL语句封装在配置文件中,便于对立治理与保护,升高了程序的耦合度SQL代码从程序代码中彻底分离出来,可重用提供了动静SQL标签,反对编写动静SQL提供映射标签,反对对象与数据库的ORM字段关系映射毛病过于依赖数据库SQL语句,导致数据库移植性差,更换数据库,如果SQL语句有差别,SQL语句工作量大因为xml里标签id必须惟一,导致DAO中办法不反对办法重载MyBatis的配置文件properties元素properties元素形容的都是内部化,可代替的属性个别用来配置连贯数据源,咱们能够应用property子节点来配置也能够应用资源门路援用 应用property子节点来配置 <properties> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql:///mybatis"/> <property name="username" value="root"/> <property name="password" value="root"/> </properties>应用资源门路援用 <properties resource="jdbcConfig.properties"/>jdbcConfig.properties外面的属性 driver=com.mysql.jdbc.Driverurl=jdbc:mysql://127.0.0.1:3306/testusername=rootpassword=123456连贯数据源的配置 <dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource>如果应用property子节点来配置和应用资源门路援用都用了,这个时候MyBatis会调用哪个勒?MyBatis会调用资源门路援用的属性值,因为资源门路援用的优先级高于property子节点的优先级 settings元素settings是 MyBatis 中极为重要的调整设置,它们会扭转 MyBatis 的运行时行为 <settings> <!-- 全局映射器启用缓存 --> <setting name="cacheEnabled" value="true"/> <!-- 查问时,敞开关联对象即时加载以进步性能 --> <setting name="lazyLoadingEnabled" value="true"/> <!-- 设置关联对象加载的状态,此处为按需加载字段 (加载字段由 SQL指 定 ),不会加载关联表的所有字段,以进步性能 --> <setting name="aggressiveLazyLoading" value="false"/> <!-- 对于未知的 SQL查问,容许返回不同的后果集以达到通用的成果 --> <setting name="multipleResultSetsEnabled" value="true"/> <!-- 容许应用列标签代替列名 --> <setting name="useColumnLabel" value="true"/> <!-- 容许应用自定义的主键值 (比方由程序生成的 UUID 32位编码作为键值 ),数据表的 PK生成策略将被笼罩 --> <setting name="useGeneratedKeys" value="true"/> <!-- 给予被嵌套的 resultMap以字段 -属性的映射反对 --> <setting name="autoMappingBehavior" value="FULL"/> <!-- 对于批量更新操作缓存 SQL以进步性能 --> <setting name="defaultExecutorType" value="BATCH"/> <!-- 数据库超过 25000秒仍未响应则超时 --> <setting name="defaultStatementTimeout" value="25000"/> </settings>typeAliases元素typeAliases元素的作用是给JavaBean取别名,不便咱们在mappeer配置文件中应用 ...

August 10, 2020 · 3 min · jiezi

关于spring:掌门教育微服务体系Solar第3弹Nacos企业级落地下篇

联席作者:谢璐 谢庆芳 伊安娜 任浩军郑重鸣谢:Nacos - 彦林,Spring Cloud Alibaba - 小马哥、洛夜,Nacos 社区 - 张龙(pader)、春少(chuntaojun) 相干文章举荐: 掌门教育微服务体系 Solar | 阿里巴巴 Nacos 企业级落地上篇掌门教育微服务体系 Solar | 阿里巴巴 Nacos 企业级落地中篇前言在高速倒退的时候,公司规模越来越大,老师人数越来越多,这时候公司不能铺太多人去做经营与服务,必须进步每个人效,这就须要技术驱动。因而掌门教育转变成一家技术驱动型的公司,如果被迫成为一家靠资金驱动的公司就活不下去了。-- 张翼(掌门教育创始人兼CEO) 掌门教育自2014年正式转型在线教育以来,秉承“让教育共享智能,让学习高效高兴”的主旨和愿景,经验云计算、大数据、人工智能、 AR / VR / MR 以及现今最火的 5G ,始终保持用科技赋能教育。掌门教育的业务近几年失去了疾速倒退,特地是往年的疫情,使在线教育成为了新的风口,也给掌门教育新的时机。 随着业务规模进一步扩充,流量进一步暴增,微服务数目进一步增长,使老的微服务体系所采纳的注册核心 Eureka 不堪重负,同时 Spring Cloud 体系曾经演进到第二代,第一代的 Eureka 注册核心曾经不大适宜当初的业务逻辑和规模,同时它目前被 Spring Cloud 官网置于保护模式,将不再向前倒退。如何抉择一个更为优良和实用的注册核心,这个课题就摆在了掌门人的背后。通过对 Alibaba Nacos 、HashiCorp Consul等开源注册核心做了深刻的调研和比拟,最终选定 Alibaba Nacos 做微服务体系 Solar 中的新注册核心。 背景故事基础架构部抉择新的注册核心,测试组须要配合对业界成熟的注册核心产品做剖析和比拟。因为掌门教育采纳的是比拟污浊的 Spring Cloud 技术栈,所以咱们须要围绕它的注册核心,从测试角度,进行性能和性能上钻研。 Spring Cloud 技术栈官网反对 Netflix Eureka ,HashiCorp Consul ,Zookeeper 三个注册核心,它们能够相互间实现无缝迁徙,Alibaba Nacos 是新加盟 Spring Cloud 技术栈的新成员。测试组的同学们对上述四个注册核心做了一一钻研和剖析,鉴于工夫紧迫,除了 Eureka 和 Nacos 之外,其它两个中间件未做深刻的功能测试和性能测试。上面提供来自阿里巴巴 Nacos 官网某次业界宣讲的材料截图以供大家参考: ...

August 10, 2020 · 4 min · jiezi

关于spring:Spring事务的传播行为案例分析

简介: 网上对于Spring事务流传性以及隔离型的文章漫天盖地,还有不负责任的间接复制名词意思,文章尽管很多却是看的云里雾里,咱们明天将给出案例别离和大家一起学习。 网上对于Spring事务流传性以及隔离型的文章漫天盖地,还有不负责任的间接复制名词意思,文章尽管很多却是看的云里雾里,咱们明天将给出案例别离和大家一起学习。1、spring给出常常面试的考点Spring事务的4个个性含意---这个很容易了解 2、spring事务流传个性的定义以及案例剖析  一、事务的个性ACID这四个英文单词拼写我始终记不住,求记忆办法 原子性(Atomicity):事务是一系列原子操作,要么全副胜利,要么全副失败。一致性(Consistency):一旦实现(不论是胜利还是失败),确保它所在的一系列业务状态保持一致,状态都是胜利,或者都是失败,不能一部分胜利一部分失败。隔离性(Isolation):不同事务同时进行某项业务,解决雷同的数据时候,须要保障事务之间互相独立,相互之间数据不影响。持久性(Durability):一旦事务实现,无论产生什么系统性谬误,事务执行后的数据都被长久化了,不会因为重启或其余操作对数据进行更改。二、spring事务流传个性的定义以及案例剖析 咱们先给出定义再别离进行简略的代码剖析 给出百度图片,请大家参考,首先生命力如果想在工程中使用事务spring 的xml必须开启事务,以下这些个性个别都是在xml属性中进行配置。 <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">相似这种的配置肯定要有,否则万事具备只欠东风,这个是DB事务有JTA和JPA以及Herbernate等,这里就不开展阐明,可自行百度。 三、案例解析事务流传7大行为1、无事务,这个时候id 为16的第一次插入胜利,第二次插入的时候失败,库中留存第一次的数据 无事务运行 2、propagation_required,默认事务的流传行为required,在进行试验2的时候将表中id为16的数据先删除免得影响接下来的测试。@Transactional(propagation=Propagation.REQUIRED) ==  @Transactional这两个的作用是一样的没有事务创立一个事务执行,![ qq'q](http://college.creditease.cn/resources/upload/image/20200804/1596529605681003338.jpeg)) 事务的流传特行为为required 后果是因为主键抵触将事务进行了回滚,所以两条数据都没有插入进去。 3、propagation_supports,如果以后程序存在事务就退出该事务运行,如果不存在事务则在非事务中运行 事务的流传行为性为supports 因为调用方未用事务那么就在非事务中运行,所以插入了first的第一条数据。 4、propagation_mandatory,必须在一个事务中运行,否则就会抛出异样mandatory 这个单词有强制性的意思咱们默认用required 而不必mandatory,是因为mandatory不能主动创立事务。 事务的流传行为为manatory 因为调用的外层没有事务,所以两条数据没有插入。大家想想上面这种写法会产生什么景象 事务的流传行为mandatory 5、propagation_ required _new,不论事务是不是存在,都会另起一个事务,如果事务存在则将以后事务挂起,从新执行新加的事务 事务的流传行为required_new 后果和require一样,两条数据都没有入库,惟一健抵触导致第一条数据回滚,大家能够思考下我上面这两种状况。 情景1新起的事务抛出异样会不会让外围事务回滚? 情景2外围事务失败会不会导致新起事务已提交的回滚? 6、 propagation_ not _support,示意不在事务中运行,如果以后存在事务则将事务挂起![qqq ](http://college.creditease.cn/resources/upload/image/20200804/1596529886418082560.jpeg)) 事务的流传行为not_suppoted 这种情景下,如果你依据我的思路一步走的应该能够想到id 为17的入库,第二条主键抵触尽管然而notSupportSonTransationsl()这个办法没有事务所以不影响第一条入库状况,然而外围事务id为16的要进行回滚了,所以库中只有一条数据id=17的。 7、 propagation_never,示意以后办法不能运行在事务当中,如果有事务则会抛出异样---->Existing transaction found for transaction marked with propagation 'never' 事务的流传行为NEVER 8、 propagation_nested,这种嵌套的事务,外围如果没有事务则本人另起一个事务,可独立与外围事务进行独自的提交或者回滚(这句话不要了解错了),上面这个案例同样的数据一条也没有落入库中, 事务的流传行为nested 事务的流传行为级别简略的演示结束 作者:宜信技术学院,王巧敏

August 10, 2020 · 1 min · jiezi

关于spring:精讲RestTemplate第5篇DELETEPUT等请求方法使用详解

本文是精讲RestTemplate第5篇,前篇的blog拜访地址如下: 精讲RestTemplate第1篇-在Spring或非Spring环境下如何应用精讲RestTemplate第2篇-多种底层HTTP客户端类库的切换精讲RestTemplate第3篇-GET申请应用办法详解精讲RestTemplate第4篇-POST申请办法应用详解为了不便后续开发测试,首先介绍一个网站给大家。JSONPlaceholder是一个提供收费的在线REST API的网站,咱们在开发时能够应用它提供的url地址测试下网络申请以及申请参数。或者当咱们程序须要获取一些模仿数据、模仿图片时也能够应用它。如果您浏览完本文章,感觉对您有帮忙,请帮忙点个赞,您的反对是我不竭的创作能源 一、RESTful格调与HTTP method相熟RESTful格调的敌人,应该理解RESTful格调API应用HTTP method表白对资源的操作。 罕用HTTP办法RESTful格调语义(操作)GET查问、获取数据POST新增、提交数据DELETE删除数据PUT更新、批改数据HEAD获取HTTP申请头数据OPTIONS判断URL提供的以后API反对哪些HTTP method办法在后面的章节,我曾经为大家具体的介绍了RestTemplate的GET和POST的相干的应用办法,本节来为大家介绍DELETE、PUT、HEAD、OPTIONS。 二、应用 DELETE办法去删除资源删除一个曾经存在的资源,应用RestTemplate的delete(uri)办法。该办法会向URL代表的资源发送一个HTTP DELETE办法申请。 @Testvoid testDelete() { String url = "http://jsonplaceholder.typicode.com/posts/1"; restTemplate.delete(url);}在后面章节测试类的根底上,写如上代码的测试用例。下面代码含意为删除posts列表外面的第1个帖子。 二、应用PUT办法去批改资源批改一个曾经存在的资源,应用RestTemplate的put()办法。该办法会向URL代表的资源发送一个HTTP PUT办法申请。 @Testvoid testPut() { // 申请地址 String url = "http://jsonplaceholder.typicode.com/posts/1"; // 要发送的数据对象(批改数据) PostDTO postDTO = new PostDTO(); postDTO.setUserId(110); postDTO.setTitle("zimug 公布文章"); postDTO.setBody("zimug 公布文章 测试内容"); // 发送PUT申请 restTemplate.put(url, postDTO);}下面代码RESTful格调语义是:批改posts列表外面的第1个帖子。 三、通用申请办法exchange办法exchange办法是一个通用的办法,它能够发送GET、POST、DELETE、PUT等等HTTP办法申请。 上面的两种形式发送GET申请成果是一样的//应用getForEntity发送GET申请ResponseEntity<PostDTO> responseEntity = restTemplate.getForEntity(url, PostDTO.class);//应用exchange发送GET申请ResponseEntity<PostDTO> responseEntity = restTemplate.exchange(url, HttpMethod.GET, null, PostDTO.class);上面的两种形式发送POST申请成果是一样的// 应用postForEntity发送POST申请ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, postDTO, String.class);// 应用exchange发送POST申请ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.POST,null, String.class);上面的两种形式发送DELETE申请成果是一样的,只是一个有返回值,一个返回值为void// 应用delete发送DELETE申请,返回值为voidrestTemplate.delete(url);// 应用exchange发送DELETE申请ResponseEntity<String> result = restTemplate.exchange(url, HttpMethod.DELETE,null,String.class);下面为大家举了几个用exchange()发送申请的例子,exchange()还能针对很多的HTTP method类型发送申请,是通用办法! ...

August 10, 2020 · 1 min · jiezi

关于spring:精讲RestTemplate第5篇DELETEPUT等请求方法使用详解

本文是精讲RestTemplate第5篇,前篇的blog拜访地址如下: 精讲RestTemplate第1篇-在Spring或非Spring环境下如何应用精讲RestTemplate第2篇-多种底层HTTP客户端类库的切换精讲RestTemplate第3篇-GET申请应用办法详解精讲RestTemplate第4篇-POST申请办法应用详解为了不便后续开发测试,首先介绍一个网站给大家。JSONPlaceholder是一个提供收费的在线REST API的网站,咱们在开发时能够应用它提供的url地址测试下网络申请以及申请参数。或者当咱们程序须要获取一些模仿数据、模仿图片时也能够应用它。如果您浏览完本文章,感觉对您有帮忙,请帮忙点个赞,您的反对是我不竭的创作能源 一、RESTful格调与HTTP method相熟RESTful格调的敌人,应该理解RESTful格调API应用HTTP method表白对资源的操作。 罕用HTTP办法RESTful格调语义(操作)GET查问、获取数据POST新增、提交数据DELETE删除数据PUT更新、批改数据HEAD获取HTTP申请头数据OPTIONS判断URL提供的以后API反对哪些HTTP method办法在后面的章节,我曾经为大家具体的介绍了RestTemplate的GET和POST的相干的应用办法,本节来为大家介绍DELETE、PUT、HEAD、OPTIONS。 二、应用 DELETE办法去删除资源删除一个曾经存在的资源,应用RestTemplate的delete(uri)办法。该办法会向URL代表的资源发送一个HTTP DELETE办法申请。 @Testvoid testDelete() { String url = "http://jsonplaceholder.typicode.com/posts/1"; restTemplate.delete(url);}在后面章节测试类的根底上,写如上代码的测试用例。下面代码含意为删除posts列表外面的第1个帖子。 二、应用PUT办法去批改资源批改一个曾经存在的资源,应用RestTemplate的put()办法。该办法会向URL代表的资源发送一个HTTP PUT办法申请。 @Testvoid testPut() { // 申请地址 String url = "http://jsonplaceholder.typicode.com/posts/1"; // 要发送的数据对象(批改数据) PostDTO postDTO = new PostDTO(); postDTO.setUserId(110); postDTO.setTitle("zimug 公布文章"); postDTO.setBody("zimug 公布文章 测试内容"); // 发送PUT申请 restTemplate.put(url, postDTO);}下面代码RESTful格调语义是:批改posts列表外面的第1个帖子。 三、通用申请办法exchange办法exchange办法是一个通用的办法,它能够发送GET、POST、DELETE、PUT等等HTTP办法申请。 上面的两种形式发送GET申请成果是一样的//应用getForEntity发送GET申请ResponseEntity<PostDTO> responseEntity = restTemplate.getForEntity(url, PostDTO.class);//应用exchange发送GET申请ResponseEntity<PostDTO> responseEntity = restTemplate.exchange(url, HttpMethod.GET, null, PostDTO.class);上面的两种形式发送POST申请成果是一样的// 应用postForEntity发送POST申请ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, postDTO, String.class);// 应用exchange发送POST申请ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.POST,null, String.class);上面的两种形式发送DELETE申请成果是一样的,只是一个有返回值,一个返回值为void// 应用delete发送DELETE申请,返回值为voidrestTemplate.delete(url);// 应用exchange发送DELETE申请ResponseEntity<String> result = restTemplate.exchange(url, HttpMethod.DELETE,null,String.class);下面为大家举了几个用exchange()发送申请的例子,exchange()还能针对很多的HTTP method类型发送申请,是通用办法! ...

August 10, 2020 · 1 min · jiezi

关于spring:Spring事务的传播行为案例分析

网上对于Spring事务流传性以及隔离型的文章漫天盖地,还有不负责任的间接复制名词意思,文章尽管很多却是看的云里雾里,咱们明天将给出案例别离和大家一起学习。1、spring给出常常面试的考点Spring事务的4个个性含意---这个很容易了解 2、spring事务流传个性的定义以及案例剖析  一、事务的个性ACID这四个英文单词拼写我始终记不住,求记忆办法 原子性(Atomicity):事务是一系列原子操作,要么全副胜利,要么全副失败。一致性(Consistency):一旦实现(不论是胜利还是失败),确保它所在的一系列业务状态保持一致,状态都是胜利,或者都是失败,不能一部分胜利一部分失败。隔离性(Isolation):不同事务同时进行某项业务,解决雷同的数据时候,须要保障事务之间互相独立,相互之间数据不影响。持久性(Durability):一旦事务实现,无论产生什么系统性谬误,事务执行后的数据都被长久化了,不会因为重启或其余操作对数据进行更改。二、spring事务流传个性的定义以及案例剖析 咱们先给出定义再别离进行简略的代码剖析 给出百度图片,请大家参考,首先生命力如果想在工程中使用事务spring 的xml必须开启事务,以下这些个性个别都是在xml属性中进行配置。 <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">相似这种的配置肯定要有,否则万事具备只欠东风,这个是DB事务有JTA和JPA以及Herbernate等,这里就不开展阐明,可自行百度。 三、案例解析事务流传7大行为1、无事务,这个时候id 为16的第一次插入胜利,第二次插入的时候失败,库中留存第一次的数据 无事务运行 2、propagation_required,默认事务的流传行为required,在进行试验2的时候将表中id为16的数据先删除免得影响接下来的测试。@Transactional(propagation=Propagation.REQUIRED) ==  @Transactional这两个的作用是一样的没有事务创立一个事务执行,![qq'q](http://college.creditease.cn/...事务的流传特行为为required后果是因为主键抵触将事务进行了回滚,所以两条数据都没有插入进去。 3、propagation_supports,如果以后程序存在事务就退出该事务运行,如果不存在事务则在非事务中运行 事务的流传行为性为supports因为调用方未用事务那么就在非事务中运行,所以插入了first的第一条数据。 4、propagation_mandatory,必须在一个事务中运行,否则就会抛出异样mandatory 这个单词有强制性的意思咱们默认用required 而不必mandatory,是因为mandatory不能主动创立事务。事务的流传行为为manatory因为调用的外层没有事务,所以两条数据没有插入。大家想想上面这种写法会产生什么景象事务的流传行为mandatory 5、propagation_ required _new,不论事务是不是存在,都会另起一个事务,如果事务存在则将以后事务挂起,从新执行新加的事务事务的流传行为required_new后果和require一样,两条数据都没有入库,惟一健抵触导致第一条数据回滚,大家能够思考下我上面这两种状况。 情景1新起的事务抛出异样会不会让外围事务回滚? 情景2外围事务失败会不会导致新起事务已提交的回滚? 6、 propagation_ not _support,示意不在事务中运行,如果以后存在事务则将事务挂起![qqq](http://college.creditease.cn/...事务的流传行为not_suppoted这种情景下,如果你依据我的思路一步走的应该能够想到id 为17的入库,第二条主键抵触尽管然而notSupportSonTransationsl()这个办法没有事务所以不影响第一条入库状况,然而外围事务id为16的要进行回滚了,所以库中只有一条数据id=17的。 7、 propagation_never,示意以后办法不能运行在事务当中,如果有事务则会抛出异样---->Existing transaction found for transaction marked with propagation 'never'事务的流传行为NEVER 8、 propagation_nested,这种嵌套的事务,外围如果没有事务则本人另起一个事务,可独立与外围事务进行独自的提交或者回滚(这句话不要了解错了),上面这个案例同样的数据一条也没有落入库中,事务的流传行为nested 事务的流传行为级别简略的演示结束 作者:宜信技术学院,王巧敏

August 10, 2020 · 1 min · jiezi

关于spring:使用java-API进行zip递归压缩文件夹以及解压

一、概述在本篇文章中,给大家介绍一下如何将文件进行zip压缩以及如何对zip包解压。所有这些都是应用Java提供的外围库java.util.zip来实现的。 二、压缩文件首先咱们来学习一个简略的例子-压缩单个文件。将一个名为test1.txt的文件压缩到一个名为Compressed.zip的zip文件中。 public class ZipFile { public static void main(String[] args) throws IOException { //输入压缩包 FileOutputStream fos = new FileOutputStream("src/main/resources/compressed.zip"); ZipOutputStream zipOut = new ZipOutputStream(fos); //被压缩文件 File fileToZip = new File("src/main/resources/test1.txt"); FileInputStream fis = new FileInputStream(fileToZip); //向压缩包中增加文件 ZipEntry zipEntry = new ZipEntry(fileToZip.getName()); zipOut.putNextEntry(zipEntry); byte[] bytes = new byte[1024]; int length; while((length = fis.read(bytes)) >= 0) { zipOut.write(bytes, 0, length); } zipOut.close(); fis.close(); fos.close(); }}三、压缩多个文件接下来,咱们看看如何将多个文件压缩为一个zip文件。咱们将把test1.txt和test2.txt压缩成multiCompressed.zip: public class ZipMultipleFiles { public static void main(String[] args) throws IOException { List<String> srcFiles = Arrays.asList("src/main/resources/test1.txt", "src/main/resources/test2.txt"); FileOutputStream fos = new FileOutputStream("src/main/resources/multiCompressed.zip"); ZipOutputStream zipOut = new ZipOutputStream(fos); //向压缩包中增加多个文件 for (String srcFile : srcFiles) { File fileToZip = new File(srcFile); FileInputStream fis = new FileInputStream(fileToZip); ZipEntry zipEntry = new ZipEntry(fileToZip.getName()); zipOut.putNextEntry(zipEntry); byte[] bytes = new byte[1024]; int length; while((length = fis.read(bytes)) >= 0) { zipOut.write(bytes, 0, length); } fis.close(); } zipOut.close(); fos.close(); }}四、压缩目录上面的例子,咱们将zipTest目录及该目录下的递归子目录文件,全都压缩到dirCompressed.zip中: ...

August 10, 2020 · 2 min · jiezi

关于spring:2020阿里字节跳动JAVA岗一线企业校招社招面试题合集

前言以下面试题全属于一线大厂社招以及校招的面试真题,各位在做这些题目对照本人的时候请平庸心看待,不要信念受挫。其实 做为致力于一线企业校招或者社招的你来说,能把每个常识模块的一小部分问题去深刻学习和总结,曾经很棒了!而后文末有我本人总结的一些答案和更多面试题的文档总结,须要能够自取!首先展现一下以下文档蕴含的路线图 根底排序实现原理和Collection实现原理和而的区别(编译之后)线程池的品种,区别和应用场景剖析线程池的实现原理和线程的调度过程线程池如何调优线程池的最大线程数目依据什么确定动静代理的几种形式HashMap的并发问题理解LinkedHashMap的利用吗反射的原理,反射创立类实例的三种形式是什么?可克隆接口实现原理,浅拷贝或深拷贝JavaNIO应用哈希表和hashmap的区别及实现原理,hashmap会问到数组索引,散列碰撞怎么解决数组列表和链接列表区别及实现原理反射中,Class.forName和ClassLoader区别字符串、字符串缓冲区、StringBuilder的区别?有没有可能2个不相等的对象有雷同的哈希码简述nio的最佳实际,比方netty,Mina树状图的实现原理Jvm相干类的实例化程序,比方父类静态数据,构造函数,字段,子类静态数据,构造函数,字段,他们的执行程序Jvm内存分代JAVA 8的内存分代改良JVM垃圾回收机制,何时触发MinorGC等操作JVM中一次残缺的GC流程(从ygc到fgc)是怎么的,重点讲讲对象如何降职到老年代,几种次要的jvm参数等你晓得哪几种垃圾收集器,各自的优缺点,重点讲下cms,G1新生代和老生代的内存回收策略伊甸园和幸存者的比例调配等深入分析了类加载器,双亲委派机制Jvm的编译优化对内存模型的了解,以及其在并发中的利用指令重排序,内存栅栏等Oom谬误,堆栈溢出谬误,permgen空间谬误Jvm罕用参数Tomcat构造,类加载器流程挥发性的语义,它润饰的变量肯定线程平安吗G1和cms区别,吞吐量优先和响应优先的垃圾收集器抉择说一说你对环境变量类门路的了解?如果一个类不在类门路下,为什么会抛出ClassNotFoundException异样,如果在不扭转这个类门路的后期下,怎样才能正确加载这个类?说一下强援用、软援用、弱援用、虚援用以及他们之间和GC的关系留神:因为面试题内容较多,在文章中我基本上简述了,文章里的面试题完整版以及答案和我集体的总结办法教训(面试学习和刷题笔记),都整顿有PDF完整版,有须要的关注我的公众号:前程有光即可获取JEC/并发相干线程本地用过么,原理是什么,用的时候要留神什么同步和锁的区别同步的原理,什么是自旋锁,偏差锁,轻量级锁,什么叫可重入锁,什么叫偏心锁和非偏心锁Concurrenthashmap具体实现及其原理,jdk 8下的改版用过哪些原子类,他们的参数以及原理是什么是什么,他会产生什么问题(ABA问题的解决,如退出批改次数、版本号)如果让你实现一个并发平安的链表,你会怎么做简述ConcurrentLinkedQueue和LinkedBlockingQueue的用途和不同之处简述AQS的实现原理和环屏障的用法,以及相互之间的差异?并发包中应用过哪些类?别离说说应用在什么场景?为什么要应用?洛克苏波特工具条件接口及其实现原理叉/退出框架的了解Jdk 8的并行流的了解分段锁的原理,锁力度减小的思考分布式相干杜博的底层实现原理和机制形容一个服务从公布到被生产的具体过程分布式系统怎么做服务治理接口的幂等性的概念消息中间件如何解决音讯失落问题杜博的服务申请失败怎么解决重连机制会不会造成谬误对分布式事务的了解如何实现负载平衡,有哪些算法能够实现?动物园管理员的用处,选举的原理是什么?数据的垂直拆分程度拆分.动物园管理员原理和实用场景动物园管理员观看机制Redis/ZK节点宕机如何解决分布式集群下如何做到惟一序列号如何做一个分布式锁用过哪些MQ,怎么用的,和其余MQ比拟有什么优缺点,MQ的连贯是线程平安的吗MQ零碎的数据如何保障不失落列举出你能想到的数据库分库分表策略;分库分表后,如何解决全表查问的问题.算法&数据结构&设计模式海量url去重类问题(布隆过滤器)数组和链表数据结构形容,各自的工夫复杂度二叉树遍历疾速排序B树相干的操作在工作中遇到过哪些设计模式,是如何利用的散列算法的有哪几种,优缺点,应用场景什么是一致性散列帕克斯算法在装璜器模式和代理模式之间,你如何抉择,请联合本身理论状况聊聊代码重构的步骤和起因,如果了解重构到模式?Redis&缓存相干红星(redis的并发竞争问题如何解决理解redis事务的操作吗)缓存机器增删如何对系统影响最小,一致性哈希的实现红系长久化的几种形式,优缺点是什么,怎么实现的红系的缓存生效策略缓存穿透的解决办法红系集群,高可用,原理Mysql里有2000 w数据,redis中只存20 w的数据,如何保障redis中的数据都是热点数据用Redis和任意语言实现一段歹意登录爱护的代码,限度1小时内每用户ID最多只能登录5次红系的数据淘汰策略网络相干Http1.0和HTTP1.1有什么区别TCP/IP协定Tcp三次握手和四次挥手的流程,为什么断开连接要4次,如果握手只有两次,会呈现什么工夫期待和敞开期待的区别说说你晓得的几种HTTP响应码当你用浏览器关上一个链接的时候,计算机做了哪些工作步骤TCP/IP如何保障可靠性,数据包有哪些数据组成长连贯与短连贯Http申请Get和POST的区别以及数据包格局简述tcp建设连贯3次握手,和断开连接4次握手的过程;敞开连贯时,呈现TIMEWAIT过多是由什么起因引起,是呈现在被动断开方还是被动断开方.其余Maven解决依赖抵触,快照版和发行版的区别Linux下IO模型有几种,各自的含意是什么理论场景问题,海量登录日志如何排序和解决sql操作,次要是索引和聚合函数的利用理论场景问题解决,典型的顶K问题线上bug解决流程如何从线上日志发现问题Linux利用哪些命令,查找哪里出了问题(例如io密集工作,cpu适度)场景问题,有一个第三方接口,有很多个线程去调用获取数据,当初规定每秒钟最多有10个线程同时调用它,如何做到.用三个线程按程序循环打印abc三个字母,比方abc abc.常见的缓存策略有哪些,你们我的项目中用到了什么缓存零碎,如何设计的设计一个秒杀零碎,30分钟没付款就主动敞开交易(并发会很高)请列出你所理解的性能测试工具后盾零碎怎么避免申请反复提交?有多个雷同的接口,我想客户端同时申请,而后只须要在第一个申请返回后果的时候返回给客户端这份面试题当然不止展现的这些内容,实际上像Spring Cloud、设计模式、Netty、Dubbo、数据结构等其余局部的面试内容均有波及,因为文章篇幅,就不全副在这里论述了,须要的小伙伴能够关注我的公众号:前程有光即可获取,以下是这份面试题的一些展现. 最初此份面试题总结一共317页,蕴含了面试可能问到的所有外围知识点以及答案,如果你能把这份面试题吃透,毫不客气的说你去阿里面试至多也是个P7岗,最初须要这份面试题的敌人关注我的公众号:前程有光即可全副获取!

August 9, 2020 · 1 min · jiezi

关于spring:精讲RestTemplate第4篇POST请求方法使用详解

本文是精讲RestTemplate第4篇,前篇的blog拜访地址如下: 精讲RestTemplate第1篇-在Spring或非Spring环境下如何应用精讲RestTemplate第2篇-多种底层HTTP客户端类库的切换精讲RestTemplate第3篇-GET申请应用办法详解如果您浏览完本文章,感觉对您有帮忙,请帮忙点个赞,您的反对是我不竭的创作能源 在上一节为大家介绍了RestTemplate的GET申请的两个办法:getForObject()和getForEntity()。其实POST申请办法和GET申请办法上大同小异,RestTemplate的POST申请也蕴含两个次要办法: postForObject()postForEntity()二者的次要区别在于,postForObject()返回值是HTTP协定的响应体。postForEntity()返回的是ResponseEntity,ResponseEntity是对HTTP响应的封装,除了蕴含响应体,还蕴含HTTP状态码、contentType、contentLength、Header等信息。 一、postForObject发送JSON格局申请写一个单元测试用例,测试用例的内容是向指定的URL提交一个Post(帖子). @SpringBootTestclass PostTests { @Resource private RestTemplate restTemplate; @Test void testSimple() { // 申请地址 String url = "http://jsonplaceholder.typicode.com/posts"; // 要发送的数据对象 PostDTO postDTO = new PostDTO(); postDTO.setUserId(110); postDTO.setTitle("zimug 公布文章"); postDTO.setBody("zimug 公布文章 测试内容"); // 发送post申请,并输入后果 PostDTO result = restTemplate.postForObject(url, postDTO, PostDTO.class); System.out.println(result); }}jsonplaceholder.typicode.com是一个能够提供在线收费RESTful测试服务的一个网站”/posts"服务接管PostDTO 参数对象,并将申请后果以JSON字符串的模式进行响应。响应后果就是申请参数对象对应的JSON字符串。所以postForObject办法第二个参数是申请数据对象,第三个参数是返回值类型最终将返回值的打印后果如下: 二、postForObject模仿表单数据提交上面给大家写一个应用postForObject模仿表单数据提交的例子,即:提交x-www-form-urlencoded格局的数据 @Testpublic void testForm() { // 申请地址 String url = "http://jsonplaceholder.typicode.com/posts"; // 申请头设置,x-www-form-urlencoded格局的数据 HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); //提交参数设置 MultiValueMap<String, String> map = new LinkedMultiValueMap<>(); map.add("title", "zimug 公布文章第二篇"); map.add("body", "zimug 公布文章第二篇 测试内容"); // 组装申请体 HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(map, headers); // 发送post申请,并打印后果,以String类型接管响应后果JSON字符串 String result = restTemplate.postForObject(url, request, String.class); System.out.println(result);}申请数据打印后果如下: ...

August 9, 2020 · 2 min · jiezi

关于spring:通过java程序JSch运行远程linux主机上的shell脚本

如果您看完文章之后,感觉对您有帮忙,请帮我点个赞,您的反对是我不竭的创作能源!如果您看完文章之后,感觉对您有帮忙,请帮我点个赞,您的反对是我不竭的创作能源!如果您看完文章之后,感觉对您有帮忙,请帮我点个赞,您的反对是我不竭的创作能源! 运行近程主机上的shell脚本上面的例子是教给大家如何通过java程序,运行近程主机上的shell脚本。(我讲的不是一个黑客学习教程,而是应用用户名明码去执行有用户认证资格的主机上的shell脚本)。并且通过java程序取得shell脚本的输入。首先通过maven坐标引入JSch依赖库,咱们正是通过JSch去执行近程主机上的脚本。 <dependency> <groupId>com.jcraft</groupId> <artifactId>jsch</artifactId> <version>0.1.55</version></dependency>当然以下java代码可执行的的前提是,近程主机曾经开明SSH服务(也就是咱们平时登录主机所应用的服务)。 近程shell脚本上面的代码放入一个文件:hello.sh,脚本的内容很简略只是用来测试,回显输入“hello <参数1> ” #! /bin/shecho "hello $1\n";而后我把它放到近程主机的/root目录上面,近程主机的IP是1.1.1.1(当然我实在测试时候不是这个IP,我不能把我的实在IP写到这个文章外面,免得被攻打)。并且在近程主机上,为这个脚本设置可执行权限,办法如下: $ chmod +x hello.sh本地java程序咱们能够应用上面的代码,去近程的linux 主机执行shell脚本,具体性能请看代码正文 import com.jcraft.jsch.*;import java.io.IOException;import java.io.InputStream;public class RunRemoteScript { //近程主机IP private static final String REMOTE_HOST = "1.1.1.1"; //近程主机用户名 private static final String USERNAME = ""; //近程主机明码 private static final String PASSWORD = ""; //SSH服务端口 private static final int REMOTE_PORT = 22; //会话超时工夫 private static final int SESSION_TIMEOUT = 10000; //管道流超时工夫(执行脚本超时工夫) private static final int CHANNEL_TIMEOUT = 5000; public static void main(String[] args) { //脚本名称及门路,与上文要对上 String remoteShellScript = "/root/hello.sh"; Session jschSession = null; try { JSch jsch = new JSch(); //SSH授信客户端文件地位,个别是用户主目录下的.ssh/known_hosts jsch.setKnownHosts("/home/zimug/.ssh/known_hosts"); jschSession = jsch.getSession(USERNAME, REMOTE_HOST, REMOTE_PORT); // 明码认证 jschSession.setPassword(PASSWORD); // 建设session jschSession.connect(SESSION_TIMEOUT); //建设可执行管道 ChannelExec channelExec = (ChannelExec) jschSession.openChannel("exec"); // 执行脚本命令"sh /root/hello.sh zimug" channelExec.setCommand("sh " + remoteShellScript + " zimug"); // 获取执行脚本可能呈现的谬误日志 channelExec.setErrStream(System.err); //脚本执行后果输入,对于程序来说是输出流 InputStream in = channelExec.getInputStream(); // 5 秒执行管道超时 channelExec.connect(CHANNEL_TIMEOUT); // 从近程主机读取输出流,取得脚本执行后果 byte[] tmp = new byte[1024]; while (true) { while (in.available() > 0) { int i = in.read(tmp, 0, 1024); if (i < 0) break; //执行后果打印到程序控制台 System.out.print(new String(tmp, 0, i)); } if (channelExec.isClosed()) { if (in.available() > 0) continue; //获取退出状态,状态0示意脚本被正确执行 System.out.println("exit-status: " + channelExec.getExitStatus()); break; } try { Thread.sleep(1000); } catch (Exception ee) { } } channelExec.disconnect(); } catch (JSchException | IOException e) { e.printStackTrace(); } finally { if (jschSession != null) { jschSession.disconnect(); } } }}最终在本地控制台,取得近程主机上shell脚本的执行后果。如下 ...

August 7, 2020 · 2 min · jiezi

关于spring:MinIO很强让我放弃FastDFS拥抱MinIO的8个理由

目前可用于文件存储的网络服务抉择有很多,比方阿里云OSS、七牛云、腾讯云等等,然而免费都有点小贵。为了帮公司节约老本,之前始终是应用fastDFS作为文件服务器,精确的说是图片服务器。直到我发现了MinIO,我决定放弃FastDFS。对于MinIO的应用办法,我就不说了。大家去看MinIO官网地址:docs.min.io/cn/ ,十分具体。我就从比照的角度来说说我为什么果决的放弃了fastDFS,转而应用MinIO作为图片存储服务器。 理由一:装置部署(运维)复杂度之前公司在应用fastDFS的时候,只有多数的几个人可能把握fasdtDFS的部署构造。所以只有呈现有点问题,可能顶上的只有这么几个人。如果将一个fastDFS分布式服务部署实现,须要具备以下的常识 linux根底的目录操作罕用的分布式主从原理C语言代码的编译nginx装置部署nginx插件的应用(防盗链)如果仅仅是下面的这些基础知识,安顿几个程序员学一学还好说。次要是fastdfs的部署构造之简单,如果我长时间不回顾,本人都会忘了这简单的架构是怎么回事。当我看到MinIO的装置过程之后,以及分布式的部署命令之后(分布式MinIO疾速入门),放弃fastDFS的信心就曾经做出了一大半。说白了:FastDFS的部署不过是整机的组装过程,须要你去了解fastDFS的架构设计,才可能正确的装置部署。MinIO在装置的过程是黑盒的,你不必去深刻关注它的架构,也不须要你进行整机组装,基本上能够做到开箱即用。一般的技术人员就可能参加前期运维。 理由二:文档我感觉从我晓得fastDFS开始,也有十年了。居然没有官网文档,所有的文档全是某某公司的本人总结的文档,或者是某某网友本人总结的文档。从这点上看fastDFS真的是落荒而逃,当然阿里余庆大神在做这个我的项目的时候可能也没有思考到起初会有这么多人用。即应用的人多了,在余庆大神眼里可能感觉这只是本人开发的一个小玩具,没有持续深刻经营的必要。 理由三:开源我的项目经营组织fastdfs是阿里余庆做的一个集体我的项目,在一些互联网守业公司中有利用,没有官网,不沉闷,6个contributors。目前曾经很少做更新。MinIO目前是由2014年在硅谷创建的公司MinIO.Inc经营的开源我的项目,社区论坛的活跃度目前也十分的不错。 理由四:UI界面咱们都晓得fastDFS默认是不带UI界面的,看看MinIO的界面吧。这个界面不须要你独自的部署,和服务端一并装置。开箱即用,爱了爱了。 理由五:性能MinIO号称是世界上速度最快的对象存储服务器。在规范硬件上,对象存储的读/写速度最高能够达到183 GB/s和171 GB/s。对于fastDFS我已经单线程测试写了20万个文件,总共200G,大概用时10个小时。总体上是很难达到MinIO“号称的”以G为单位的每秒读写速度。 理由六:容器化反对MinIO提供了与k8s、etcd、docker等容器化技术深度集成计划,能够说就是为了云环境而生的。这点是FastDFS不具备的。 理由七:丰盛的SDK反对fastDFS目前提供了 C 和 Java SDK ,以及 PHP 扩大 SDK。下图是MinIO提供的SDK反对,MinIO简直提供了所有支流开发语言的SDK以及文档。同志们,重要的是文档。 不是说PHP不支流啊,不想引战。求生欲很强。 理由八:AWS S3规范兼容Amazon的S3 API是对象存储畛域的事实标准。MinIO是S3兼容性的事实上的规范,是第一个采纳API和第一个增加对S3 Select反对的规范之一。包含微软Azure在内的750多家公司应用MinIO的S3网关,这一数字超过了业内其余公司的总和。 什么意思?就是说你当初为了节约老本应用MinIO,等你的公司壮大了、有钱了。不想本人运维基础设施了,你就能够把对象存储放到云上,只有云厂商反对S3规范,你的应用程序是不须要从新开发的。 欢送关注我的博客,外面有很多精品合集本文转载注明出处(必须带连贯,不能只转文字):字母哥博客。感觉对您有帮忙的话,帮我点赞、分享!您的反对是我不竭的创作能源! 。另外,笔者最近一段时间输入了如下的精品内容,期待您的关注。 《手摸手教你学Spring Boot2.0》《Spring Security-JWT-OAuth2一本通》《实战前后端拆散RBAC权限管理系统》《实战SpringCloud微服务从青铜到王者》《VUE深入浅出系列》

August 6, 2020 · 1 min · jiezi

关于spring:两年经验拿到蚂蚁金服字节offer附上金九银十BAT面试核心知识点整理

前言我本人是本科毕业后在老东家干了两年多,老东家算是一家”小公司”(毕竟这年头没有 BAT 或 TMD 的 title 都不好意思报出身),毕业这两年多我也没有在大厂待过,因而找坑的时候是十分十分虚的。迫于心慌,我好好思考了一阵来给本人打气,过后真正找坑和筹备面试的过程大略分为这几个阶段: 面试筹备反思:本人是不是真的要到职,如果不到职,在老东家接下来应该做什么能力持续晋升?定位:我在硬性技能(编码、架构)上的短处在哪?我在软技能(沟通,团队)上的短处在哪?这步顺带写了简历寻找平台:哪些平台能同时满足:1、有挑战有回升空间;2、合乎我的定位方向;3、团队气氛和老东家一样好找人内推:根本都是在 v2 上找的当你真的决定要跳槽面试的时候就得最本人的知做一个小总结了,找出本人的技术短板去补救,把本人的学习路线给整理出来会事倍功半,上面附上我本人的温习路线。 就一个JVM就能梳理出这么多知识点,从而能够看出总结本人的温习路线是一个如许重要的事件,这里只是展现我总结的一部分,整个路线包含源码框架,并发专题,JVM性能调优,mysql,分布式,微服务等等。我都总结出了每一小步的温习路线,须要这份温习路线的:关注我的公众号前程有光即可获取 上面是我本人依据下面的温习路线图总记得温习文档,文档内容包含:数据结构与算法,JVM内存构造、垃圾回收器、回收算法、GC、并发编程相干(多线程、线程池等)、NIO/BIO、性能优化、设计模式、Spring框架:分布式相干:Redis缓存、统一Hash算法、分布式存储、负载平衡等,微服务以及Docker容器等。获取形式在文末上面为局部的内容和面试题展现 JVMjava中会存在内存透露吗,请简略形容。64 位 JVM 中,int 的长度是少数?Serial 与 Parallel GC 之间的不同之处?32 位和 64 位的 JVM,int 类型变量的长度是少数?Java 中 WeakReference 与 SoftReference 的区别?JVM 选项 -XX:+UseCompressedOops 有什么作用?为什么要应用怎么通过 Java 程序来判断 JVM 是 32 位 还是 64位?32 位 JVM 和 64 位 JVM 的最大堆内存别离是少数?JRE、JDK、JVM 及 JIT 之间有什么不同?解释 Java 堆空间及 GC? Redis什么是 Redis?Redis 与其余 key-value 存储有什么不同?Redis 的数据类型?应用 Redis 有哪些益处?Redis 相比 Memcached 有哪些劣势?Memcache 与 Redis 的区别都有哪些?Redis 是单过程单线程的?一个字符串类型的值能存储最大容量是多少?Redis长久化机制 ...

August 5, 2020 · 1 min · jiezi

关于spring:两年经验拿到蚂蚁金服字节offer附上金九银十BAT面试核心知识点整理

前言我本人是本科毕业后在老东家干了两年多,老东家算是一家”小公司”(毕竟这年头没有 BAT 或 TMD 的 title 都不好意思报出身),毕业这两年多我也没有在大厂待过,因而找坑的时候是十分十分虚的。迫于心慌,我好好思考了一阵来给本人打气,过后真正找坑和筹备面试的过程大略分为这几个阶段: 面试筹备反思:本人是不是真的要到职,如果不到职,在老东家接下来应该做什么能力持续晋升?定位:我在硬性技能(编码、架构)上的短处在哪?我在软技能(沟通,团队)上的短处在哪?这步顺带写了简历寻找平台:哪些平台能同时满足:1、有挑战有回升空间;2、合乎我的定位方向;3、团队气氛和老东家一样好找人内推:根本都是在 v2 上找的当你真的决定要跳槽面试的时候就得最本人的知做一个小总结了,找出本人的技术短板去补救,把本人的学习路线给整理出来会事倍功半,上面附上我本人的温习路线。 就一个JVM就能梳理出这么多知识点,从而能够看出总结本人的温习路线是一个如许重要的事件,这里只是展现我总结的一部分,整个路线包含源码框架,并发专题,JVM性能调优,mysql,分布式,微服务等等。我都总结出了每一小步的温习路线,须要这份温习路线的:关注我的公众号前程有光即可获取 上面是我本人依据下面的温习路线图总记得温习文档,文档内容包含:数据结构与算法,JVM内存构造、垃圾回收器、回收算法、GC、并发编程相干(多线程、线程池等)、NIO/BIO、性能优化、设计模式、Spring框架:分布式相干:Redis缓存、统一Hash算法、分布式存储、负载平衡等,微服务以及Docker容器等。获取形式在文末上面为局部的内容和面试题展现 JVMjava中会存在内存透露吗,请简略形容。64 位 JVM 中,int 的长度是少数?Serial 与 Parallel GC 之间的不同之处?32 位和 64 位的 JVM,int 类型变量的长度是少数?Java 中 WeakReference 与 SoftReference 的区别?JVM 选项 -XX:+UseCompressedOops 有什么作用?为什么要应用怎么通过 Java 程序来判断 JVM 是 32 位 还是 64位?32 位 JVM 和 64 位 JVM 的最大堆内存别离是少数?JRE、JDK、JVM 及 JIT 之间有什么不同?解释 Java 堆空间及 GC? Redis什么是 Redis?Redis 与其余 key-value 存储有什么不同?Redis 的数据类型?应用 Redis 有哪些益处?Redis 相比 Memcached 有哪些劣势?Memcache 与 Redis 的区别都有哪些?Redis 是单过程单线程的?一个字符串类型的值能存储最大容量是多少?Redis长久化机制 ...

August 5, 2020 · 1 min · jiezi

关于spring:在IntelliJ-IDEA中多线程并发代码的调试方法

通常来说,多线程的并发及条件断点的debug是很难实现的,或者本篇文章会给你提供一个敌对的调试办法。让你在多线程开发过程中的调试更加的对症下药。 咱们将通过一个例子来学习。在这里,我编写了一个多线程程序来计算此数学问题:100! + 100000!。即:100的阶乘 + 100000的阶乘。 数学不好的同学看这里,100 阶乘就是:1 2 3 …… 100 = ? ,简写为100!import java.math.BigInteger;public class MathProblemSolver { //开启两个线程 public static void main(String arg[]){ //第一个线程计算 100! FactorialCalculatingThread thread1 = new FactorialCalculatingThread(100); //第二个线程计算 100000! FactorialCalculatingThread thread2 = new FactorialCalculatingThread(100000); thread1.setName("Thread 1"); thread2.setName("Thread 2"); thread1.start(); thread2.start(); try { thread1.join(); //线程Jion,以使主线程在“线程1”和“线程2”都返回后果之前不会进一步执行 thread2.join(); } catch (InterruptedException e) { e.printStackTrace(); } BigInteger result = thread1.getResult().add(thread2.getResult()); System.out.println("将两个线程的计算结果相加等于:" + result); } //用于阶乘计算的线程类 private static class FactorialCalculatingThread extends Thread { private BigInteger result = BigInteger.ONE; private long num; public FactorialCalculatingThread(long num) { this.num = num; } @Override public void run() { System.out.println(Thread.currentThread().getName() + " 开始阶乘的计算:" + num); factorialCalc(num); System.out.println(Thread.currentThread().getName() + "执行实现"); } //数的阶乘计算方法 public void factorialCalc(long num) { BigInteger f = new BigInteger("1"); for (int i = 2; i <= num; i++) f = f.multiply(BigInteger.valueOf(i)); result = f; } public BigInteger getResult() { return result; } }}下面的代码解释 ...

August 5, 2020 · 1 min · jiezi

关于spring:精讲RestTemplate第3篇GET请求使用方法详解

本文是精讲RestTemplate第3篇,前篇的blog拜访地址如下: 精讲RestTemplate第1篇-在Spring或非Spring环境下如何应用精讲RestTemplate第2篇-多种底层HTTP客户端类库的切换RestTemplate能够发送HTTP GET申请,常常应用到的办法有两个: getForObject()getForEntity()二者的次要区别在于,getForObject()返回值是HTTP协定的响应体。getForEntity()返回的是ResponseEntity,ResponseEntity是对HTTP响应的封装,除了蕴含响应体,还蕴含HTTP状态码、contentType、contentLength、Header等信息。 为了不便后续开发测试,首先介绍一个网站给大家。JSONPlaceholder是一个提供收费的在线REST API的网站,咱们在开发时能够应用它提供的url地址测试下网络申请以及申请参数。或者当咱们程序须要获取一些模仿数据、模仿图片时也能够应用它。一、 getForObject() 办法1.1.以String的形式承受申请后果数据在Spring Boot环境下写一个单元测试用例,以String类型接管响应后果信息 @SpringBootTestclass ResttemplateWithSpringApplicationTests { @Resource private RestTemplate restTemplate; @Test void testSimple() { String url = "http://jsonplaceholder.typicode.com/posts/1"; String str = restTemplate.getForObject(url, String.class); System.out.println(str); }}getForObject第二个参数为返回值的类型,String.class以字符串的模式承受getForObject响应后果, 1.2.以POJO对象的形式承受后果数据在Spring Boot环境下写一个单元测试用例,以java POJO对象接管响应后果信息 @Testpublic void testPoJO() { String url = "http://jsonplaceholder.typicode.com/posts/1"; PostDTO postDTO = restTemplate.getForObject(url, PostDTO.class); System.out.println(postDTO.toString());}输入打印后果如下: POJO的定义如下,依据JSON String的数据格式定义。 @Datapublic class PostDTO { private int userId; private int id; private String title; private String body;}1.3.以数组的形式接管申请后果拜访http://jsonplaceholder.typicode.com/posts 能够取得JSON数组形式的申请后果 ...

August 5, 2020 · 1 min · jiezi

关于spring:保姆级教程手把手教你实现一个SpringBoot的starter

引言上篇文章《天天用SpringBoot,它的主动拆卸原理却说不进去》咱们有说springBoot的主动拆卸怎么实现的(倡议最好先看下篇文章,因为前后有关系),这篇文章的话咱们就本人来实现一个SpringBoot的 starter吧。废话不多说咱们还是直入主题吧。什么是Spring Boot Starter呢?咱们间接来看看官网是怎么介绍的吧。 Starters are a set of convenient dependency descriptors that you can include in your application. You get a one-stop shop for all the Spring and related technologies that you need without having to hunt through sample code and copy-paste loads of dependency descriptors. For example, if you want to get started using Spring and JPA for database access, include the spring-boot-starter-data-jpa dependency in your project.纳尼,一大堆的英文,这还有趣味接着往下看吗?是不是看到这间接退出了。都到门口了,不进来喝杯茶再走嘛?看都看到这了还是接着持续往下看吧。咱们先不解释这一段话是什么意思,咱们能够看看starter的呈现给咱们解决了什么问题。咱们还是以上述官网的例子来进行阐明比如说咱们须要在Spring 中适应JPA来操作数据库。在没有springBoot-starter之前,咱们须要引入jpa的步骤 ...

August 4, 2020 · 3 min · jiezi

关于spring:超给力一键生成数据库文档数据库表结构逆向工程

一、解决什么问题数据库文档是咱们在企业我的项目开发中须要交付的文档,通常须要开发人员去手工编写。编写实现后,数据库产生变更又须要手动的进行批改,从而节约了大量的人力。并且这种文档并没有什么技术含量,被安顿做这个工作的程序员往往本人心里会有抵触情绪,乐观的预期本人在团队的地位,造成到职也是可能的。如上面的这种文档的内容: 笔者最近在github下面发现一个数据库文档生成工具:screw(螺丝钉)。该工具可能通过简略地配置,疾速的依据数据库表构造进行逆向工程,将数据库表构造及字段逆向生成为文档。 二、特点简洁、轻量、设计良好多数据库反对:MySQL、MariaDB、TIDB、Oracle、 SqlServer、PostgreSQL、Cache DB多种格局文档: html、word、 markdwon灵便扩大:反对用户自定义模板和展现款式批改(freemarker模板)三、依赖库探索mvn地方仓库查看最新版本,将如下的maven坐标引入到Spring Boot我的项目中去: <dependency> <groupId>cn.smallbun.screw</groupId> <artifactId>screw-core</artifactId> <version>1.0.3</version></dependency>从maven仓库的编译依赖中能够看到,screw-core其实现依赖了如下的内容。重点关注freemarker,因为该我的项目是应用freemarker作为模板生成文档。 除此之外,screw应用了HikariCP作为数据库连接池,所以: 你的Spring Boot我的项目须要引入HikariCP数据库连接池。依据你的数据库类型及版本,引入正确的JDBC驱动四、开始造作吧以上的工作都做好之后,咱们就能够来配置文档生成参数了。实现文档生成有两种形式,一种是写代码,一种是应用maven 插件。 我集体还是比拟喜爱应用代码的过后,写一个单元测试用例就能够了,绝对独立,应用形式也灵便。如果放在pom.xml的插件配置外面,让本就很简短的pom.xml变的更加的简短,不喜爱。所以maven插件的这种形式我就不给大家演示了,间接把上面的代码Ctrl + C/V到你的src/test/java目录下。简略的批改配置,运行就能够了 import cn.smallbun.screw.core.Configuration;import cn.smallbun.screw.core.engine.EngineConfig;import cn.smallbun.screw.core.engine.EngineFileType;import cn.smallbun.screw.core.engine.EngineTemplateType;import cn.smallbun.screw.core.execute.DocumentationExecute;import cn.smallbun.screw.core.process.ProcessConfig;import com.zaxxer.hikari.HikariConfig;import com.zaxxer.hikari.HikariDataSource;import org.junit.jupiter.api.Test;import javax.sql.DataSource;import java.util.ArrayList;public class ScrewTest { @Test void testScrew() { //数据源 HikariConfig hikariConfig = new HikariConfig(); hikariConfig.setDriverClassName("com.mysql.cj.jdbc.Driver"); hikariConfig.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/database"); hikariConfig.setUsername("db-username"); hikariConfig.setPassword("db-password"); //设置能够获取tables remarks信息 hikariConfig.addDataSourceProperty("useInformationSchema", "true"); hikariConfig.setMinimumIdle(2); hikariConfig.setMaximumPoolSize(5); DataSource dataSource = new HikariDataSource(hikariConfig); //生成配置 EngineConfig engineConfig = EngineConfig.builder() //生成文件门路 .fileOutputDir("d://") //关上目录 .openOutputDir(true) //生成文件类型:HTML .fileType(EngineFileType.HTML) //生成模板实现 .produceType(EngineTemplateType.freemarker) .build(); //疏忽表 ArrayList<String> ignoreTableName = new ArrayList<>(); ignoreTableName.add("test_user"); ignoreTableName.add("test_group"); //疏忽表前缀 ArrayList<String> ignorePrefix = new ArrayList<>(); ignorePrefix.add("test_"); //疏忽表后缀 ArrayList<String> ignoreSuffix = new ArrayList<>(); ignoreSuffix.add("_test"); ProcessConfig processConfig = ProcessConfig.builder() //指定生成逻辑、当存在指定表、指定表前缀、指定表后缀时,将生成指定表,其余表不生成、并跳过疏忽表配置 //依据名称指定表生成 .designatedTableName(new ArrayList<>()) //依据表前缀生成 .designatedTablePrefix(new ArrayList<>()) //依据表后缀生成 .designatedTableSuffix(new ArrayList<>()) //疏忽表名 .ignoreTableName(ignoreTableName) //疏忽表前缀 .ignoreTablePrefix(ignorePrefix) //疏忽表后缀 .ignoreTableSuffix(ignoreSuffix).build(); //配置 Configuration config = Configuration.builder() //版本 .version("1.0.0") //形容,文档名称 .description("数据库设计文档生成") //数据源 .dataSource(dataSource) //生成配置 .engineConfig(engineConfig) //生成配置 .produceConfig(processConfig) .build(); //执行生成 new DocumentationExecute(config).execute(); }}在测试用例外面运行下面的代码,就会主动生成数据库文档到fileOutputDir配置目录下。 ...

August 4, 2020 · 1 min · jiezi

关于spring:Spring-Cache缓存注解

Spring Cache缓存注解本篇文章代码示例在Spring Cache简略实现上的代码示例加以批改。只有应用public定义的办法才能够被缓存,而private办法、protected 办法或者应用default 修饰符的办法都不能被缓存。 当在一个类上应用注解时,该类中每个公共办法的返回值都将被缓存到指定的缓存项中或者从中移除。 @Cacheable@Cacheable注解属性一览: 属性名 作用与形容 cacheNames/value 指定缓存的名字,缓存应用CacheManager治理多个缓存Cache,这些Cache就是依据该属性进行辨别。对缓存的真正增删改查操作在Cache中定义,每个缓存Cache都有本人惟一的名字。 key 缓存数据时的key的值,默认是应用办法所有入参的值,能够应用SpEL表达式示意key的值。 keyGenerator 缓存的生成策略(键生成器),和key二选一,作用是生成键值key,keyGenerator可自定义。 cacheManager 指定缓存管理器(例如ConcurrentHashMap、Redis等)。 cacheResolver 和cacheManager作用一样,应用时二选一。 condition 指定缓存的条件(对参数判断,满足什么条件时才缓存),可用SpEL表达式,例如:办法入参为对象user则表达式能够写为condition = "#user.age>18",示意当入参对象user的属性age大于18才进行缓存。 unless 否定缓存的条件(对后果判断,满足什么条件时不缓存),即满足unless指定的条件时,对调用办法获取的后果不进行缓存,例如:unless = "result==null",示意如果后果为null时不缓存。 sync 是否应用异步模式进行缓存,默认false。 @Cacheable指定了被注解办法的返回值是可被缓存的。其工作原理是Spring首先在缓存中查找数据,如果没有则执行办法并缓存后果,而后返回数据。 缓存名是必须提供的,能够应用引号、Value或者cacheNames属性来定义名称。上面的定义展现了users缓存的申明及其注解的应用: @Cacheable("users")//Spring 3.x@Cacheable(value = "users")//Spring 从4.0开始新增了value别名cacheNames比value更达意,举荐应用@Cacheable(cacheNames = "users") 键生成器缓存的实质就是键/值对汇合。在默认状况下,缓存形象应用(办法签名及参数值)作为一个键值,并将该键与办法调用的后果组成键/值对。 如果在Cache注解上没有指定key, 则Spring会应用KeyGenerator来生成一个key。 package org.springframework.cache.interceptor;import java.lang.reflect.Method;@FunctionalInterfacepublic interface KeyGenerator {    Object generate(Object var1, Method var2, Object... var3);} Sping默认提供了SimpleKeyGenerator生成器。Spring 3.x之后废除了3.x 的DefaultKey Generator而用SimpleKeyGenerator取代,起因是DefaultKeyGenerator在有多个入参时只是简略地把所有入参放在一起应用hashCode()办法生成key值,这样很容易造成key抵触。SimpleKeyGenerator应用一个复合键SimpleKey来解决这个问题。通过其源码可得悉Spring生成key的规定。 /** * SimpleKeyGenerator源码的类门路参见{@link org.springframework.cache.interceptor.SimpleKeyGenerator} */ 从SimpleKeyGenerator的源码中能够发现其生成规定如下(附SimpleKey源码): 如果办法没有入参,则应用SimpleKey.EMPTY作为key(key = new SimpleKey())。如果只有一个入参,则应用该入参作为key(key = 入参的值)。如果有多个入参,则返回蕴含所有入参的一个SimpleKey(key = new SimpleKey(params))。package org.springframework.cache.interceptor;import java.io.Serializable;import java.util.Arrays;import org.springframework.util.Assert;import org.springframework.util.StringUtils;public class SimpleKey implements Serializable {    public static final SimpleKey EMPTY = new SimpleKey(new Object[0]);    private final Object[] params;    private final int hashCode;    public SimpleKey(Object... elements) {        Assert.notNull(elements, "Elements must not be null");        this.params = new Object[elements.length];        System.arraycopy(elements, 0, this.params, 0, elements.length);        this.hashCode = Arrays.deepHashCode(this.params);    }    public boolean equals(Object other) {        return this == other || other instanceof SimpleKey && Arrays.deepEquals(this.params, ((SimpleKey)other).params);    }    public final int hashCode() {        return this.hashCode;    }    public String toString() {        return this.getClass().getSimpleName() + " [" + StringUtils.arrayToCommaDelimitedString(this.params) + "]";    }} 如需自定义键生成策略,能够通过实现org.springframework.cache.interceptor.KeyGenerator接口来定义本人理论须要的键生成器。示例如下,自定义了一个MyKeyGenerator类并且实现(implements)了KeyGenerator以实现自定义的键值生成器: package com.example.cache.springcache;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.cache.interceptor.KeyGenerator;import org.springframework.cache.interceptor.SimpleKey;import java.lang.reflect.Method;/** * @author: 博客「成猿手册」 * @description: 为不便演示,这里自定义的键生成器只是在SimpleKeyGenerator根底上加了一些logger打印以区别自定义的Spring默认的键值生成器; */public class MyKeyGenerator implements KeyGenerator {    private static final Logger logger =  LoggerFactory.getLogger(MyKeyGenerator.class);    @Override    public Object generate(Object o, Method method, Object... objects) {        logger.info("执行自定义键生成器");        return generateKey(objects);    }    public static Object generateKey(Object... params) {        if (params.length == 0) {            logger.debug("本次缓存键名称:{}", SimpleKey.EMPTY);            return SimpleKey.EMPTY;        } else {            if (params.length == 1) {                Object param = params[0];                if (param != null && !param.getClass().isArray()) {                    logger.debug("本次缓存键名称:{}", params);                    return param;                }            }            SimpleKey simpleKey = new SimpleKey(params);            logger.debug("本次缓存键名称:{}", simpleKey.toString());            return simpleKey;        }    }} 同时在Spring配置文件中配置: <!-- 配置键生成器Bean --><bean id = "myKeyGenerator" class="com.example.cache.springcache.MyKeyGenerator" /> 应用示例如下: @Cacheable(cacheNames = "userId",keyGenerator = "myKeyGenerator")public User getUserById(String userId) 执行的打印后果如下: first query...14:50:29.901 [main] INFO com.example.cache.springcache.MyKeyGenerator - 执行自定义键生成器14:50:29.902 [main] DEBUG com.example.cache.springcache.MyKeyGenerator - 本次键名称:test00114:50:29.904 [main] INFO com.example.cache.springcache.MyKeyGenerator - 执行自定义键生成器14:50:29.904 [main] DEBUG com.example.cache.springcache.MyKeyGenerator - 本次键名称:test001query user by userId=test001querying id from DB...test001result object: com.example.cache.customize.entity.User@1a6c1270second query...14:50:29.927 [main] INFO com.example.cache.springcache.MyKeyGenerator - 执行自定义键生成器14:50:29.927 [main] DEBUG com.example.cache.springcache.MyKeyGenerator - 本次键名称:test001result object: com.example.cache.customize.entity.User@1a6c1270 @CachePut@CachePut注解属性与@Cacheable注解属性相比少了sync属性。其余用法基本相同: 属性名 作用与形容 cacheNames/value 指定缓存的名字,缓存应用CacheManager治理多个缓存Cache,这些Cache就是依据该属性进行辨别。对缓存的真正增删改查操作在Cache中定义,每个缓存Cache都有本人惟一的名字。 key 缓存数据时的key的值,默认是应用办法所有入参的值,能够应用SpEL表达式示意key的值。 keyGenerator 缓存的生成策略(键生成器),和key二选一,作用是生成键值key,keyGenerator可自定义。 ...

August 3, 2020 · 1 min · jiezi

关于spring:精讲RestTemplate第2篇多种底层HTTP客户端类库的切换

本文是精讲RestTemplate第2篇,前篇的blog拜访地址如下: 精讲RestTemplate第1篇-在Spring或非Spring环境下如何应用RestTemplate只是对其余的HTTP客户端的封装,其自身并没有实现HTTP相干的根底性能。其底层实现是能够配置切换的,咱们本大节就带着大家来看一下RestTemplate底层实现,及如何实现底层根底HTTP库的切换。 一、源码剖析RestTemplate有一个十分重要的类叫做HttpAccessor,能够了解为用于HTTP接触拜访的根底类。下图为源码: 从源码中咱们能够剖析出以下几点信息 RestTemplate 反对至多三种HTTP客户端库。 SimpleClientHttpRequestFactory。对应的HTTP库是java JDK自带的HttpURLConnection。HttpComponentsAsyncClientHttpRequestFactory。对应的HTTP库是Apache HttpComponents。OkHttp3ClientHttpRequestFactory。对应的HTTP库是OkHttpjava JDK自带的HttpURLConnection是默认的底层HTTP实现客户端SimpleClientHttpRequestFactory,即java JDK自带的HttpURLConnection不反对HTTP协定的Patch办法,如果心愿应用Patch办法,须要将底层HTTP客户端实现切换为Apache HttpComponents 或 OkHttp能够通过设置setRequestFactory办法,来切换RestTemplate的底层HTTP客户端实现类库。二、底层实现切换办法从开发人员的反馈,和网上的各种HTTP客户端性能以及易用水平评测来看,OkHttp 优于 Apache HttpComponents、Apache HttpComponents优于HttpURLConnection。所以我集体更倡议大家将底层HTTP实现切换为okHTTP。 以下所讲的切换办法,基于第一篇内容: 精讲RestTemplate第1篇-在Spring或非Spring环境下如何应用2.1.切换为okHTTP首先通过maven坐标将okHTTP的包引入到我的项目中来 <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>4.7.2</version></dependency>如果是spring 环境下通过如下形式应用OkHttp3ClientHttpRequestFactory初始化RestTemplate bean对象。 @Configurationpublic class ContextConfig { @Bean("OKHttp3") public RestTemplate OKHttp3RestTemplate(){ RestTemplate restTemplate = new RestTemplate(new OkHttp3ClientHttpRequestFactory()); return restTemplate; }}如果是非Spring环境,间接new RestTemplate(new OkHttp3ClientHttpRequestFactory()之后应用就能够了。 2.2.切换为Apache HttpComponents与切换为okHTTP办法相似、不再赘述。 <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.12</version></dependency>应用HttpComponentsClientHttpRequestFactory初始化RestTemplate bean对象 @Bean("httpClient")public RestTemplate httpClientRestTemplate(){ RestTemplate restTemplate = new RestTemplate(new HttpComponentsClientHttpRequestFactory()); return restTemplate;}欢送关注我的博客,外面有很多精品合集本文转载注明出处(必须带连贯,不能只转文字):字母哥博客。感觉对您有帮忙的话,帮我点赞、分享!您的反对是我不竭的创作能源! 。另外,笔者最近一段时间输入了如下的精品内容,期待您的关注。 《手摸手教你学Spring Boot2.0》《Spring Security-JWT-OAuth2一本通》《实战前后端拆散RBAC权限管理系统》《实战SpringCloud微服务从青铜到王者》《VUE深入浅出系列》

August 3, 2020 · 1 min · jiezi

关于spring:精讲RestTemplate第2篇多种底层HTTP客户端类库的切换

本文是精讲RestTemplate第2篇,前篇的blog拜访地址如下: 精讲RestTemplate第1篇-在Spring或非Spring环境下如何应用RestTemplate只是对其余的HTTP客户端的封装,其自身并没有实现HTTP相干的根底性能。其底层实现是能够配置切换的,咱们本大节就带着大家来看一下RestTemplate底层实现,及如何实现底层根底HTTP库的切换。 一、源码剖析RestTemplate有一个十分重要的类叫做HttpAccessor,能够了解为用于HTTP接触拜访的根底类。下图为源码: 从源码中咱们能够剖析出以下几点信息 RestTemplate 反对至多三种HTTP客户端库。 SimpleClientHttpRequestFactory。对应的HTTP库是java JDK自带的HttpURLConnection。HttpComponentsAsyncClientHttpRequestFactory。对应的HTTP库是Apache HttpComponents。OkHttp3ClientHttpRequestFactory。对应的HTTP库是OkHttpjava JDK自带的HttpURLConnection是默认的底层HTTP实现客户端SimpleClientHttpRequestFactory,即java JDK自带的HttpURLConnection不反对HTTP协定的Patch办法,如果心愿应用Patch办法,须要将底层HTTP客户端实现切换为Apache HttpComponents 或 OkHttp能够通过设置setRequestFactory办法,来切换RestTemplate的底层HTTP客户端实现类库。二、底层实现切换办法从开发人员的反馈,和网上的各种HTTP客户端性能以及易用水平评测来看,OkHttp 优于 Apache HttpComponents、Apache HttpComponents优于HttpURLConnection。所以我集体更倡议大家将底层HTTP实现切换为okHTTP。 以下所讲的切换办法,基于第一篇内容: 精讲RestTemplate第1篇-在Spring或非Spring环境下如何应用2.1.切换为okHTTP首先通过maven坐标将okHTTP的包引入到我的项目中来 <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>4.7.2</version></dependency>如果是spring 环境下通过如下形式应用OkHttp3ClientHttpRequestFactory初始化RestTemplate bean对象。 @Configurationpublic class ContextConfig { @Bean("OKHttp3") public RestTemplate OKHttp3RestTemplate(){ RestTemplate restTemplate = new RestTemplate(new OkHttp3ClientHttpRequestFactory()); return restTemplate; }}如果是非Spring环境,间接new RestTemplate(new OkHttp3ClientHttpRequestFactory()之后应用就能够了。 2.2.切换为Apache HttpComponents与切换为okHTTP办法相似、不再赘述。 <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.12</version></dependency>应用HttpComponentsClientHttpRequestFactory初始化RestTemplate bean对象 @Bean("httpClient")public RestTemplate httpClientRestTemplate(){ RestTemplate restTemplate = new RestTemplate(new HttpComponentsClientHttpRequestFactory()); return restTemplate;}欢送关注我的博客,外面有很多精品合集本文转载注明出处(必须带连贯,不能只转文字):字母哥博客。感觉对您有帮忙的话,帮我点赞、分享!您的反对是我不竭的创作能源! 。另外,笔者最近一段时间输入了如下的精品内容,期待您的关注。 《手摸手教你学Spring Boot2.0》《Spring Security-JWT-OAuth2一本通》《实战前后端拆散RBAC权限管理系统》《实战SpringCloud微服务从青铜到王者》《VUE深入浅出系列》

August 3, 2020 · 1 min · jiezi

关于spring:项目部署点一下按钮就可以全流程自动化

咱们平时在开发一些小我的项目的时候,有疾速部署公布的这样的需要,我感觉最智能的形式可能是喊一声“公布”,应用程序就能主动打包公布到服务器上并运行起来。因为我的项目的规模比拟小,咱们可能不会利用到DevOps团队。咱们心愿有一个小工具,帮咱们实现应用程序的疾速上线。 Alibaba Cloud ToolKit就能够帮忙咱们就解决这个问题,然而咱们还是得打一点小小的折扣,咱们无奈实现“喊一声”,然而咱们能够实现“按一下”就公布应用程序。对于看文档感觉乏味的同学:点这里,这里有本文对应的操作《视频》。 第一步:装置IDEA插件Alibaba Cloud ToolKitIDEA File-> Settings-> Plugins->插件市场搜寻alibaba-> 装置install Alibaba Cloud ToolKit。 插件装置实现之后,重启IDEA编辑器。 第二步:增加服务器插件装置实现之后,在IDEA中找到“Alibaba Cloud View” 外面的Host的Tab框。 点击“Add Host”按钮之后弹出如下对话框,增加近程服务器主机IP及用户名明码。 增加实现之后多出一条Host记录 第三步:为服务器增加命令行将一些在该服务器上常常应用的命令行,固化为command配置 点击command,执行增加命令行操作 对于利用部署,须要应用到如下两个命令行 # 删除历史启动的 server-jwt过程ps -aux|grep -v grep |grep server-jwt| awk '{print $2}'|xargs kill -9;# 用java 形式启动server-jwt-1.0.jarnohup java -jar /root/server-jwt-1.0.jar &;将下面的命令行中的“server-jwt”替换为你本人的利用的jar名称或惟一关键字即可。如果对于这两个命令齐全无奈了解,须要去学习shell脚本、nohup、awk脚本和java -jar启动形式等基础知识。 第四步:利用部署配置须要部署的我的项目右键->Alibaba Cloud -> Deploy To Host,弹出如下对话框: 上图对话框红色区域中,从上到下、从左到右顺次是: 本次部署配置的名称:Name,配置固化下来之后能够复用在我的项目上传到服务器之前maven打包:Maven Build。也能够抉择应用Gradle打包:Gradle Build或者手动打包之后上传文件:Upload File。抉择近程部署的服务器的Ip,本文中第二步的配置后果Target Directory:maven打包之后的文件上传目录(即利用部署目录):依据本人的主机门路布局填写。After Deploy:当文件上传主机之后执行的shell脚本或命令行,咱们这里抉择执行nohup java -jar /root/server-jwt-1.0.jar &;启动利用。Run Maven Goal :maven 的打包指标,先对父我的项目打包,再对子模块打包。如果不存在,就点击“+”新建,打包命令是“clean install” ...

August 2, 2020 · 1 min · jiezi

关于spring:项目部署点一下按钮就可以全流程自动化

咱们平时在开发一些小我的项目的时候,有疾速部署公布的这样的需要,我感觉最智能的形式可能是喊一声“公布”,应用程序就能主动打包公布到服务器上并运行起来。因为我的项目的规模比拟小,咱们可能不会利用到DevOps团队。咱们心愿有一个小工具,帮咱们实现应用程序的疾速上线。 Alibaba Cloud ToolKit就能够帮忙咱们就解决这个问题,然而咱们还是得打一点小小的折扣,咱们无奈实现“喊一声”,然而咱们能够实现“按一下”就公布应用程序。对于看文档感觉乏味的同学:点这里,这里有本文对应的操作《视频》。 第一步:装置IDEA插件Alibaba Cloud ToolKitIDEA File-> Settings-> Plugins->插件市场搜寻alibaba-> 装置install Alibaba Cloud ToolKit。 插件装置实现之后,重启IDEA编辑器。 第二步:增加服务器插件装置实现之后,在IDEA中找到“Alibaba Cloud View” 外面的Host的Tab框。 点击“Add Host”按钮之后弹出如下对话框,增加近程服务器主机IP及用户名明码。 增加实现之后多出一条Host记录 第三步:为服务器增加命令行将一些在该服务器上常常应用的命令行,固化为command配置 点击command,执行增加命令行操作 对于利用部署,须要应用到如下两个命令行 # 删除历史启动的 server-jwt过程ps -aux|grep -v grep |grep server-jwt| awk '{print $2}'|xargs kill -9;# 用java 形式启动server-jwt-1.0.jarnohup java -jar /root/server-jwt-1.0.jar &;将下面的命令行中的“server-jwt”替换为你本人的利用的jar名称或惟一关键字即可。如果对于这两个命令齐全无奈了解,须要去学习shell脚本、nohup、awk脚本和java -jar启动形式等基础知识。 第四步:利用部署配置须要部署的我的项目右键->Alibaba Cloud -> Deploy To Host,弹出如下对话框: 上图对话框红色区域中,从上到下、从左到右顺次是: 本次部署配置的名称:Name,配置固化下来之后能够复用在我的项目上传到服务器之前maven打包:Maven Build。也能够抉择应用Gradle打包:Gradle Build或者手动打包之后上传文件:Upload File。抉择近程部署的服务器的Ip,本文中第二步的配置后果Target Directory:maven打包之后的文件上传目录(即利用部署目录):依据本人的主机门路布局填写。After Deploy:当文件上传主机之后执行的shell脚本或命令行,咱们这里抉择执行nohup java -jar /root/server-jwt-1.0.jar &;启动利用。Run Maven Goal :maven 的打包指标,先对父我的项目打包,再对子模块打包。如果不存在,就点击“+”新建,打包命令是“clean install” ...

August 2, 2020 · 1 min · jiezi

关于spring:细说selenium的等待条件

selenium的显示期待在进行UI自动化测试的时候,咱们为了放弃用例的稳定性,往往要设置显示期待,显示期待就是说明确的要等到某个元素的呈现或者元素的某些条件呈现,比方可点击、可见等条件,如果在规定的工夫之内都没有找到,那么就会抛出Exception. 下面是我用selenium写的一个测试用例,展现了selenium中显示期待的应用形式,其中会应用到expected_conditions模块和WebDriverWait类,留神这里expected_conditions是一个py文件的文件名,也就是一个模块名,这个模块上面有很多的条件类,而咱们用例中应用的title_is就是一个条件类。 WebDriverWait是一个类,这个类的作用就是依据肯定的条件,一直的查看这个条件是否被满足了。WebDriverWait类只有两个办法,一个是until直到满足某个条件,另一个是until_not直到不满足某个条件。 class WebDriverWait(object): def __init__(self, driver, timeout, poll_frequency=POLL_FREQUENCY, ignored_exceptions=None):WebDriverWait有四个参数别离是, driver驱动, timeout超时工夫, poll_frequency=POLL_FREQUENCY轮训工夫,也就是去判断条件是否满足的工夫距离,默认是0.5秒, ignored_exceptions=None在期待的过程中须要疏忽的异样,是一个可迭代的异样类汇合,比方咱们能够设置一个list,外面是[NoSuchElementException,NoSuchAttributeException,InvalidElementStateException....],默认状况下,是一个元组,只蕴含一个NoSuchElementException,因为只有元素呈现,能力去判断条件是否满足,在一直轮训的过程中,必定会产生NoSuchElementException,这个时候必须疏忽掉这个异样,不然程序就会中断。 其中driver和timeout是毕传的地位参数,另外两个是抉择传递的关键字参数,如果不传都有指定的默认值。 上面就进入咱们明天的主题,selenium中的期待条件的探讨 期待条件条件类的实现原理在selenium.webdriver.support.expected_conditions这个模块里,寄存着所有的期待条件,每个条件类的构造都是一样的一个__init__构造方法和一个__call__办法。 在python中,如果想把类型的对象当做函数来应用,那么就能够给这个类实现__call__办法,如下: class TestCase: def __init__(self): self.driver = webdriver.Chrome(executable_path="./driver/chromedriver") self.driver.get('http://www.baidu.com') # sleep(2) def __call__(self): print(self.driver.title)if __name__ == '__main__': case = TestCase() case() case()对象的调用,就会执行__call__办法外面的逻辑打印以后页面的题目,咱们取一个selenium的实现类: class presence_of_element_located(object): def __init__(self, locator): self.locator = locator def __call__(self, driver): return _find_element(driver, self.locator)这个条件类的意思是判断一个元素是否曾经渲染到页面当中,在应用这个条件的时候须要先实例化,传入元素的定位,而后要进行判断的时候须要对实例对象进行调用并传入driver,对实例对象进行调用的时候就会执行__call__办法里的条件判断逻辑。 WebDriverWait是如何进行条件判断的再回到文章结尾看一下咱们应用显示期待的代码: wait = WebDriverWait(self.driver, 2)wait.until(EC.title_is('百度一下,你就晓得'))先是实例化一个WebDriverWait对象,而后再调用until办法并且传递一个条件的实例对象,until办法里就会一直的去轮训条件是否满足。 def until(self, method, message=''): screen = None stacktrace = None end_time = time.time() + self._timeout while True: try: value = method(self._driver) if value: return value except self._ignored_exceptions as exc: screen = getattr(exc, 'screen', None) stacktrace = getattr(exc, 'stacktrace', None) time.sleep(self._poll) if time.time() > end_time: break raise TimeoutException(message, screen, stacktrace)method这个参数就是咱们传递进来的条件的实例对象,value = method(self._driver)这里就是进行对象的调用,也就是执行了__call__办法里的逻辑。 ...

August 1, 2020 · 1 min · jiezi

关于spring:细说selenium的等待条件

selenium的显示期待在进行UI自动化测试的时候,咱们为了放弃用例的稳定性,往往要设置显示期待,显示期待就是说明确的要等到某个元素的呈现或者元素的某些条件呈现,比方可点击、可见等条件,如果在规定的工夫之内都没有找到,那么就会抛出Exception. 下面是我用selenium写的一个测试用例,展现了selenium中显示期待的应用形式,其中会应用到expected_conditions模块和WebDriverWait类,留神这里expected_conditions是一个py文件的文件名,也就是一个模块名,这个模块上面有很多的条件类,而咱们用例中应用的title_is就是一个条件类。 WebDriverWait是一个类,这个类的作用就是依据肯定的条件,一直的查看这个条件是否被满足了。WebDriverWait类只有两个办法,一个是until直到满足某个条件,另一个是until_not直到不满足某个条件。 class WebDriverWait(object): def __init__(self, driver, timeout, poll_frequency=POLL_FREQUENCY, ignored_exceptions=None):WebDriverWait有四个参数别离是, driver驱动, timeout超时工夫, poll_frequency=POLL_FREQUENCY轮训工夫,也就是去判断条件是否满足的工夫距离,默认是0.5秒, ignored_exceptions=None在期待的过程中须要疏忽的异样,是一个可迭代的异样类汇合,比方咱们能够设置一个list,外面是[NoSuchElementException,NoSuchAttributeException,InvalidElementStateException....],默认状况下,是一个元组,只蕴含一个NoSuchElementException,因为只有元素呈现,能力去判断条件是否满足,在一直轮训的过程中,必定会产生NoSuchElementException,这个时候必须疏忽掉这个异样,不然程序就会中断。 其中driver和timeout是毕传的地位参数,另外两个是抉择传递的关键字参数,如果不传都有指定的默认值。 上面就进入咱们明天的主题,selenium中的期待条件的探讨 期待条件条件类的实现原理在selenium.webdriver.support.expected_conditions这个模块里,寄存着所有的期待条件,每个条件类的构造都是一样的一个__init__构造方法和一个__call__办法。 在python中,如果想把类型的对象当做函数来应用,那么就能够给这个类实现__call__办法,如下: class TestCase: def __init__(self): self.driver = webdriver.Chrome(executable_path="./driver/chromedriver") self.driver.get('http://www.baidu.com') # sleep(2) def __call__(self): print(self.driver.title)if __name__ == '__main__': case = TestCase() case() case()对象的调用,就会执行__call__办法外面的逻辑打印以后页面的题目,咱们取一个selenium的实现类: class presence_of_element_located(object): def __init__(self, locator): self.locator = locator def __call__(self, driver): return _find_element(driver, self.locator)这个条件类的意思是判断一个元素是否曾经渲染到页面当中,在应用这个条件的时候须要先实例化,传入元素的定位,而后要进行判断的时候须要对实例对象进行调用并传入driver,对实例对象进行调用的时候就会执行__call__办法里的条件判断逻辑。 WebDriverWait是如何进行条件判断的再回到文章结尾看一下咱们应用显示期待的代码: wait = WebDriverWait(self.driver, 2)wait.until(EC.title_is('百度一下,你就晓得'))先是实例化一个WebDriverWait对象,而后再调用until办法并且传递一个条件的实例对象,until办法里就会一直的去轮训条件是否满足。 def until(self, method, message=''): screen = None stacktrace = None end_time = time.time() + self._timeout while True: try: value = method(self._driver) if value: return value except self._ignored_exceptions as exc: screen = getattr(exc, 'screen', None) stacktrace = getattr(exc, 'stacktrace', None) time.sleep(self._poll) if time.time() > end_time: break raise TimeoutException(message, screen, stacktrace)method这个参数就是咱们传递进来的条件的实例对象,value = method(self._driver)这里就是进行对象的调用,也就是执行了__call__办法里的逻辑。 ...

August 1, 2020 · 1 min · jiezi

关于spring:细说selenium的等待条件

selenium的显示期待在进行UI自动化测试的时候,咱们为了放弃用例的稳定性,往往要设置显示期待,显示期待就是说明确的要等到某个元素的呈现或者元素的某些条件呈现,比方可点击、可见等条件,如果在规定的工夫之内都没有找到,那么就会抛出Exception. 下面是我用selenium写的一个测试用例,展现了selenium中显示期待的应用形式,其中会应用到expected_conditions模块和WebDriverWait类,留神这里expected_conditions是一个py文件的文件名,也就是一个模块名,这个模块上面有很多的条件类,而咱们用例中应用的title_is就是一个条件类。 WebDriverWait是一个类,这个类的作用就是依据肯定的条件,一直的查看这个条件是否被满足了。WebDriverWait类只有两个办法,一个是until直到满足某个条件,另一个是until_not直到不满足某个条件。 class WebDriverWait(object): def __init__(self, driver, timeout, poll_frequency=POLL_FREQUENCY, ignored_exceptions=None):WebDriverWait有四个参数别离是, driver驱动, timeout超时工夫, poll_frequency=POLL_FREQUENCY轮训工夫,也就是去判断条件是否满足的工夫距离,默认是0.5秒, ignored_exceptions=None在期待的过程中须要疏忽的异样,是一个可迭代的异样类汇合,比方咱们能够设置一个list,外面是[NoSuchElementException,NoSuchAttributeException,InvalidElementStateException....],默认状况下,是一个元组,只蕴含一个NoSuchElementException,因为只有元素呈现,能力去判断条件是否满足,在一直轮训的过程中,必定会产生NoSuchElementException,这个时候必须疏忽掉这个异样,不然程序就会中断。 其中driver和timeout是毕传的地位参数,另外两个是抉择传递的关键字参数,如果不传都有指定的默认值。 上面就进入咱们明天的主题,selenium中的期待条件的探讨 期待条件条件类的实现原理在selenium.webdriver.support.expected_conditions这个模块里,寄存着所有的期待条件,每个条件类的构造都是一样的一个__init__构造方法和一个__call__办法。 在python中,如果想把类型的对象当做函数来应用,那么就能够给这个类实现__call__办法,如下: class TestCase: def __init__(self): self.driver = webdriver.Chrome(executable_path="./driver/chromedriver") self.driver.get('http://www.baidu.com') # sleep(2) def __call__(self): print(self.driver.title)if __name__ == '__main__': case = TestCase() case() case()对象的调用,就会执行__call__办法外面的逻辑打印以后页面的题目,咱们取一个selenium的实现类: class presence_of_element_located(object): def __init__(self, locator): self.locator = locator def __call__(self, driver): return _find_element(driver, self.locator)这个条件类的意思是判断一个元素是否曾经渲染到页面当中,在应用这个条件的时候须要先实例化,传入元素的定位,而后要进行判断的时候须要对实例对象进行调用并传入driver,对实例对象进行调用的时候就会执行__call__办法里的条件判断逻辑。 WebDriverWait是如何进行条件判断的再回到文章结尾看一下咱们应用显示期待的代码: wait = WebDriverWait(self.driver, 2)wait.until(EC.title_is('百度一下,你就晓得'))先是实例化一个WebDriverWait对象,而后再调用until办法并且传递一个条件的实例对象,until办法里就会一直的去轮训条件是否满足。 def until(self, method, message=''): screen = None stacktrace = None end_time = time.time() + self._timeout while True: try: value = method(self._driver) if value: return value except self._ignored_exceptions as exc: screen = getattr(exc, 'screen', None) stacktrace = getattr(exc, 'stacktrace', None) time.sleep(self._poll) if time.time() > end_time: break raise TimeoutException(message, screen, stacktrace)method这个参数就是咱们传递进来的条件的实例对象,value = method(self._driver)这里就是进行对象的调用,也就是执行了__call__办法里的逻辑。 ...

August 1, 2020 · 1 min · jiezi

关于spring:angular的input输入搜索防抖避免keyup造成请求过于频繁以及如何封装成input组件的指令

一、常见的搜寻性能<input nz-input [(ngModel)]="paramsChannelVo.name" (keyup)="getData(paramsChannelVo.name)" placeholder="零碎名称" />input的keyup事件把每次按键弹起都发送给了 getData() 办法。 这样一个绑定就造成了,每输出一个字符就会进行一次搜寻,如果应用中文输入法,最初回车写入中文时,又有可能造成不会进行搜寻 所以最好是能等到用户进行输出时才发送申请。此时就能够用到申请防抖(应用 RxJS 的操作符实现)。 二、如何应用防抖性能1、component.js中引入rxjs/Subjectimport {Subject} from 'rxjs/Subject';import {debounceTime, distinctUntilChanged} from 'rxjs/operators';2、申明变量private getDataTerms = new Subject<string>();这个string通常是[(ngModel)]绑定的值的类型 3、keyup绑定的getData办法getData(value: string) { this.getDataTerms.next(value);}4、申请防抖ngOnInit(): void { this.getDataTerms .pipe( // 申请防抖 300毫秒 debounceTime(300), distinctUntilChanged()) .subscribe(term => { // 此处进行httpClient的申请 // term是用户输出的值 this.getDataList(); }); } getDataList(){ // 此处进行httpClient的申请 } 5、阐明ngOnInit() 中的代码还通过下列两个操作符对这些搜寻值进行管道解决: debounceTime(300) - 期待,直到用户进行输出(这个例子中是进行 300ms)。distinctUntilChanged() - 期待,直到搜寻内容产生了变动。getDataTerms 是一个序列,蕴含用户输出到搜寻框中的所有值。 它定义成了 RxJS 的 Subject 对象,这示意它是一个多播 Observable,同时还能够自行调用 next(value) 来产生值 ...

August 1, 2020 · 1 min · jiezi

关于spring:angular的input输入搜索防抖避免keyup造成请求过于频繁以及如何封装成input组件的指令

一、常见的搜寻性能<input nz-input [(ngModel)]="paramsChannelVo.name" (keyup)="getData(paramsChannelVo.name)" placeholder="零碎名称" />input的keyup事件把每次按键弹起都发送给了 getData() 办法。 这样一个绑定就造成了,每输出一个字符就会进行一次搜寻,如果应用中文输入法,最初回车写入中文时,又有可能造成不会进行搜寻 所以最好是能等到用户进行输出时才发送申请。此时就能够用到申请防抖(应用 RxJS 的操作符实现)。 二、如何应用防抖性能1、component.js中引入rxjs/Subjectimport {Subject} from 'rxjs/Subject';import {debounceTime, distinctUntilChanged} from 'rxjs/operators';2、申明变量private getDataTerms = new Subject<string>();这个string通常是[(ngModel)]绑定的值的类型 3、keyup绑定的getData办法getData(value: string) { this.getDataTerms.next(value);}4、申请防抖ngOnInit(): void { this.getDataTerms .pipe( // 申请防抖 300毫秒 debounceTime(300), distinctUntilChanged()) .subscribe(term => { // 此处进行httpClient的申请 // term是用户输出的值 this.getDataList(); }); } getDataList(){ // 此处进行httpClient的申请 } 5、阐明ngOnInit() 中的代码还通过下列两个操作符对这些搜寻值进行管道解决: debounceTime(300) - 期待,直到用户进行输出(这个例子中是进行 300ms)。distinctUntilChanged() - 期待,直到搜寻内容产生了变动。getDataTerms 是一个序列,蕴含用户输出到搜寻框中的所有值。 它定义成了 RxJS 的 Subject 对象,这示意它是一个多播 Observable,同时还能够自行调用 next(value) 来产生值 ...

August 1, 2020 · 1 min · jiezi

关于spring:项目相关汇总

1.Redis分布式锁存在的问题,如何优化

July 31, 2020 · 1 min · jiezi

关于spring:精讲RestTemplate第1篇在Spring或非Spring环境下如何使用

一、什么是 RestTemplate?RestTemplate是执行HTTP申请的同步阻塞式的客户端,它在HTTP客户端库(例如JDK HttpURLConnection,Apache HttpComponents,okHttp等)根底封装了更加简略易用的模板办法API。也就是说RestTemplate是一个封装,底层的实现还是java利用开发中罕用的一些HTTP客户端。然而绝对于间接应用底层的HTTP客户端库,它的操作更加不便、快捷,能很大水平上晋升咱们的开发效率。 RestTemplate作为spring-web我的项目的一部分,在Spring 3.0版本开始被引入。RestTemplate类通过为HTTP办法(例如GET,POST,PUT,DELETE等)提供重载的办法,提供了一种十分不便的办法拜访基于HTTP的Web服务。如果你的Web服务API基于规范的RESTful格调设计,应用成果将更加的完满。 依据Spring官网文档及源码中的介绍,RestTemplate在未来的版本中它可能会被弃用,因为他们已在Spring 5中引入了WebClient作为非阻塞式Reactive HTTP客户端。然而RestTemplate目前在Spring 社区内还是很多我的项目的“重度依赖”,比如说Spring Cloud。另外,RestTemplate说白了是一个客户端API封装,和服务端相比,非阻塞Reactive 编程的需要并没有那么高。二、非Spring环境下应用RestTemplate为了不便后续开发测试,首先介绍一个网站给大家。JSONPlaceholder是一个提供收费的在线REST API的网站,咱们在开发时能够应用它提供的url地址测试下网络申请以及申请参数。或者当咱们程序须要获取一些模仿数据、模仿图片时也能够应用它。RestTemplate是spring的一个rest客户端,在spring-web这个包下。这个包尽管叫做spring-web,然而它的RestTemplate能够脱离Spring 环境应用。 <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>5.2.6.RELEASE</version></dependency>测试一下Hello world,应用RestTemplate发送一个GET申请,并把申请失去的JSON数据后果打印进去。 @Testpublic void simpleTest(){ RestTemplate restTemplate = new RestTemplate(); String url = "http://jsonplaceholder.typicode.com/posts/1"; String str = restTemplate.getForObject(url, String.class); System.out.println(str);}服务端是JSONPlaceholder网站,帮咱们提供的服务端API。须要留神的是:"http://jsonplaceholder.typicode.com/posts/1"服务URL,尽管URL外面有posts这个单词,然而它的英文含意是:帖子或者布告,而不是咱们的HTTP Post协定。所以说"http://jsonplaceholder.typicode.com/posts/1",申请的数据是:id为1的Post布告资源。打印后果如下: 这里咱们只是演示了RestTemplate 最根底的用法,RestTemplate 会写成一个系列的文章,请大家关注。 三、Spring环境下应用RestTemplate将maven坐标从spring-web换成spring-boot-starter-web <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId></dependency>将RestTemplate配置初始化为一个Bean。这种初始化办法,是应用了JDK 自带的HttpURLConnection作为底层HTTP客户端实现。咱们还能够把底层实现切换为Apache HttpComponents,okHttp等,咱们后续章节会为大家介绍。 @Configurationpublic class ContextConfig { //默认应用JDK 自带的HttpURLConnection作为底层实现 @Bean public RestTemplate restTemplate(){ RestTemplate restTemplate = new RestTemplate(); return restTemplate; }}在须要应用RestTemplate 的地位,注入并应用即可。 ...

July 31, 2020 · 1 min · jiezi

关于spring:Spring事务传播行为

本文出处Spring 事务流传行为转载请阐明出处在Spring @Transactional 申明式事务有一个项属性propagation事务流传行为,是一个Propagation 枚举类,有7种类型,对应不同应用场景。上面说下这些枚举代码含意,在联合代码加深了解,坚固学习。 Spring 属性阐明REQUIRED反对以后事务,如果不存在事务则创立一个新事务。这个propagation默认属性SUPPORTS反对以后事务,如果不存在事务则依照无事务执行MANDATORY反对以后事务,如果不存事务在则抛出异样REQUIRES_NEW创立一个新的事务,如果存在以后事务,则将它挂起NOT_SUPPORTED无事务执行,如果存在事务将它挂起NEVER无事务执行,如果存在以后事务则抛出异样NESTED如果以后事务存在,则在嵌套事务中执行,如果不存在事务就像REQUIRED成果事务流传级别生效先做一个小试验,写一个长久化的save办法,设置成禁用事务,用事务办法去调用它,看会产生什么成果。 @Transactional(propagation = Propagation.NEVER) public void save(Users users){ usersRepository.save(users); } @Transactional public void multSave(){ Users users = getUsers(); save(users); }依照下面字段含意解析,save办法不反对事务,在以后事务运行会抛出异样。可是执行后果不是意料那样,没有抛出异样,数据写入到数据库了。并且咱们能够在改一次save办法,间接抛出一个RuntimeTime异样,你会发现后果更加显著。 @Transactional(propagation = Propagation.NEVER) public void save(Users users){ usersRepository.save(users); throw new RuntimeException("4322"); } @Transactional public void multSave(){ Users users = getUsers(); save(users); }你会发现save 办法 数据回滚了。在做多几次这种试验你就会发现,在同一个类中,最外层事务注解属性会笼罩办法内所有事务注解,比方你的外层设置默认事务流传行为,无论调用那种行为都会依照默认属性,外层没有设置事务,调用办法有事务也不会失效的。这个不难理解,实现Spring 事务一个基于AOP的代理类,它依据指标办法注解来加强办法,这个是运行时动静执行的,办法内其余办法没有代理类的性能加强,就相当于一般办法成果了。千万不要在同一个类外面测试事务流传行为,否则你永远都都得不到论断的。 进入办法验证默认事务 @Transactional public void save(){ Employee employee = new Employee(); employee.setDepartmentId(2); employee.setName("Jorry"); employee.setSalary(60000); repository.save(employee); throw new RuntimeException("33333"); } @Transactional public void multSave(){ Users users = getUsers(); save(users); employeeService.save(); }执行后果: users、employee写入失败,employee的办法抛出异样触发回滚,也会导致外层办法回滚。在同一个事务中,只有触发回滚,事务内所有数据操作都会回滚的。 ...

July 30, 2020 · 2 min · jiezi

关于spring:Spring事务传播行为

本文出处Spring 事务流传行为转载请阐明出处在Spring @Transactional 申明式事务有一个项属性propagation事务流传行为,是一个Propagation 枚举类,有7种类型,对应不同应用场景。上面说下这些枚举代码含意,在联合代码加深了解,坚固学习。 Spring 属性阐明REQUIRED反对以后事务,如果不存在事务则创立一个新事务。这个propagation默认属性SUPPORTS反对以后事务,如果不存在事务则依照无事务执行MANDATORY反对以后事务,如果不存事务在则抛出异样REQUIRES_NEW创立一个新的事务,如果存在以后事务,则将它挂起NOT_SUPPORTED无事务执行,如果存在事务将它挂起NEVER无事务执行,如果存在以后事务则抛出异样NESTED如果以后事务存在,则在嵌套事务中执行,如果不存在事务就像REQUIRED成果事务流传级别生效先做一个小试验,写一个长久化的save办法,设置成禁用事务,用事务办法去调用它,看会产生什么成果。 @Transactional(propagation = Propagation.NEVER) public void save(Users users){ usersRepository.save(users); } @Transactional public void multSave(){ Users users = getUsers(); save(users); }依照下面字段含意解析,save办法不反对事务,在以后事务运行会抛出异样。可是执行后果不是意料那样,没有抛出异样,数据写入到数据库了。并且咱们能够在改一次save办法,间接抛出一个RuntimeTime异样,你会发现后果更加显著。 @Transactional(propagation = Propagation.NEVER) public void save(Users users){ usersRepository.save(users); throw new RuntimeException("4322"); } @Transactional public void multSave(){ Users users = getUsers(); save(users); }你会发现save 办法 数据回滚了。在做多几次这种试验你就会发现,在同一个类中,最外层事务注解属性会笼罩办法内所有事务注解,比方你的外层设置默认事务流传行为,无论调用那种行为都会依照默认属性,外层没有设置事务,调用办法有事务也不会失效的。这个不难理解,实现Spring 事务一个基于AOP的代理类,它依据指标办法注解来加强办法,这个是运行时动静执行的,办法内其余办法没有代理类的性能加强,就相当于一般办法成果了。千万不要在同一个类外面测试事务流传行为,否则你永远都都得不到论断的。 进入办法验证默认事务 @Transactional public void save(){ Employee employee = new Employee(); employee.setDepartmentId(2); employee.setName("Jorry"); employee.setSalary(60000); repository.save(employee); throw new RuntimeException("33333"); } @Transactional public void multSave(){ Users users = getUsers(); save(users); employeeService.save(); }执行后果: users、employee写入失败,employee的办法抛出异样触发回滚,也会导致外层办法回滚。在同一个事务中,只有触发回滚,事务内所有数据操作都会回滚的。 ...

July 30, 2020 · 2 min · jiezi

关于spring:不想得手指关节炎帮你提炼IDEA常用代码补全操作

一、罕用的代码补全操作1、.for和.fori(for 循环遍历)输出args.for回车(args是一个数组或汇合类),则会生成for循环遍历: 输出args.fori回车,则会生成带有索引的for循环遍历语句: 2、sout(控制台输入语句)代码中输出sout回车,会主动生成System.out.println()这个控制台输入打印语句: 3、psvm在代码中输出psvm之后回车 会主动生成main函数,psvm是public static void main的首字母: 4、.var(为对象生成申明局部代码)输出“xxx”.var回车,则会生成如下代码: 输出123.var回车,则会生成如下代码: 输出new ArrayList().var回车,则会生成如下代码: 5、.if(生成 if 语句)写好一个判断条件之后加上.if,回车: 生成如下的if语句: 6、.null 与 .nn(空、非空判断)输出args.null回车,则会生成如下代码,判断是否为null: 输出args.nn回车,则会生成如下代码,判断是否不为null: 二、罕用快捷键Ctrl + O查看咱们继承的类或者接口中的办法,以及咱们要实现的办法 Ctrl+Alt+T将代码包在一个块中,例如try/catch  ;synchronized等 作用windows 快捷键Alt + Enter比拟全能的一个快捷键,import 类以及报错下一步可选操作提醒,IDEA报错了不晓得怎么做,能够尝试它全局搜寻double shift代码格式化ctrl+ alt + L去掉无用的包的援用ctrl + alt + O正文(勾销正文)ctrl + /多行正文 (勾销多行正文)ctrl + shift + /Ctrl+D复制光标所在行的内容,插入光标地位上面Ctrl+Y删除光标所在行Ctrl+X剪切光标所在行Ctrl+Z复原到上一步操作的历史代码Alt+Shift+高低箭头向上或向下挪动以后代码行Alt + Insertset/get; 构造方法;  toString; 等重写办法欢送关注我的博客,外面有很多精品合集本文转载注明出处(必须带连贯,不能只转文字):字母哥博客。感觉对您有帮忙的话,帮我点赞、分享!您的反对是我不竭的创作能源! 。另外,笔者最近一段时间输入了如下的精品内容,期待您的关注。 ...

July 30, 2020 · 1 min · jiezi

关于spring:吃透了这一套2020阿里美团字节跳动Java-面试真题你离-BAT还远吗

前言最近,金九银十在即,很多人都在筹备面试,特地给大家总结了 Java 程序员面试必备题,这份面试清单是我从 去年开始收集的,一方面是给公司招聘用,另一方面是想用它来开掘我在 Java 技术栈中的技术盲点,而后修复和欠缺它,以此来进步本人的技术水平。下文次要是我集体的总结办法教训(面试学习和刷题笔记),都整顿有PDF完整版,有须要的能够看文末有支付形式 面试题模块介绍说了这么多,直奔主题,咱们这份面试题,总内容蕴含了十九个模块:Java 根底、容器、多线程、反射、对象拷贝、Java Web 模块、异样、网络、设计模式、Spring/Spring MVC、Spring Boot/Spring Cloud、Hibernate、Mybatis、RabbitMQ、Kafka、Zookeeper、MySql、Redis、JVM 。如下图所示: 可能对于初学者不须要看前面的框架和 JVM 模块的常识,读者敌人们可依据本人的状况,抉择对应的模块进行浏览。 合适浏览人群 须要面试的初/中/高级 Java 程序员想要查漏补缺的人想要不断完善和裁减本人 Java 技术栈的人Java 面试官Java 根底JDK 和 JRE 有什么区别?== 和 equals 的区别是什么?两个对象的 hashCode()雷同,则 equals()也肯定为 true,对吗?final 在 java 中有什么作用?java 中的 Math.round(-1.5) 等于多少?String 属于根底的数据类型吗?java 中操作字符串都有哪些类?它们之间有什么区别?String str="i"与 String str=new String(“i”)一样吗?如何将字符串反转?String 类的罕用办法都有那些?抽象类必须要有形象办法吗?一般类和抽象类有哪些区别?抽象类能应用 final 润饰吗?接口和抽象类有什么区别?java 中 IO 流分为几种?BIO、NIO、AIO 有什么区别?Files的罕用办法都有哪些?留神:下文次要是我集体的总结办法教训(面试学习和刷题笔记),都整顿有PDF完整版,有须要的能够关注我的公众号前程有光自取 多线程并行和并发有什么区别?线程和过程的区别?守护线程是什么?创立线程有哪几种形式?说一下 runnable 和 callable 有什么区别?线程有哪些状态?sleep() 和 wait() 有什么区别?notify()和 notifyAll()有什么区别?线程的 run()和 start()有什么区别?创立线程池有哪几种形式?线程池都有哪些状态?线程池中 submit()和 execute()办法有什么区别?在 java 程序中怎么保障多线程的运行平安?多线程锁的降级原理是什么?什么是死锁?怎么避免死锁?ThreadLocal 是什么?有哪些应用场景?说一下 synchronized 底层实现原理?synchronized 和 volatile 的区别是什么?synchronized 和 Lock 有什么区别?synchronized 和 ReentrantLock 区别是什么?说一下 atomic 的原理? ...

July 28, 2020 · 2 min · jiezi

关于spring:Spring-Security-OAuth2之resourceid配置与验证

一、resource_id的作用 Spring Security OAuth2 架构上分为Authorization Server认证服务器和Resource Server资源服务器。咱们能够为每一个Resource Server(一个微服务实例)设置一个resourceid。Authorization Server给client第三方客户端受权的时候,能够设置这个client能够拜访哪一些Resource Server资源服务,如果没设置,就是对所有的Resource Server都有拜访权限。 二、ResourceServer如何设置ResourceID在每个ResourceServer实例上设置resourceId,该resourceId作为该服务资源的惟一标识。(如果同一个微服务资源部署多份,resourceId雷同) @Configuration@EnableResourceServerpublic class OAuth2ResourceServer extends ResourceServerConfigurerAdapter { private static final String DEMO_RESOURCE_ID = "test-resource"; @Override public void configure(ResourceServerSecurityConfigurer resources) { resources.resourceId(DEMO_RESOURCE_ID) //...... 还能够有有其余的配置 } }三、AuthorizationServer如何设置ResourceIDs在AuthorizationServer为客户端client配置ResourceID的目标是:限度某个client能够拜访的资源服务。 @Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception { //配置客户端存储到db 代替原来得内存模式 JdbcClientDetailsService clientDetailsService = new JdbcClientDetailsService(dataSource); clientDetailsService.setPasswordEncoder(passwordEncoder); clients.withClientDetails(clientDetailsService);}这里须要应用JdbcClientDetailsService类和数据库表oauth_client_details进行配置的长久化存储,以及动静配置。 三、ResourceID在哪验证ResourceID当然是在Resource Server资源服务器进行验证(你能不能拜访我的资源,当然由我本人来验证)。当资源申请发送到Resource Server的时候会携带access_token,Resource Server会依据access_token找到client_id,进而找到该client能够拜访的resource_ids。如果resource_ids蕴含ResourceServer本人设置ResourceID,这关就过来了,就能够持续进行其余的权限验证。 @EnableResourceServer会给Spring Security的FilterChan增加一个OAuth2AuthenticationProcessingFilter过滤器,过滤所有的资源申请。OAuth2AuthenticationProcessingFilter会应用OAuth2AuthenticationManager来验证token。验证Token的时候会去oauth_client_details表加载client配置信息。如果AuthorizationServer认证client1能够拜访test-resource,但client1去拜访了oauth-rs,会响应如下信息: {"error":"access_denied","error_description":"Invalid token does not contain resource id (oauth-rs)"}具体实现resource_id验证的源码:OAuth2AuthenticationManager#authenticate(Authentication authentication) ...

July 28, 2020 · 2 min · jiezi

关于spring:一年六个月十八天从外包到字节跳动客户端提前批没想到我也能够逆袭

前言话不多说,但先介绍一下本人还是要的,末流985大学本科,自动化方面业余,自学Java和后端。听敌人说字节往年后端投递的人十分多,竞争比拟大,我本科不是CS,也只是做翻新创业项目的时候接触过Java后端,起初看到有说客户端0教训的,就让他人帮忙内推了一下,没想到四面过了!!!哈哈哈 分享一下我的面试流程:一面(45min左右):自我介绍。(我就说了下本人的经验和我的项目)问了一下平时怎么学Java的,做的我的项目有没有和Java无关的。过程和线程的区别。http申请三次握手,四次挥手。为什么是四次挥手。https的工作原理和流程。罕用的网络状态码有哪些,50x是什么类型的谬误。Java ThreadLocal的源码,举个理论的利用场景。java内存透露的问题,非动态外部类为什么能够拜访到外部类的成员。算法题:青蛙跳台阶,有多少种跳法。(起初问了一下我怎么去思考这个算法的,边界条件怎么设计的等等) 留神:这次面试过程比拟长,内容繁多,在文章中我基本上简述了,文章里的面试题完整版和我集体的总结办法教训(面试学习和刷题笔记),都整顿有PDF完整版,有须要的能够关注我的公众号前程有光收费分享给你。二面(60min):自我介绍(为什么又让我介绍???可能是不同的面试官吧)数据结构和操作系统方面平时有没有学习,感觉本人学的如何。(说是自学的,上了学校的一些课程)HashMap的实现原理,Java 1.8前后的次要区别是什么。hashCode()和equles()办法有什么关系,为什么重写了前者必须要重写后者。不重写会有什么问题。Java内存模型,内存共享等系列问题。(我认为是问办法区、堆、栈等这种内存划分,后果是指的内存共享方面的问题,面试官等我答完了才跟我说答错了,领导我答复正确的答案)线程锁的问题,synchronized关键字,造成死锁的条件是什么。算法题1:让我写几种生产消费者模型。(我写了三种实现)算法题2: 版本号的比照,比方:1.7.93和1.8.1这种。感觉二面官非常重视Java根底,而且问的问题也是由浅入深的,依据你的答复状况来抉择下一个问题。三面(60min):Java类加载的流程,双亲委派机制是什么,它是为了解决什么问题。Java GC回收的原理,新生代老年代划分机制。Java设计模式学的怎么样,动态代理和动静代理的区别,各有什么劣势。手撕三种Java 单例的写法。最优的写法是什么,为什么?(这道题答得不是很好)给定一个长度为n的钢条,以及一个价格表p,p中列出了每英寸钢条的价格,将长度为n的钢条切割为若干短钢条发售,求一个钢条的切割计划,使得收益最大,切割工序没有老本。(《算法导论》上规范的动静布局例题。)算是运气比拟好吧,面试官也没有在算法上特意刁难,问了一道典型的动静布局问题。感觉三面官是所有面试官里最庄重的,问的问题也更重视根底,思考的更深刻。四面(HR):HR面大略就是问了一下本人的职业倒退方向啊,将来有什么打算啊 面试经验总结置信大家都很好奇,我是非科班出世,又是前面自学的java后端,是怎么一步步从外包走到字节跳动的呢? 留神:下文次要是我集体的总结办法教训(面试学习和刷题笔记),都整顿有PDF完整版,有须要的能够关注我的公众号前程有光收费分享给你。1.本人布局好路线图,学会查漏补缺把本人的知识点梳理好,根本问题不大 并发编程:多线程,高并发,CAS,锁,容器,线程池底层性能调优:Mysql,IO及网络调优,算法调优,JVMSpring全家桶:Spring,SpringMVC,MyBatis,IOC,AOP缓存数据库:Redis,mongoDB,MySQL分布式&微服务:SpringBoot,SpringCloud,docker,maven2.依据本人布局的路线图,找出本身有余JMM内存模型古代计算机模型基础理论常识什么是线程 深刻了解Java线程JMM Volatile 缓存一致性协定指令重排、可见性、原子性、程序一致性、happens-beofre详解 as-if-serial Mysql性能调优Mysql索引数据结构深度解说B+树Hash红黑树Mysql 执行打算与索引解说explain工具深度应用索引优化最佳实际 ZookeeperZookeeper疾速入门Zookeeper多节点集群部署实战Zookeeper典型利用场景实战服务注册与订阅分布式配置核心分布式锁Zookeeper中znode、watcher、ACL、客户端API详解Zookeeper客户端服务端源码分析Zookeeper迁徙、扩容、监控详解 DubboDubbo企业级利用实际Dubbo 调用模块详解Dubbo容错机制与高扩展性剖析Dubbo RPC协定底层原理与实现Dubbo设计原理剖析与源码详解Dubbo负载平衡策略剖析Dubbo管控后盾治理与部署详解 RedisRedis外围数据结构分析Redis在微博,微信及电商场景典型利用实际Redis长久化机制与平安机制详解Redis主从及哨兵架构详解Redis Cluster集群架构实战及原理分析集群数据分片算法及动静程度扩容详解Jedis、Redisson客户端源码分析Redis高并发分布式锁实战Redis缓存穿透,缓存生效,缓存雪崩实战解析Redis布隆过滤器实现Redis缓存设计与性能优化 这份面试文档当然不止这些内容,实际上像Spring Cloud、设计模式、Netty、分布式、数据结构等其余局部的面试内容均有波及,因为文章篇幅,就不全副在这里论述了,须要的能够关注我的公众号前程有光收费下载完整版。写在最初的话对于大厂面试,我最初想要强调的一点就是心态真的很重要,是决定你在面试过程中施展的要害,若不能失常施展,很可能就因为一个小失误与offer失之交臂,所以肯定要器重起来。另外揭示一点,充沛温习,是打消你缓和的心理状态的要害,但你温习充沛了,天然面试过程中就要有底气得多。再揭示一下,如果你想要学习,却无奈于没有干货学习材料,以上所有的材料内容都能够收费分享给你,关注我的公众号前程有光以上所有材料一次性打包带走!

July 27, 2020 · 1 min · jiezi

关于spring:一年六个月十八天从外包到字节跳动客户端提前批没想到我也能够逆袭

前言话不多说,但先介绍一下本人还是要的,末流985大学本科,自动化方面业余,自学Java和后端。听敌人说字节往年后端投递的人十分多,竞争比拟大,我本科不是CS,也只是做翻新创业项目的时候接触过Java后端,起初看到有说客户端0教训的,就让他人帮忙内推了一下,没想到四面过了!!!哈哈哈 分享一下我的面试流程:一面(45min左右):自我介绍。(我就说了下本人的经验和我的项目)问了一下平时怎么学Java的,做的我的项目有没有和Java无关的。过程和线程的区别。http申请三次握手,四次挥手。为什么是四次挥手。https的工作原理和流程。罕用的网络状态码有哪些,50x是什么类型的谬误。Java ThreadLocal的源码,举个理论的利用场景。java内存透露的问题,非动态外部类为什么能够拜访到外部类的成员。算法题:青蛙跳台阶,有多少种跳法。(起初问了一下我怎么去思考这个算法的,边界条件怎么设计的等等) 留神:这次面试过程比拟长,内容繁多,在文章中我基本上简述了,文章里的面试题完整版和我集体的总结办法教训(面试学习和刷题笔记),都整顿有PDF完整版,有须要的能够关注我的公众号前程有光收费分享给你。二面(60min):自我介绍(为什么又让我介绍???可能是不同的面试官吧)数据结构和操作系统方面平时有没有学习,感觉本人学的如何。(说是自学的,上了学校的一些课程)HashMap的实现原理,Java 1.8前后的次要区别是什么。hashCode()和equles()办法有什么关系,为什么重写了前者必须要重写后者。不重写会有什么问题。Java内存模型,内存共享等系列问题。(我认为是问办法区、堆、栈等这种内存划分,后果是指的内存共享方面的问题,面试官等我答完了才跟我说答错了,领导我答复正确的答案)线程锁的问题,synchronized关键字,造成死锁的条件是什么。算法题1:让我写几种生产消费者模型。(我写了三种实现)算法题2: 版本号的比照,比方:1.7.93和1.8.1这种。感觉二面官非常重视Java根底,而且问的问题也是由浅入深的,依据你的答复状况来抉择下一个问题。三面(60min):Java类加载的流程,双亲委派机制是什么,它是为了解决什么问题。Java GC回收的原理,新生代老年代划分机制。Java设计模式学的怎么样,动态代理和动静代理的区别,各有什么劣势。手撕三种Java 单例的写法。最优的写法是什么,为什么?(这道题答得不是很好)给定一个长度为n的钢条,以及一个价格表p,p中列出了每英寸钢条的价格,将长度为n的钢条切割为若干短钢条发售,求一个钢条的切割计划,使得收益最大,切割工序没有老本。(《算法导论》上规范的动静布局例题。)算是运气比拟好吧,面试官也没有在算法上特意刁难,问了一道典型的动静布局问题。感觉三面官是所有面试官里最庄重的,问的问题也更重视根底,思考的更深刻。四面(HR):HR面大略就是问了一下本人的职业倒退方向啊,将来有什么打算啊 面试经验总结置信大家都很好奇,我是非科班出世,又是前面自学的java后端,是怎么一步步从外包走到字节跳动的呢? 留神:下文次要是我集体的总结办法教训(面试学习和刷题笔记),都整顿有PDF完整版,有须要的能够关注我的公众号前程有光收费分享给你。1.本人布局好路线图,学会查漏补缺把本人的知识点梳理好,根本问题不大 并发编程:多线程,高并发,CAS,锁,容器,线程池底层性能调优:Mysql,IO及网络调优,算法调优,JVMSpring全家桶:Spring,SpringMVC,MyBatis,IOC,AOP缓存数据库:Redis,mongoDB,MySQL分布式&微服务:SpringBoot,SpringCloud,docker,maven2.依据本人布局的路线图,找出本身有余JMM内存模型古代计算机模型基础理论常识什么是线程 深刻了解Java线程JMM Volatile 缓存一致性协定指令重排、可见性、原子性、程序一致性、happens-beofre详解 as-if-serial Mysql性能调优Mysql索引数据结构深度解说B+树Hash红黑树Mysql 执行打算与索引解说explain工具深度应用索引优化最佳实际 ZookeeperZookeeper疾速入门Zookeeper多节点集群部署实战Zookeeper典型利用场景实战服务注册与订阅分布式配置核心分布式锁Zookeeper中znode、watcher、ACL、客户端API详解Zookeeper客户端服务端源码分析Zookeeper迁徙、扩容、监控详解 DubboDubbo企业级利用实际Dubbo 调用模块详解Dubbo容错机制与高扩展性剖析Dubbo RPC协定底层原理与实现Dubbo设计原理剖析与源码详解Dubbo负载平衡策略剖析Dubbo管控后盾治理与部署详解 RedisRedis外围数据结构分析Redis在微博,微信及电商场景典型利用实际Redis长久化机制与平安机制详解Redis主从及哨兵架构详解Redis Cluster集群架构实战及原理分析集群数据分片算法及动静程度扩容详解Jedis、Redisson客户端源码分析Redis高并发分布式锁实战Redis缓存穿透,缓存生效,缓存雪崩实战解析Redis布隆过滤器实现Redis缓存设计与性能优化 这份面试文档当然不止这些内容,实际上像Spring Cloud、设计模式、Netty、分布式、数据结构等其余局部的面试内容均有波及,因为文章篇幅,就不全副在这里论述了,须要的能够关注我的公众号前程有光收费下载完整版。写在最初的话对于大厂面试,我最初想要强调的一点就是心态真的很重要,是决定你在面试过程中施展的要害,若不能失常施展,很可能就因为一个小失误与offer失之交臂,所以肯定要器重起来。另外揭示一点,充沛温习,是打消你缓和的心理状态的要害,但你温习充沛了,天然面试过程中就要有底气得多。再揭示一下,如果你想要学习,却无奈于没有干货学习材料,以上所有的材料内容都能够收费分享给你,关注我的公众号前程有光以上所有材料一次性打包带走!

July 27, 2020 · 1 min · jiezi

关于spring:掌门教育微服务体系-Solar-阿里巴巴-Nacos-企业级落地上篇

联席作者:吴毅挺 任浩军 张彬彬 廖梦鸽 张金星 胡振建郑重鸣谢:Nacos - 彦林,Spring Cloud Alibab - 小马哥、落夜,Nacos 社区 - 张龙(pader)、春少(chuntaojun) 前言在高速倒退的时候,公司规模越来越大,老师人数越来越多,这时候公司不能铺太多人去做经营与服务,必须进步每个人效,这就须要技术驱动。因而掌门教育转变成一家技术驱动型的公司,如果被迫成为一家靠资金驱动的公司就活不下去了。-- 张翼(掌门教育创始人兼 CEO)掌门教育自 2014 年正式转型在线教育以来,秉承“让教育共享智能,让学习高效高兴”的主旨和愿景,经验云计算、大数据、人工智能、 AR / VR / MR 以及现今最火的 5G ,始终保持用科技赋能教育。掌门教育的业务近几年失去了疾速倒退,特地是往年的疫情,使在线教育成为了新的风口,也给掌门教育新的时机。 随着业务规模进一步扩充,流量进一步暴增,微服务数目进一步增长,使老的微服务体系所采纳的注册核心 Eureka 不堪重负,同时 Spring Cloud 体系曾经演进到第二代,第一代的 Eureka 注册核心曾经不大适宜当初的业务逻辑和规模,同时它目前被 Spring Cloud 官网置于保护模式,将不再向前倒退。如何抉择一个更为优良和实用的注册核心,这个课题就摆在了掌门人的背后。通过对 Alibaba Nacos 、HashiCorp Consul 等开源注册核心做了深刻的调研和比拟,最终选定 Alibaba Nacos 做微服务体系 Solar 中的新注册核心。 背景故事1. 掌门教育微服务面临的挑战1)第一次生产事变2020 年疫情暴发后的几个月后,掌门教育的微服务实例数比去年猛增 40% ,基础架构部乐观的认为注册核心 Eureka 服务器能够抗住该数量级的实例数规模, Eureka 服务器在阿里云 PROD 环境上执行三台 8C16G 普通型机器三角结构型对等部署,运行了好几年都始终很稳固,但劫难还是在2020年3月某天早晨来临,当天早晨大略 9 点 30 分左右,其中两台 Eureka 服务器无征兆的 CPU 占用迅速回升到100%,同时大量业务服务掉线,告警零碎被触发,钉钉机器人告警和邮件告警铺天盖地而来。基础架构部和运维部紧急重启 Eureka 服务器,但没多久,CPU 仍旧没抗住,而且更加来势凶猛,关上的文件描述符数霎时达到 8000+ ,TCP 连贯达到 1 万+ ,业务服务和 Eureka 服务器的通信产生大面积的 TCP CLOSE_WAIT 事件,且伴有大量 Broken pipe 异样。 ...

July 27, 2020 · 4 min · jiezi

关于spring:小书MybatisPlus第9篇常用字段默认值自动填充

本文为Mybatis Plus系列文章的第9篇,前8篇拜访地址如下: 小书MybatisPlus第1篇-整合SpringBoot疾速开始增删改查小书MybatisPlus第2篇-条件结构器的利用及总结小书MybatisPlus第3篇-自定义SQL小书MybatisPlus第4篇-表格分页与下拉分页查问小书MybatisPlus第5篇-Active Record模式精讲小书MybatisPlus第6篇-主键生成策略精讲小书MybatisPlus第7篇-代码生成器的原理精讲及应用办法小书MybatisPlus第8篇-逻辑删除实现及API细节精讲一、填充字段解决需要案例:在插入数据的时候主动填充createTime和updateTime为以后插入数据的工夫,在数据更新的时候批改updateTime为批改数据的工夫。不须要人为的手动赋值。 在数据库表层面须要先增加2个日期类型的字段create_tme和update_time 应用@TableField注解标记实体类中的哪些字段须要填充:@Datapublic class User { private Long id; private String name; private Integer age; private String email; @TableField(fill = FieldFill.INSERT) private Date createTime; @TableField(fill = FieldFill.INSERT_UPDATE) private Date updateTime;}FieldFill是一个枚举,用于指定在何种状况下会主动填充,有如下几种可选值: DEFAULT:默认不解决INSERT:插入时主动填充字段UPDATE:更新时主动填充字段INSERT_UPDATE:插入和更新时主动填充字段二、自定义填充默认数值编写公共字段填充处理器类,该类继承了MetaObjectHandler类,重写 insertFill和updateFill办法,咱们在这两个办法中获取须要填充的字段以及默认填充的值。 填充处理器MyMetaObjectHandler在Spring Boot中须要申明@Component或@Bean注入strictInsertFill和strictUpdateFill办法第二个参数写的是实体类里的属性名,不是对应数据库字段名。@Componentpublic class MyMetaObjectHandler implements MetaObjectHandler { @Override public void insertFill(MetaObject metaObject) { this.strictInsertFill(metaObject, "createTime", Date.class, new Date()); this.strictInsertFill(metaObject, "updateTime", Date.class, new Date()); } @Override public void updateFill(MetaObject metaObject) { this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date()); }}如果是3.3.0前面的版本,比方3.3.1.8,也能够改用上面更简略的写法(3.3.0不要用该办法,有bug) ...

July 27, 2020 · 1 min · jiezi

关于spring:SpringBean的几个问题以及原理

一、几个问题Spring中的bean是如何生成?Spring提供了哪些扩大点能够整合第三方框架Spring如何整合Mybatis的二、什么是SpringSpring治理bean(Java中的对象),初始化的操作, 三、Spring IoC容器资源组件:Resource,对资源文件的形容,不同资源文件如xml、properties文件等,格局不同,最终都将被ResourceLoader加载取得相应的Resource对象;集体了解是。主配置文件.主配置作为所有配置的入口 资源加载组件:ResourceLoader:加载xml、properties等各类格式文件,解析文件,并生成Resource对象。加载哪些解析过的配置资源 Bean容器组件:BeanFactory体系:IoC容器的外围,其余组件都是为它工作的(但不是仅仅为其服务).外围 Bean注册组件:SingletonBeanRegister/AliasRegister:将BeanDefinition对象注册到BeanFactory(BeanDefinition Map)中去。注册对象所应用的容器 Bean形容组件:BeanDefinition体系,Spring外部对Bean形容的根本数据结构。负责形容BeanDefinition资源 将资源模式的bean转化为spring所冀望的格局构造 Bean结构组件:BeanDefinitionReader体系,读取Resource并将其数据转换成一个个BeanDefinition对象。负责将一个个的资源 解析转化为BeanDefinition 为之后形容bean做筹备 <img src="https://tva1.sinaimg.cn/large/007S8ZIlgy1gg9jtxriloj31330mi0w2.jpg" alt="image-20200205095809050" style="zoom:50%;float:left" /> 四、BeanFactory4.1 筹备bean-v1.xml配置bean的信息BeanDefinition用于寄存bean的定义BeanFactory获取bean的信息,实例化bean`BeanFactoryTest测试BeanFactory是否可用4.2 代码实现bean-v1.xml <?xml version="1.0" encoding="UTF-8"?><beans> <bean id="user" class="com.timwang.spring.small.User"/> <bean id="invalidBean" class="xxx.xxx"/></beans> BeanDefinition bean-v1.xml中定义了每个bean,但这些信息咱们该如何存储呢? spring是通过BeanDefinition接口来形容bean的定义 package com.timwang.spring.small;/** * @author wangjun*/public interface BeanDefinition { /** * 获取bean.xml中 bean的全名 如 "com.niocoder.service.v1.NioCoderService" * @return string */ String getBeanClassName();} `GenericBeanDefinition`实现了`BeanDefinition`接口package com.timwang.spring.small; /** * @author wangjun* @date 2020-06-29*/public class GenericBeanDefinition implements BeanDefinition { private String id; private String beanClassName; public GenericBeanDefinition(String id, String beanClassName) { this.id = id; this.beanClassName = beanClassName; } @Override public String getBeanClassName() { return this.beanClassName; } public String getId() { return id; }} ...

July 26, 2020 · 2 min · jiezi

关于spring:在java中进行日期时间比较的4种方法

1. Date.compareTo()java.util.Date提供了在Java中比拟两个日期的经典办法compareTo()。 如果两个日期相等,则返回值为0。如果Date在date参数之后,则返回值大于0。如果Date在date参数之前,则返回值小于0。@Testvoid testDateCompare() throws ParseException { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); Date date1 = sdf.parse("2009-12-31"); Date date2 = sdf.parse("2019-01-31"); System.out.println("date1 : " + sdf.format(date1)); System.out.println("date2 : " + sdf.format(date2)); if (date1.compareTo(date2) > 0) { System.out.println("Date1 工夫在 Date2 之后"); } else if (date1.compareTo(date2) < 0) { System.out.println("Date1 工夫在 Date2 之前"); } else if (date1.compareTo(date2) == 0) { System.out.println("Date1 工夫与 Date2 相等"); } else { System.out.println("程序怎么会运行到这里?失常应该不会"); }}输入后果: ...

July 26, 2020 · 2 min · jiezi

关于spring:spring源码解析springcore三

getBean这里便是bean初始化的外围逻辑。源码比较复杂,离开说。以getBean(String name)为例。AbstractBeanFactory.getBean:@Overridepublic Object getBean(String name) throws BeansException {return doGetBean(name, null, null, false); } 第二个参数示意bean的Class类型,第三个示意创立bean须要的参数,最初一个示意不须要进行类型查看。beanName转化final String beanName = transformedBeanName(name);这里是将FactoryBean的前缀去掉以及将别名转为实在的名字。手动注册bean检测后面注册环境一节说过,Spring其实手动注册了一些单例bean。这一步就是检测是不是这些bean。如果是,那么再检测是不是工厂bean,如果是返回其工厂办法返回的实例,如果不是返回bean自身。Object sharedInstance = getSingleton(beanName);if (sharedInstance != null && args == null) { bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } 查看父容器如果父容器存在并且存在此bean定义,那么交由其父容器初始化:BeanFactory parentBeanFactory = getParentBeanFactory();if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { // Not found -> check parent. //此办法其实是做了后面beanName转化的逆操作,因为父容器同样会进行转化操作 String nameToLookup = originalBeanName(name); if (args != null) { // Delegation to parent with explicit args. ...

July 25, 2020 · 5 min · jiezi

关于spring:spring源码解析springcore二

Bean解析 XmlBeanDefinitionReader.registerBeanDefinitions: public int registerBeanDefinitions(Document doc, Resource resource) {     BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();     int countBefore = getRegistry().getBeanDefinitionCount();     documentReader.registerBeanDefinitions(doc, createReaderContext(resource));     return getRegistry().getBeanDefinitionCount() - countBefore; } createBeanDefinitionDocumentReader: protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() { return BeanDefinitionDocumentReader.class.cast //反射 (BeanUtils.instantiateClass(this.documentReaderClass)); } documentReaderClass默认是DefaultBeanDefinitionDocumentReader,这其实也是策略模式,通过setter办法能够更换其实现。 留神cast办法,代替了强转。 createReaderContext: public XmlReaderContext createReaderContext(Resource resource) {     return new XmlReaderContext(resource, this.problemReporter, this.eventListener,     this.sourceExtractor, this, getNamespaceHandlerResolver()); } problemReporter是一个FailFastProblemReporter对象。 eventListener是EmptyReaderEventListener对象,此类里的办法都是空实现。 sourceExtractor是NullSourceExtractor对象,间接返回空,也是空实现。 getNamespaceHandlerResolver默认返回DefaultNamespaceHandlerResolver对象,用来获取xsd对应的处理器。 XmlReaderContext的作用感觉就是这一堆参数的容器,糅合到一起传给DocumentReader,并美其名为Context。能够看出,Spring中到处都是策略模式,大量操作被形象成接口。 DefaultBeanDefinitionDocumentReader.registerBeanDefinitions: @Overridepublic void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {     this.readerContext = readerContext;     Element root = doc.getDocumentElement();     doRegisterBeanDefinitions(root); } doRegisterBeanDefinitions: protected void doRegisterBeanDefinitions(Element root) { BeanDefinitionParserDelegate parent = this.delegate; this.delegate = createDelegate(getReaderContext(), root, parent); //默认的命名空间即 //http://www.springframework.org/schema/beans if (this.delegate.isDefaultNamespace(root)) { //查看profile属性 String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE); if (StringUtils.hasText(profileSpec)) { //profile属性能够以,宰割 String[] specifiedProfiles = StringUtils.tokenizeToStringArray( profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS); if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) { return; } } } preProcessXml(root); parseBeanDefinitions(root, this.delegate); postProcessXml(root); ...

July 25, 2020 · 6 min · jiezi

关于spring:spring源码解析springcore二

Bean解析 XmlBeanDefinitionReader.registerBeanDefinitions: public int registerBeanDefinitions(Document doc, Resource resource) {     BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();     int countBefore = getRegistry().getBeanDefinitionCount();     documentReader.registerBeanDefinitions(doc, createReaderContext(resource));     return getRegistry().getBeanDefinitionCount() - countBefore; } createBeanDefinitionDocumentReader: protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() { return BeanDefinitionDocumentReader.class.cast //反射 (BeanUtils.instantiateClass(this.documentReaderClass)); } documentReaderClass默认是DefaultBeanDefinitionDocumentReader,这其实也是策略模式,通过setter办法能够更换其实现。 留神cast办法,代替了强转。 createReaderContext: public XmlReaderContext createReaderContext(Resource resource) {     return new XmlReaderContext(resource, this.problemReporter, this.eventListener,     this.sourceExtractor, this, getNamespaceHandlerResolver()); } problemReporter是一个FailFastProblemReporter对象。 eventListener是EmptyReaderEventListener对象,此类里的办法都是空实现。 sourceExtractor是NullSourceExtractor对象,间接返回空,也是空实现。 getNamespaceHandlerResolver默认返回DefaultNamespaceHandlerResolver对象,用来获取xsd对应的处理器。 XmlReaderContext的作用感觉就是这一堆参数的容器,糅合到一起传给DocumentReader,并美其名为Context。能够看出,Spring中到处都是策略模式,大量操作被形象成接口。 DefaultBeanDefinitionDocumentReader.registerBeanDefinitions: @Overridepublic void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {     this.readerContext = readerContext;     Element root = doc.getDocumentElement();     doRegisterBeanDefinitions(root); } doRegisterBeanDefinitions: protected void doRegisterBeanDefinitions(Element root) { BeanDefinitionParserDelegate parent = this.delegate; this.delegate = createDelegate(getReaderContext(), root, parent); //默认的命名空间即 //http://www.springframework.org/schema/beans if (this.delegate.isDefaultNamespace(root)) { //查看profile属性 String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE); if (StringUtils.hasText(profileSpec)) { //profile属性能够以,宰割 String[] specifiedProfiles = StringUtils.tokenizeToStringArray( profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS); if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) { return; } } } preProcessXml(root); parseBeanDefinitions(root, this.delegate); postProcessXml(root); ...

July 25, 2020 · 6 min · jiezi

关于spring:spring源码解析二spring结构组成容器基础XmlBeanFactory

本文来源于:宋文超super,专属平台有csdn、思否(SegmentFault)、 简书、 开源中国(oschina),转载请注明出处。

July 25, 2020 · 1 min · jiezi

关于spring:小书MybatisPlus第8篇逻辑删除实现及API细节精讲

本文为Mybatis Plus系列文章的第8篇,前7篇拜访地址如下: 小书MybatisPlus第1篇-整合SpringBoot疾速开始增删改查小书MybatisPlus第2篇-条件结构器的利用及总结小书MybatisPlus第3篇-自定义SQL小书MybatisPlus第4篇-表格分页与下拉分页查问小书MybatisPlus第5篇-Active Record模式精讲小书MybatisPlus第6篇-主键生成策略精讲小书MybatisPlus第7篇-代码生成器的原理精讲及应用办法一、物理删除与逻辑删除物理删除:指文件存储所用到的磁存储区域被真正的擦除或清零,这样删除的文件是不能够复原的,物理删除是计算机解决数据时的一个概念。如果在数据库中间接应用delete、drop删除了表数据,如果没有备份的话,数据就很难复原了。逻辑删除(软删除):逻辑删除就是对要被删除的数据打上一个删除标记,通常应用一个deleted字段标示行记录是不是被删除,比方该数据有一个字段deleted,当其值为0示意未删除,值为1示意删除。那么逻辑删除就是将0变成1。在逻辑上是数据是被删除的,但数据自身是仍然存在的。两者的优劣: 物理删除肯定水平上删除了“无用”的数据,升高了表的数据量,对性能必定是有益处的;然而如果没有备份的话,数据很难复原。也无奈对历史数据进行数据分析。逻辑删除复原的话只有批改ideleted等相似的状态标示字段就能够了,然而表的数据量必定会比物理删除减少了,并且查问时常常要思考到deleted字段,对索引都会有影响。所以一张表的数据是否采纳逻辑删除,还要依据数据的重要性、数据量、查问性能以及业务需要等因素综合判断。 二、逻辑删除实现首先为须要逻辑删除的表减少一个deleted字段作为逻辑删除字段,并且设置其默认值为0,如下:CREATE TABLE `user` ( `id` BIGINT(20) NOT NULL COMMENT '主键ID', `name` VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名', `age` INT(11) NULL DEFAULT NULL COMMENT '年龄', `email` VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱', `deleted` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '逻辑删除标记', PRIMARY KEY (`id`));给数据库表对应的实体类字段上加上@TableLogic注解: 三、API应用办法3.1.插入一条数据插入数据的时候,不须要为deleted字段赋值 @Testpublic void testInsert() { User user = new User(); user.setName("字母哥"); user.setAge(18); int row = userMapper.insert(user);}deleted采纳默认值0(未删除),新插入的数据都是未删除的数据 3.2.删除一条记录:执行如下Mybatis Plus API删除操作 ...

July 25, 2020 · 1 min · jiezi

关于spring:小书MybatisPlus第8篇逻辑删除实现及API细节精讲

本文为Mybatis Plus系列文章的第8篇,前7篇拜访地址如下: 小书MybatisPlus第1篇-整合SpringBoot疾速开始增删改查小书MybatisPlus第2篇-条件结构器的利用及总结小书MybatisPlus第3篇-自定义SQL小书MybatisPlus第4篇-表格分页与下拉分页查问小书MybatisPlus第5篇-Active Record模式精讲小书MybatisPlus第6篇-主键生成策略精讲小书MybatisPlus第7篇-代码生成器的原理精讲及应用办法一、物理删除与逻辑删除物理删除:指文件存储所用到的磁存储区域被真正的擦除或清零,这样删除的文件是不能够复原的,物理删除是计算机解决数据时的一个概念。如果在数据库中间接应用delete、drop删除了表数据,如果没有备份的话,数据就很难复原了。逻辑删除(软删除):逻辑删除就是对要被删除的数据打上一个删除标记,通常应用一个deleted字段标示行记录是不是被删除,比方该数据有一个字段deleted,当其值为0示意未删除,值为1示意删除。那么逻辑删除就是将0变成1。在逻辑上是数据是被删除的,但数据自身是仍然存在的。两者的优劣: 物理删除肯定水平上删除了“无用”的数据,升高了表的数据量,对性能必定是有益处的;然而如果没有备份的话,数据很难复原。也无奈对历史数据进行数据分析。逻辑删除复原的话只有批改ideleted等相似的状态标示字段就能够了,然而表的数据量必定会比物理删除减少了,并且查问时常常要思考到deleted字段,对索引都会有影响。所以一张表的数据是否采纳逻辑删除,还要依据数据的重要性、数据量、查问性能以及业务需要等因素综合判断。 二、逻辑删除实现首先为须要逻辑删除的表减少一个deleted字段作为逻辑删除字段,并且设置其默认值为0,如下:CREATE TABLE `user` ( `id` BIGINT(20) NOT NULL COMMENT '主键ID', `name` VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名', `age` INT(11) NULL DEFAULT NULL COMMENT '年龄', `email` VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱', `deleted` TINYINT(4) NOT NULL DEFAULT '0' COMMENT '逻辑删除标记', PRIMARY KEY (`id`));给数据库表对应的实体类字段上加上@TableLogic注解: 三、API应用办法3.1.插入一条数据插入数据的时候,不须要为deleted字段赋值 @Testpublic void testInsert() { User user = new User(); user.setName("字母哥"); user.setAge(18); int row = userMapper.insert(user);}deleted采纳默认值0(未删除),新插入的数据都是未删除的数据 3.2.删除一条记录:执行如下Mybatis Plus API删除操作 ...

July 25, 2020 · 1 min · jiezi

关于spring:Spring依赖处理过程源码分析

AbstractAutowireCapableBeanFactory#doCreateBean创立BeanAbstractAutowireCapableBeanFactory#populateBean属性的外围注入办法InstantiationAwareBeanPostProcessor#postProcessProperties用于给bean解决值注入,@Autowire就在这个过程解决注入InjectionMetadata#inject-->AutowiredMethodElement#injectresolveDependencydoResolveDependencyAbstractAutowireCapableBeanFactory#doCreateBean创立Beanprotected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { // 1. 实例化Bean,结构器注入或工厂办法注入 BeanWrapper instanceWrapper = createBeanInstance(beanName, mbd, args); // 2. 后置处理器批改Bean的定义BeanDefinition:bdp#postProcessMergedBeanDefinition applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); // 3. 提前将Bean裸露到IoC容器中,用于解决循环依赖 boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } // 4. populateBean属性注入的外围办法,initializeBean则执行bean初始化办法 Object exposedObject = bean; populateBean(beanName, mbd, instanceWrapper); exposedObject = initializeBean(beanName, exposedObject, mbd); // 5. 注册bean的依赖关系,用于bean销毁用 registerDisposableBeanIfNecessary(beanName, bean, mbd); return exposedObject;}AbstractAutowireCapableBeanFactory#populateBean属性的外围注入办法protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { // 1. 判断是否须要进行属性注入:ibp#postProcessAfterInstantiation if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { return; } } } } PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); // 2. 主动注入:包含名称注入和类型注入 int resolvedAutowireMode = mbd.getResolvedAutowireMode(); if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // 2.1 主动依据名称注入 if (resolvedAutowireMode == AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // 2.2 主动依据类型注入 if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE); // 3. 注解注入:后置处理器ibp#postProcessProperties,赫赫有名的@Autowired就是在这解决的。 PropertyDescriptor[] filteredPds = null; if (hasInstAwareBpps) { if (pvs == null) { pvs = mbd.getPropertyValues(); } for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { return; } } pvs = pvsToUse; } } } // 4. 依赖查看,循环依赖... if (needsDepCheck) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } checkDependencies(beanName, mbd, filteredPds, pvs); } // 5. 手动依赖注入 if (pvs != null) { applyPropertyValues(beanName, mbd, bw, pvs); }}InstantiationAwareBeanPostProcessor#postProcessProperties用于给bean解决值注入,@Autowire就在这个过程解决注入@Override public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) { // 这里获取指标bean每个须要注入的依赖,metadata会蕴含一组元素,每个元素对应一个指标bean : // 1. @Autowired/@Value 注解的属性 或者 // 2. @Autowired/@Value 注解的办法参数 InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs); try { // 执行依赖注入 metadata.inject(bean, beanName, pvs); } catch (BeanCreationException ex) { throw ex; } catch (Throwable ex) { throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex); } return pvs; }InjectionMetadata#inject-->AutowiredMethodElement#injectpublic void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { Collection<InjectedElement> checkedElements = this.checkedElements; Collection<InjectedElement> elementsToIterate = (checkedElements != null ? checkedElements : this.injectedElements); if (!elementsToIterate.isEmpty()) { // 遍历指标bean每个须要注入的成员属性依赖或者成员办法参数依赖,执行相应的依赖注入 for (InjectedElement element : elementsToIterate) { if (logger.isTraceEnabled()) { logger.trace("Processing injected element of bean '" + beanName + "': " + element); } element.inject(target, beanName, pvs); } } }@Override protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { Field field = (Field) this.member; Object value; if (this.cached) { value = resolvedCachedArgument(beanName, this.cachedFieldValue); } else { DependencyDescriptor desc = new DependencyDescriptor(field, this.required); desc.setContainingClass(bean.getClass()); Set<String> autowiredBeanNames = new LinkedHashSet<>(1); Assert.state(beanFactory != null, "No BeanFactory available"); TypeConverter typeConverter = beanFactory.getTypeConverter(); try { // 依赖解析应用 beanFactory#resolveDependency value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter); } catch (BeansException ex) { throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex); } synchronized (this) { if (!this.cached) { if (value != null || this.required) { this.cachedFieldValue = desc; registerDependentBeans(beanName, autowiredBeanNames); if (autowiredBeanNames.size() == 1) { String autowiredBeanName = autowiredBeanNames.iterator().next(); if (beanFactory.containsBean(autowiredBeanName) && beanFactory.isTypeMatch(autowiredBeanName, field.getType())) { this.cachedFieldValue = new ShortcutDependencyDescriptor( desc, autowiredBeanName, field.getType()); } } } else { this.cachedFieldValue = null; } this.cached = true; } } } if (value != null) { ReflectionUtils.makeAccessible(field); field.set(bean, value); } }Spring中依赖解决从DefaultListableBeanFactory的resolveDependency办法开始解决形容注入信息的类DependencyDescriptorpublic class DependencyDescriptor extends InjectionPoint implements Serializable { //被注入的申明类 private final Class<?> declaringClass; //办法注入的办法名 @Nullable private String methodName; //对应的参数 @Nullable private Class<?>[] parameterTypes; //参数索引 private int parameterIndex; //如果所包装的是成员属性,则这里记录该成员属性的名称 @Nullable private String fieldName; //是否必要依赖 private final boolean required; //是否是懒加载 private final boolean eager; //嵌套级别 private int nestingLevel = 1; //通常和declaringClass一样 @Nullable private Class<?> containingClass; //泛型解决 @Nullable private transient volatile ResolvableType resolvableType; //依赖 TypeDescriptor 的缓存 @Nullable private transient volatile TypeDescriptor typeDescriptor;} ...

July 25, 2020 · 5 min · jiezi

关于spring:Spring依赖处理过程源码分析

AbstractAutowireCapableBeanFactory#doCreateBean创立BeanAbstractAutowireCapableBeanFactory#populateBean属性的外围注入办法InstantiationAwareBeanPostProcessor#postProcessProperties用于给bean解决值注入,@Autowire就在这个过程解决注入InjectionMetadata#inject-->AutowiredMethodElement#injectresolveDependencydoResolveDependencyAbstractAutowireCapableBeanFactory#doCreateBean创立Beanprotected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { // 1. 实例化Bean,结构器注入或工厂办法注入 BeanWrapper instanceWrapper = createBeanInstance(beanName, mbd, args); // 2. 后置处理器批改Bean的定义BeanDefinition:bdp#postProcessMergedBeanDefinition applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); // 3. 提前将Bean裸露到IoC容器中,用于解决循环依赖 boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } // 4. populateBean属性注入的外围办法,initializeBean则执行bean初始化办法 Object exposedObject = bean; populateBean(beanName, mbd, instanceWrapper); exposedObject = initializeBean(beanName, exposedObject, mbd); // 5. 注册bean的依赖关系,用于bean销毁用 registerDisposableBeanIfNecessary(beanName, bean, mbd); return exposedObject;}AbstractAutowireCapableBeanFactory#populateBean属性的外围注入办法protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { // 1. 判断是否须要进行属性注入:ibp#postProcessAfterInstantiation if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { return; } } } } PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); // 2. 主动注入:包含名称注入和类型注入 int resolvedAutowireMode = mbd.getResolvedAutowireMode(); if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // 2.1 主动依据名称注入 if (resolvedAutowireMode == AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // 2.2 主动依据类型注入 if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE); // 3. 注解注入:后置处理器ibp#postProcessProperties,赫赫有名的@Autowired就是在这解决的。 PropertyDescriptor[] filteredPds = null; if (hasInstAwareBpps) { if (pvs == null) { pvs = mbd.getPropertyValues(); } for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { return; } } pvs = pvsToUse; } } } // 4. 依赖查看,循环依赖... if (needsDepCheck) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } checkDependencies(beanName, mbd, filteredPds, pvs); } // 5. 手动依赖注入 if (pvs != null) { applyPropertyValues(beanName, mbd, bw, pvs); }}InstantiationAwareBeanPostProcessor#postProcessProperties用于给bean解决值注入,@Autowire就在这个过程解决注入@Override public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) { // 这里获取指标bean每个须要注入的依赖,metadata会蕴含一组元素,每个元素对应一个指标bean : // 1. @Autowired/@Value 注解的属性 或者 // 2. @Autowired/@Value 注解的办法参数 InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs); try { // 执行依赖注入 metadata.inject(bean, beanName, pvs); } catch (BeanCreationException ex) { throw ex; } catch (Throwable ex) { throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex); } return pvs; }InjectionMetadata#inject-->AutowiredMethodElement#injectpublic void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { Collection<InjectedElement> checkedElements = this.checkedElements; Collection<InjectedElement> elementsToIterate = (checkedElements != null ? checkedElements : this.injectedElements); if (!elementsToIterate.isEmpty()) { // 遍历指标bean每个须要注入的成员属性依赖或者成员办法参数依赖,执行相应的依赖注入 for (InjectedElement element : elementsToIterate) { if (logger.isTraceEnabled()) { logger.trace("Processing injected element of bean '" + beanName + "': " + element); } element.inject(target, beanName, pvs); } } }@Override protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { Field field = (Field) this.member; Object value; if (this.cached) { value = resolvedCachedArgument(beanName, this.cachedFieldValue); } else { DependencyDescriptor desc = new DependencyDescriptor(field, this.required); desc.setContainingClass(bean.getClass()); Set<String> autowiredBeanNames = new LinkedHashSet<>(1); Assert.state(beanFactory != null, "No BeanFactory available"); TypeConverter typeConverter = beanFactory.getTypeConverter(); try { // 依赖解析应用 beanFactory#resolveDependency value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter); } catch (BeansException ex) { throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex); } synchronized (this) { if (!this.cached) { if (value != null || this.required) { this.cachedFieldValue = desc; registerDependentBeans(beanName, autowiredBeanNames); if (autowiredBeanNames.size() == 1) { String autowiredBeanName = autowiredBeanNames.iterator().next(); if (beanFactory.containsBean(autowiredBeanName) && beanFactory.isTypeMatch(autowiredBeanName, field.getType())) { this.cachedFieldValue = new ShortcutDependencyDescriptor( desc, autowiredBeanName, field.getType()); } } } else { this.cachedFieldValue = null; } this.cached = true; } } } if (value != null) { ReflectionUtils.makeAccessible(field); field.set(bean, value); } }Spring中依赖解决从DefaultListableBeanFactory的resolveDependency办法开始解决形容注入信息的类DependencyDescriptorpublic class DependencyDescriptor extends InjectionPoint implements Serializable { //被注入的申明类 private final Class<?> declaringClass; //办法注入的办法名 @Nullable private String methodName; //对应的参数 @Nullable private Class<?>[] parameterTypes; //参数索引 private int parameterIndex; //如果所包装的是成员属性,则这里记录该成员属性的名称 @Nullable private String fieldName; //是否必要依赖 private final boolean required; //是否是懒加载 private final boolean eager; //嵌套级别 private int nestingLevel = 1; //通常和declaringClass一样 @Nullable private Class<?> containingClass; //泛型解决 @Nullable private transient volatile ResolvableType resolvableType; //依赖 TypeDescriptor 的缓存 @Nullable private transient volatile TypeDescriptor typeDescriptor;} ...

July 25, 2020 · 5 min · jiezi

关于spring:Spring-Bean循环引用的处理

循环依赖解决的思维如上图所示,ABean援用了BBean,同时BBean也援用了ABeanSpring在初始化时,会依照beanDefinitionNames的程序(就是Bean的注册程序)顺次初始化所有Bean(对所有的Bean调用一次getBean),而后由BeanFactory进行初始化初始化Bean有两个要害的流程: instantiateBean - 创立Bean对象populateBean - 填充Bean,将Bean中的援用Bean填充至以后Bean那么问题来了,如果在ABean populateBean 的过程中发现了另一个BBean的援用,此时须要对另一个BBean提前进行初始化操作(getBean),可是BBean初始化的时候也发现了ABean的援用,又会返回对ABean进行初始化,此时就会陷入死循环 抛开Spring的实现细节,这个问题也不难解决,当发现循环援用的时候,只须要提早populateBean的机会就行: 比方发现BBean的援用时,调用getBean(BBean)操作,这个时候B不必实现全副初始化操作,只须要实现第一步instantiateBean 而后就返回BBean的实例 当按beanDefinitionNames的程序初始化到BBean的时候,在对BBean进行populateBean 就能够防止死循环的问题 对于下面的问题解决,关键点是要解决这个未齐全初始化然而有相互援用的对象。最容易想到的就是保护一个中间状态“半初始化”,代表只instantiate并没有进行populate的Bean,这样就能够将实例化和注入“离开”进行,注入时只须要获取已对象的实例即可,对象是否populate实现并不关怀这个半初始化状态实现也很简略,只须要保护两组对象列表,一个汇合负责存储已instantiate但并没有实现populate半初始化的bean - InCreation,另一个汇合保护加载实现的bean - registered回到下面那个流程,当ABean执行完instantial后增加到下面的InCreation汇合中,此时populate会调用BBean的初始化,这时Bbean会发现对ABean的援用,先从加载实现的InCreation汇合中获取,如果没有再从InCreation汇合中获取,此时会发现ABean的实例,而后将ABean实例 populate到BBean的实例中,BBean加载实现,增加到registered汇合中;回到ABean的populate过程,此时曾经获取到BBean的返回,间接populate到ABean实例中,ABean加载实现,功败垂成当然,上述解决方案只是针对属性模式的注入,如果是构造函数的注入就没法解决了,因为连构造方法都没法执行,不能正确的实例化Spring中的解决思维也是大同小异,此处就不贴代码了,具体能够参考org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean留神:尽管spring对循环援用做了解决,但这种援用关系在程序设计中是不太正当的,应该尽量避免

July 24, 2020 · 1 min · jiezi

关于spring:小书MybatisPlus第7篇代码生成器的原理精讲及使用方法

本文是本系列文章的第七篇,前6篇拜访地址如下: 小书MybatisPlus第1篇-整合SpringBoot疾速开始增删改查小书MybatisPlus第2篇-条件结构器的利用及总结小书MybatisPlus第3篇-自定义SQL小书MybatisPlus第4篇-表格分页与下拉分页查问小书MybatisPlus第5篇-Active Record模式精讲小书MybatisPlus第6篇-主键生成策略精讲一、代码生成器的根底实现原理置信大部分的开发者都应用过或者据说过“模板引擎”,它能够帮咱们实现视图与数据的拆散,疾速开发视图页面,并将模板整合后果用于在浏览器显示。其外围实现原理就是:HTML模板页面 + 页面数据 = 输入后果。页面视图输入的过程就是通过模板引擎实现的。 代码生成器的实现原理与模板引擎实现页面渲染的逻辑简直是统一的,除了上面的几个区别: 所谓模板:就是某语言的代码 + 模板引擎语法的占位符,该占位符用来数据天换。所以代码生成器的模板文件不再专指HTML页面模板文件,能够是任何类型的代码文件。模板引擎的输入后果在我的项目中是输入给浏览器进行页面渲染的,然而对于代码生成器而言,模板引擎的输入后果是保留到磁盘文件。 二、如何编写模板文件要编写模板文件,首先咱们要晓得失常的代码待如何书写。比方上面的POJO代码: 下面的POJO代码写成Freemarker模板文件,就是上面的样子: package ${package.Entity};<#list table.importPackages as pkg>import ${pkg};</#list><#if entityLombokModel>import lombok.Data;import lombok.EqualsAndHashCode;</#if>/** * <p> * ${table.comment!} * </p> * * @author ${author} * @since ${date} */<#if entityLombokModel>@Data <#if superEntityClass??>@EqualsAndHashCode(callSuper = true) <#else>@EqualsAndHashCode(callSuper = false) </#if></#if>public class ${entity} extends Model<${entity}> {<#list table.fields as field> private ${field.propertyType} ${field.propertyName};</#list>Mybatis Plus 代码生成的模板文件:https://gitee.com/baomidou/mybatis-plus/tree/3.0/mybatis-plus-generator/src/main/resources/templates 三、数据从哪里来?有了模板文件,咱们想通过模板引擎生成代码,上面的一个问题就是数据从哪里来?有了数据咱们能力生成代码 从配置中来,比方:package门路等一些动态化不常常变动的信息,一个我的项目生成的代码寄存的包门路通常不会常常变动。从数据库中来,比方:实体类名称、实体类字段名称、实体类字段类型等信息。相似于逆向工程,通过数据库表名、字段名、字段类型等信息生成实体信息。3.1.以MySQL的INFORMATION_SCHEMA信息获取为例咱们的代码主动生成是针对数据库操作,所以首先要理解数据库表的构造 SELECT column_name,data_type,is_nullable,character_maximum_length,column_commentFROM INFORMATION_SCHEMA.COLUMNS WHERE table_name='kpi_task' AND table_schema='home'ORDER BY ordinal_position如上图SQL查问的是home库,kpi_task表的信息,如下: ...

July 24, 2020 · 1 min · jiezi

关于spring:java开发两年连Spring中bean的装配都不知道你怎么涨薪啊

Spring1.1.1.1 创立一个beanpackage com.zt.spring;public class MyBean { private String userName; private Integer userAge;}1.1.1.2 配置Config 配置beanpackage com.zt.spring;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configurationpublic class MyBeanConfig { // 和xml中配置文件的bean的标签是一样的 @Bean(name = "beanName") public MyBean createBean(){ return new MyBean(); }}1.1.1.3 配置bean 单例还是多例的package com.zt.spring;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.Scope;@Configurationpublic class MyBeanConfig { @Bean(name = "beanName") // 默认值是多例的 xml的形式能够在bean的标签下面 设置这个参数 @Scope("prototype") public MyBean createBean(){ return new MyBean(); }}1.1.1.4 获取上文,获取beanpackage com.zt.spring;import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class App { public static void main(String[] args) { // 获取上下文 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyBeanConfig.class); // 通过bean的那么获取bean System.out.println(context.getBean("beanName")); // 获取bean的class文件获取 System.out.println(context.getBean(MyBean.class)); context.close(); }}1.1.2 通过FactoryBean实现bena的拆卸1.1.2.1 创立一个beanpackage com.zt.spring;public class Car {}1.1.2.2 配置Config 配置beanpackage com.zt.spring;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configurationpublic class MyBeanConfig { @Bean public CarFactoryBean createRunnableFactoryBean() { return new CarFactoryBean(); }}1.1.2.3 配置FactoryBean 生产beanpackage com.zt.spring;import org.springframework.beans.factory.FactoryBean;public class CarFactoryBean implements FactoryBean<Car> { //获取到对应的实体 @Override public Car getObject() throws Exception { return new Car(); } // 返回的额对应的是class文件 @Override public Class<?> getObjectType() { return Car.class; } //配置是不是单例 @Override public boolean isSingleton() { return true; }}1.1.2.4 获取上文,获取beanpackage com.zt.spring;import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class App { public static void main(String[] args) { // 获取上下文 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyBeanConfig.class); // 通过FactoryBean 创立的bean System.out.println(context.getBean(Car.class)); // 通过name获取car的实体 System.out.println(context.getBean("createRunnableFactoryBean")); context.close(); }}1.1.3 通过另外一种工工厂模式实现bena的拆卸1.1.3.1 创立一个beanpackage com.zt.spring;public class Jeep {}1.1.3.2 配置Config 配置beanpackage com.zt.spring;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configurationpublic class MyBeanConfig { @Bean public JeepFactory createJeepFactory() { return new JeepFactory(); } @Bean public Jeep createJeep(JeepFactory factory) { return factory.creat(); }}1.1.3.3 创立 Factory 实现构建办法package com.zt.spring;public class JeepFactory { public Jeep creat() { return new Jeep(); }}1.1.3.4 获取上文,获取beanpackage com.zt.spring;import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class App { public static void main(String[] args) { // 获取上下文 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyBeanConfig.class); System.out.println(context.getBean("createJeep")); System.out.println(context.getBean(Jeep.class)); context.close(); }}1.2 spring中bean的销毁办法1.2.1 调用spring本人的初始化和销毁的办法1.2.1.1 创立一个bean并且继承InitializingBean, DisposableBean ,实现afterPropertiesSet,destroy办法package com.zt.spring;import org.springframework.beans.factory.DisposableBean;import org.springframework.beans.factory.InitializingBean;public class User implements InitializingBean, DisposableBean { @Override public void afterPropertiesSet() throws Exception { System.out.println("=======afterPropertiesSet========"); } @Override public void destroy() throws Exception { System.out.println("=======destroy========"); }}1.2.1.2在conffig文件中拆卸这个beanpackage com.zt.spring;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configurationpublic class MyBeanConfig { @Bean public User createUser() { return new User(); }}1.2.1.3 获取上下文package com.zt.spring;import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class App { public static void main(String[] args) { // 获取上下文 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyBeanConfig.class); System.out.println(context.getBean(User.class)); context.close(); }}1.2.2 调用自定义初始化和销毁的办法1.2.2.1 创立一个bean自定义init,destroy办法package com.zt.spring;public class Dog { // 初始化办法 public void init() throws Exception { System.out.println("=======init========"); } // 销毁的办法 public void destroy() throws Exception { System.out.println("=======destroy========"); }}1.2.2.2在conffig文件中拆卸这个beanpackage com.zt.spring;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configurationpublic class MyBeanConfig { @Bean(initMethod = "init",destroyMethod = "destroy") public Dog createDog() { return new Dog(); }}1.2.2.3 获取上下文package com.zt.spring;import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class App { public static void main(String[] args) { // 获取上下文 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyBeanConfig.class); System.out.println(context.getBean(Dog.class)); context.close(); }}1.2.3 调用自定义并且注解初始化和销毁的办法1.2.3.1 创立一个bean自定义init,destroy办法 在加上注解放 @PostConstruct, @PreDestroy的形式实现package com.zt.spring;import javax.annotation.PostConstruct;import javax.annotation.PreDestroy;public class UserInfo { @PostConstruct public void afterPropertiesSet() throws Exception { System.out.println("=======afterPropertiesSet========"); } @PreDestroy public void destroy() throws Exception { System.out.println("=======destroy========"); }}1.2.3.2在conffig文件中拆卸这个beanpackage com.zt.spring;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configurationpublic class MyBeanConfig { @Bean public UserInfo createUserInfo() { return new UserInfo(); }}1.2.2.3 获取上下文package com.zt.spring;import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class App { public static void main(String[] args) { // 获取上下文 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyBeanConfig.class); System.out.println(context.getBean(UserInfo.class)); context.close(); }}1.4 pom.文件<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com..zt</groupId> <artifactId>spring</artifactId> <version>1.0-SNAPSHOT</version> <properties> <project.build.sourceEncodding>UTF-8</project.build.sourceEncodding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.20.RELEASE</version> </dependency> </dependencies></project>最初感激你看到这里,说的都是本人的一些认识和见解,如有不对,请斧正!感觉文章对你有帮忙的话无妨给我点个赞,每天都会分享java相干技术文章或行业资讯,欢送大家关注和转发文章! ...

July 23, 2020 · 3 min · jiezi

关于spring:要去面试先刷完这16道高频面试题阿里字节跳动美团任你选

1.JDK8 新个性Lambda 表达式-也是函数编程的一种形式(将函数做为参数)办法的利用,利用已有的java类对象的办法或者结构器。与Lambda表达式相结合,办法利用使得语言结构更加简洁,从而缩小代码的冗余默认办法,默认办法就是一个在接口里边有了一个实现的办法新工具-新的编译工具,如:Nashorn引擎jjs,类依赖分析器jdepsStream API  - 把真正的函数式编程格调引入到Java中。Date Time API - 增强对日期与工夫的解决Optional 类 - Optional 类曾经成为Java 8 类库的一部分,用来解决空指针异样Base64 Java8 内置了Base64 编码的编码器和解析器 2.hashMap 底层实现?当你put一个元素时,在底层构造是如何执行的?   首先须要晓得在不同的JDK版本下面hashMap 的实现是有区别的:    JDK8之前: 数组 + 链表    JDK8之后:数组 + 链表 + 红黑树 当你put元素时:  ####  执行步骤:   a.计算该元素的hashCode 值 b.通过计算它的hashCode 值去确定数组下标,数组的初始化16大小,增长因子为0.75   c.当存在哈希抵触是,雷同的hashCode 值得到的数组下标就是会一样的,则单纯的数组则不满足,须要链表的反对   d.链表满足长度大于8时转成红黑树,那为啥8呢,遵循泊松散布,红黑树均匀查找长度是log(n),长度为8的时候,均匀查找长度为3,如果持续应用链表,均匀查找长度为8/2=4,这才有转换为树的必要。 3.Spring 中AOP 与IOC的个性,应用场景是在哪些方面?AOP:面向切面编程,aspect oriented programming  面向切面为的是将日志记录,性能统计,安全控制,事务处理,异样解决等代码从业务逻辑代码中划分进去 次要的性能:日志记录,性能统计,安全控制,事务处理,异样解决等等 IOC:管制反转,就是创建对象的操作交给Spring容器来做。DI 依赖注入,spring通过xml配置文件实例化对象,依赖对象通过 setter办法获取。 4.Spring 注解有哪些?@Controller  用于标注管制层组件 @Service  用于业务层,也是实现接口 @Component 泛指组件,在不好归类状况下进行标注 @RequestMapping  申请映射,能够指定申请形式 @Resource 装bean注入应用:通过byName主动注入 ...

July 23, 2020 · 2 min · jiezi

关于spring:小书MybatisPlus第6篇主键生成策略精讲

本文为mybatis系列文档的第6篇,前5篇请拜访上面的网址。 小书MybatisPlus第1篇-整合SpringBoot疾速开始增删改查小书MybatisPlus第2篇-条件结构器的利用及总结小书MybatisPlus第3篇-自定义SQL小书MybatisPlus第4篇-表格分页与下拉分页查问小书MybatisPlus第5篇-Active Record模式精讲Mybatis Plus 为咱们提供了三种设置 主键生成策略的形式。它们的优先级程序是:部分注解 > 全局 > 默认(雪花算法)。上面咱们来一一介绍 一、默认主键生成策略:雪花算法Mybatis Plus如果不做任何主键策略配置,默认应用的是雪花算法。该策略会依据雪花算法生成主键ID,主键类型为Long或String(具体到MySQL数据库就是BIGINT和VARCHAR),该策略应用接口IdentifierGenerator的办法nextId(默认实现类为DefaultIdentifierGenerator雪花算法) snowflake算法是Twitter开源的分布式ID生成算法,后果是一个long类型的ID 。其核心思想:应用41bit作为毫秒数,10bit作为机器的ID(5bit数据中心,5bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每个毫秒能够产生4096个ID),最初还有一个符号位,永远是0。二、自定义主键策略mybatis-plus3.3.0当前,次要有五种主键生成策略。 public enum IdType { /** * 数据库ID自增,数据库须要反对主键自增(如MySQL),并设置主键自增 */ AUTO(0), /** * 该类型为未设置主键类型,默认应用雪花算法生成 */ NONE(1), /** * 用户输出ID,数据类型和数据库保持一致就行 * <p>该类型能够通过本人注册主动填充插件进行填充</p> */ INPUT(2), /* 以下3种类型、只有当插入对象ID 为空,才主动填充。 */ /** * 全局惟一ID (idWorker),数值类型 数据库中也必须是数值类型 否则会报错 */ ID_WORKER(3), /** * 全局惟一ID (UUID,不含中划线) */ UUID(4), /** * 字符串全局惟一ID (idWorker 的字符串示意),数据库也要保障一样字符类型 */ ID_WORKER_STR(5);}三、部分注解配置策略咱们针对主键设置主键策略应用注解形式为 @TableId(type = IdType.AUTO)private long userId;四、全局配置策略mybatis-plus: global-config: db-config: id-type: auto五、扩大应用5.1.INPUT用户输出ID策略的用法其中须要和大家非凡介绍的是:Input(用户输出ID),这个ID起源能够有两种 ...

July 23, 2020 · 1 min · jiezi

关于spring:Spring延迟依赖注入ObjectFactoryObjectProvider

ObjectProvider 继承自 ObjectFactory ObjectFactory提早注入 (繁多类型注入/汇合类型注入)ObjectProvider提早注入 (繁多类型注入/汇合类型注入) 举荐实体类Rumenz/SuperRumenz package com.rumenz;public class Rumenz{ private Integer id; private String name; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Rumenz{" + "id=" + id + ", name='" + name + '\'' + '}'; }}package com.rumenz;public class SuperRumenz extends Rumenz { private String type; public String getType() { return type; } public void setType(String type) { this.type = type; } @Override public String toString() { return "SuperRumenz{" + "type='" + type + '\'' + "} " + super.toString(); }}配置文件Beans.xml ...

July 22, 2020 · 2 min · jiezi

关于spring:Spring中的singleton和prototype

对于spring bean作用域,基于不同的容器,会有所不同,如BeanFactory和ApplicationContext容器就有所不同,在本篇文章,次要解说基于ApplicationContext容器的bean作用域。 对于bean的作用域,在spring中,次要包含singleton,prototype,session,request,global,本篇文章次要解说罕用的两种,即:singleton和prototype. 一  singletonsingleton为单例模式,即scope="singleton"的bean,在容器中,只实例化一次。 dao示例代码: package com.demo.dao;public class UserDao { public UserDao(){ System.out.println("UserDao 无参构造函数被调用"); } //获取用户名 public String getUserName(){ //模仿dao层 return "Alan_beijing"; }} applicationContext.xml <?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean class="com.demo.dao.UserDao" id="userDao" scope="singleton"/></beans> test: public class MyTest { @Test public void test(){ //定义容器并初始化 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); //定义第一个对象 UserDao userDao = applicationContext.getBean(UserDao.class); System.out.println(userDao.getUserName()); //定义第二个对象 UserDao userDao2 = (UserDao) applicationContext.getBean("userDao"); System.out.println(userDao2.getUserName()); //比拟两个对象实例是否是同一个对象实例 System.out.println("第一个实例:"+userDao+"\n"+"第二个实例:"+userDao2); }} 测试后果: 剖析:在测试代码中,将bean定义为singleton,并先后2次通过ApplicationContext的getBean()办法获取bean(userDao),却返回雷同的实例对象:com.demo.dao.UserDao@27a5f880,仔细观察,尽管获取bean两次,然而UserDao的无参构造函数却只被调用一次,这也证实了在容器中,singleton理论只被实例化一次,须要留神的是,Singleton模式的bean,ApplicationContext加载bean时,就实例化了bean。  定义bean: ...

July 22, 2020 · 1 min · jiezi

关于spring:SpringCloud-第十三篇-Zuul高层架构二

1:架构图 2:ZuulServletZuul的外围是一系列的filters,Zuul大部分性能都是通过过滤器来实现的 1:ZuulServlet是Zuul的外围类,用来调度不同阶段的filters,解决申请,并解决异样等,门路是/zuul,能够应用zuul.servlet-path属性更改此门路2:性能相似于SpringMvc的DispatcherServlet,所有的Request都要通过它的解决3:外面有三个外围办法:preRoute(),route(), postRoute()4:ZuulServlet会把具体的执行交给ZuulRunner去做,ZuulServlet是单例,因而ZuulRunner也仅有一个实例5:Zuul的过滤器之间没有间接的互相通信,它们之间通过一个RequestContext的动态类来进行数据传递的。RequestContext类中有ThreadLocal变量来记录每个Request所须要传递的数据,ZuulRunner会初始化RequestContext6:ZuulRunner间接将执行逻辑交由FilterProcessor解决,FilterProcessor也是单例,其性能就是根据filterType执行filter的解决逻辑,大抵过程如下:(1)依据Type获取所有输出该Type的filter(2)遍历执行每个filter的解决逻辑,processZuulFilter(ZuulFilter filter)(3)RequestContext对每个filter的执行情况进行记录,如果执行失败则对异样封装后抛出3:生命周期 4:过滤器类型与申请生命周期PRE:这种过滤器在申请被路由之前调用。可利用这种过滤器实现身份验证、在集群中抉择申请的微服务、记录调试信息等。ROUTING:这种过滤器将申请路由到微服务。这种过滤器用于构建发送给微服务的申请,并应用Apache HttpClient或Netfilx Ribbon申请微服务。POST:这种过滤器在路由到微服务当前执行。这种过滤器可用来为响应增加规范的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。ERROR:在其余阶段产生谬误时执行该过滤器。一般来说,如果须要在申请达到后端利用前就进行解决的话,会抉择前置过滤器,例如鉴权、申请转发、减少申请参数等行为。在申请实现后须要解决的操作放在后置过滤器中实现,例如统计返回值和调用工夫、记录日志、减少跨域头等行为。路由过滤器个别只须要抉择 Zuul 中内置的即可,谬误过滤器个别只须要一个,这样能够在 Gateway 遇到谬误逻辑时间接抛出异常中断流程,并间接对立解决返回后果5:外围过滤器5.1:概述在spring cloud zuul中,为了让api网关组件能够被更不便的应用,它在http申请生命周期的各个阶段默认实现了一批外围过滤器,它们会在api网关服务启动的时候被主动加载和启动。默认spring-cloud-netflix-core模块org.springframework.cloud.netflix.zuul.filters包下 5.2:pre过滤器ServletDetectionFilter用来检测以后申请是通过Spring的DispatcherServlet解决运行的,还是通过ZuulServlet来解决运行的。它的检测后果会以布尔类型保留在以后申请上下文的isDispatcherServletRequest参数中,这样后续的过滤器中,能够通过RequestUtils.isDispatcherServletRequest()和RequestUtils.isZuulServletRequest()办法来判断申请解决的源头,以实现后续不同的解决机制。个别状况下,发送到API网关的内部申请都会被Spring的DispatcherServlet解决,除了通过/zuul/*门路拜访的申请会绕过DispatcherServlet,被ZuulServlet解决。 FormBodyWrapperFilter:解析表单数据,并对上游申请进行从新编码。该过滤器仅对两类申请失效,第一类是Context-Type为application/x-www-form-urlencoded的申请,第二类是Context-Type为multipart/form-data并且是由String的DispatcherServlet解决的申请,而该过滤器的次要目标是将符合要求的申请体包装成FormBodyRequestWrapper对象 DebugFilter:该过滤器会依据配置参数zuul.debug.request和申请中的debug参数来决定是否执行过滤器中的操作。它的具体操作内容是将以后申请上下文中的debugRouting和debugRequest参数设置为true。因为在同一个申请的不同生命周期都能够拜访到这二个值,所以咱们在后续的各个过滤器中能够利用这二个值来定义一些debug信息,这样当线上环境呈现问题的时候,能够通过参数的形式来激活这些debug信息以帮忙剖析问题,另外,对于申请参数中的debug参数,咱们能够通过zuul.debug.parameter来进行自定义。 PreDecorationFilter:此过滤器依据提供的RouteLocator确定在哪里和如何路由。该过滤器会判断以后申请上下文中是否存在forward.do和serviceId参数,如果都不存在,那么它就会执行具体过滤器的操作(如果有一个存在的话,阐明以后申请曾经被解决过了,因为这二个信息就是依据以后申请的路由信息加载进来的)。另外,还能够在该实现中找到对HTTP头申请进行解决的逻辑,其中蕴含了一些耳熟能详的头域,比方X-Forwarded-Host,X-Forwarded-Port。对于这些头域是通过zuul.addProxyHeaders参数进行管制的,而这个参数默认值是true,所以zuul在申请跳转时默认会为申请减少X-Forwarded-*头域,包含X-Forwarded-Host,X-Forwarded-Port,X-Forwarded-For,X-Forwarded-Prefix,X-Forwarded-Proto。也能够通过设置zuul.addProxyHeaders=false敞开对这些头域的增加动作 5.3:route过滤器RibbonRoutingFilter:该过滤器只对申请上下文中存在serviceId参数的申请进行解决,即只对通过serviceId配置路由规定的申请失效。该过滤器的执行逻辑就是面向服务路由的外围,它通过应用ribbon和hystrix来向服务实例发动申请,并将服务实例的申请后果返回 SimpleHostRoutingFilter:该过滤器只对申请上下文存在routeHost参数的申请进行解决,即只对通过url配置路由规定的申请失效。该过滤器的执行逻辑就是间接向routeHost参数的物理地址发动申请,从源码中咱们能够晓得该申请是间接通过httpclient包实现的,而没有应用Hystrix命令进行包装,所以这类申请并没有线程隔离和断路器的爱护。 SendForwardFilter:该过滤器只对申请上下文中存在的forward.do参数进行解决申请,即用来解决路由规定中的forward本地跳转拆卸 5.4:post过滤器SendErrorFilter:该过滤器仅在申请上下文中蕴含error.status_code参数(由之前执行的过滤器设置的谬误编码)并且还没有被该过滤器解决过的时候执行。该过滤器的具体逻辑就是利用上下文中的错误信息来组成一个forward到api网关/error谬误端点的申请来产生谬误响应。 能够通过设置error.path属性来更改默认转发门路(/error)。 SendResponseFilter:该过滤器会查看申请上下文中是否蕴含申请响应相干的头信息,响应数据流或是响应体,只有在蕴含它们其中一个的时候执行解决逻辑。其解决逻辑就是利用上下文的响应信息来组织须要发送回客户端的响应内容 5.5:禁用过滤器重写shouldFilter逻辑,让它返回false通过配置来禁用:zuul.<SimpleClassName>.<filterType>.disable=true <SimpleClassName>代表过滤器的类名,<filterType>代表过滤器类型 6: 重试机制Zuul的重试机制是依赖于Spring-Retry的,因而pom.xml必须有spring-retry,<dependency>   <groupId>org.springframework.retry</groupId>   <artifactId>spring-retry</artifactId>  </dependency> 开启重试,也能够具体的为某个服务开启重试zuul.routes.user-api.retryable=true其中的user-api是路由名称,可自行自定义 而后是相应的hystrix和Ribbon的配置hystrix.command.default.execution.timeout.enabled=true  hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=2000  ribbon.ConnectTimeout=250  ribbon.ReadTimeout=1000  ribbon.OkToRetryOnAllOperations=true  ribbon.MaxAutoRetries=0  ribbon.MaxAutoRetriesNextServer=1  敞开重试机制全局敞开:zuul.retryable=false 指定路由敞开zuul.routes.<route>.retryable=false 7: 饿汉式加载Zuul外部应用Ribbon调用近程URL,并且Ribbon客户端默认在第一次调用时由Spring Cloud加载。能够应用以下配置更改Zuul的此行为:zuul.ribbon.eager-load.enabled=true 在Spring Cloud Zuul的饥饿加载中没有设计专门的参数来配置,而是间接采纳了读取路由配置来进行饥饿加载的做法。所以,如果咱们应用默认路由,而没有通过配置的形式指定具体路由规定,那么zuul.ribbon.eager-load.enabled=true的配置就没有什么作用了。因而,在真正应用的时候,能够通过zuul.ignored-services=*来疏忽所有的默认路由,让所有路由配置均保护在配置文件中,以达到网关启动的时候就默认初始化好各个路由转发的负载平衡对象8:上传文件8.1:对于小文件Zuul不必做任何特地配置,间接依照门路进行路由就能够了 8.2:对于大文件一个简略的计划就是应用在你的门路前增加上/zuul/,来绕开Spring的DispatcherServlet,以防止多局部解决,同时也躲避了后盾提取中文名乱码的问题。 要设置真正解决文件上传的利用,设置容许大文件上传,默认最大是10M,如:spring.http.multipart.enabled=truespring.http.multipart.max-file-size=1000Mbspring.http.multipart.max-request-size=1500Mb要设置zuul利用,次要是超时的问题,如:zuul.host.socket-timeout-millis=10000 zuul.host.connect-timeout-millis=10000hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=15000ribbon.ConnectTimeout=500ribbon.ReadTimeout=150009:健康检查退出依赖<dependency>   <groupId>org.springframework.boot</groupId>   <artifactId>spring-boot-starter-actuator</artifactId>  </dependency>  配置示例#开启健康检查(须要spring-boot-starter-actuator依赖)  eureka.client.healthcheck.enabled=true  #租期到期工夫,默认90秒  eureka.instance.lease-expiration-duration-in-seconds=30  #租赁更新工夫距离,默认30,即30秒发送一次心跳  eureka.instance.lease-renewal-interval-in-seconds=10 #hystrix dashboard的信息收集频率,默认500毫秒 ,设置dashboard的刷新频率hystrix.stream.dashboard.intervalInMilliseconds=5000 

July 22, 2020 · 1 min · jiezi

关于spring:Spring限定注入逻辑分组Qualifier

应用场景 当你创立多个具备雷同类型的 bean 时,并且想要用一个属性只为它们其中的一个进行拆卸,在这种状况下,你能够应用 @Qualifier 正文和 @Autowired 正文通过指定哪一个真正的 bean 将会被拆卸来打消凌乱。上面显示的是应用 @Qualifier 正文的一个示例。实体类Rumenz/SuperRumenz package com.rumenz;public class Rumenz{ private Integer id; private String name; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Rumenz{" + "id=" + id + ", name='" + name + '\'' + '}'; }}package com.rumenz;public class SuperRumenz extends Rumenz { private String type; public String getType() { return type; } public void setType(String type) { this.type = type; } @Override public String toString() { return "SuperRumenz{" + "type='" + type + '\'' + "} " + super.toString(); }}自定义注解@Grp进行逻辑分组用 ...

July 21, 2020 · 2 min · jiezi

关于spring:spring-boot-整合-ehcache

1. 该说的话每个人都该当学会独立地去思考、去寻找答案,而不是一味地伸手向别人索取所谓的标准答案。 首先,别成为“拿来主义”者,其次远离"拿来主义"的人。 2. ehcache2.1 次要个性疾速,简略.多种缓存策略缓存数据有两级:内存和磁盘,因而无需放心容量问题缓存数据会在虚拟机重启的过程中写入磁盘能够通过RMI、可插入API等形式进行分布式缓存具备缓存和缓存管理器的侦听接口反对多缓存管理器实例,以及一个实例的多个缓存区域提供Hibernate的缓存实现2.2 和redis相比ehcache间接在jvm虚拟机中缓存,速度快,效率高;然而缓存共享麻烦,集群分布式应用不不便。redis是通过socket拜访到缓存服务,效率比ecache低,比数据库要快很多.2.3 在应用程序中的地位 3. spring boot 整合1.搭建spring boot 我的项目 pom.xml文件中增加依赖<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId></dependency><dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache</artifactId></dependency>增加ehcache.xml配置文件<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd"><!-- 磁盘存储:将缓存中临时不应用的对象,转移到硬盘,相似于Windows零碎的虚拟内存 path:指定在硬盘上存储对象的门路 path能够配置的目录有: user.home(用户的家目录) user.dir(用户以后的工作目录) java.io.tmpdir(默认的长期目录) ehcache.disk.store.dir(ehcache的配置目录) 绝对路径(如:d:\\ehcache) 查看门路办法:String tmpDir = System.getProperty("java.io.tmpdir"); --> <diskStore path="java.io.tmpdir" /> <!-- defaultCache:默认的缓存配置信息,如果不加非凡阐明,则所有对象依照此配置项解决 maxElementsInMemory:设置了缓存的下限,最多存储多少个记录对象 eternal:代表对象是否永不过期 (指定true则上面两项配置需为0无限期) timeToIdleSeconds:最大的发愣工夫 /秒 timeToLiveSeconds:最大的存活工夫 /秒 overflowToDisk:是否容许对象被写入到磁盘 阐明:下列配置自缓存建设起600秒(10分钟)无效 。 在无效的600秒(10分钟)内,如果间断120秒(2分钟)未拜访缓存,则缓存生效。 就算有拜访,也只会存活600秒。 --> <defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="600" timeToLiveSeconds="600" overflowToDisk="true" /> <!--无效工夫: 7200秒 = 2小时 ,间断180秒 = 3分钟未拜访缓存,则生效--> <cache name="userCache" maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="1800" timeToLiveSeconds="7200" overflowToDisk="true" /></ehcache>启用缓存在启动类增加 @EnableCaching 注解。5.利用如下代码所示,你能够在函数上应用@Cacheable,@CachePut,@CacheEvict,来新增、更新、删除缓存。留神,当这个类中所有的缓存都处于同一缓存区时,你能够在类名上方应用@CacheConfig(cacheNames =userCache )来配置,这样在函数注解上就不须要再写 value = userCache。(cacheNames 的值在ehcache.xml文件中配置。) ...

July 21, 2020 · 1 min · jiezi

关于spring:SpringCloud-第十二篇-Zuul概念及原理一

1:Zuul是什么Zuul是Netflix开源的API网关。API网关,相似于面向对象设计模式中的Facade模式,它的存在就像是整个微服务架构零碎的门面一样,所有的内部客户端拜访都须要通过它来进行调度和过滤,它除了要实现申请路由,负载平衡,起源合法性检测,权限校验,反爬虫等性能之外,还须要更多能力,比方与服务治理框架的联合,申请转发时的熔断机制,服务的聚合等一系列的高级性能。官网:https://github.com/Netflix/zuul/ 2:Zuul能干什么身份验证和平安 - 辨认每个资源的身份验证要求,并回绝不满足的申请审查和监测 - 跟踪边缘的有意义的数据和统计数据,以便咱们精确地理解生产运行状况动静路由 - 依据须要将申请动静路由到不同的后端集群压力测试 - 逐步减少到集群的流量,以掂量性能负载调配 - 为每种类型的申请调配容量并删除超出限度的申请动态响应解决 - 间接在边缘构建一些响应,而不是将它们转发到外部集群3: 流程图 4:Zuul有什么Zuul蕴含了对申请的路由和过滤两个最次要的性能: 其中路由性能负责将内部申请转发到具体的微服务实例上,是实现内部拜访对立入口的根底而过滤器性能则负责对申请的处理过程进行干涉,是实现申请校验、服务聚合等性能的根底然而实际上,路由性能在真正运行时,它的路由映射和申请转发都是由几个不同的过滤器实现的。其中,路由映射次要通过pre类型的过滤器实现,它将申请门路与配置的路由规定进行匹配,以找到须要转发的指标地址;而申请转发的局部则是由route类型的过滤器来实现,对pre类型过滤器取得的路由地址进行转发5:HelloWorder退出依赖<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zuul</artifactId></dependency>配置示例,留神serviceId须要全小写eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/server.port=8780spring.application.name=service-zuulzuul.routes.api-a.path=/aa/**zuul.routes.api-a.serviceId=userservicezuul.routes.api-b.path=/bb/**zuul.routes.api-b.serviceId=service-feign启动类退出注解@EnableZuulProxy@EnableDiscoveryClient@SpringBootApplication1:@EnableZuulProxy开启Zuul服务,将本地调用转发到相应的服务,Zuul应用Ribbon来定位一个要转发到的服务实例,并且所有申请都以 hystrix命令执行2:留神@EnableZuulProxy不包含发现服务的客户端,因而对于基于服务ID的路由,还须要提供服务治理(例如Eureka)3:应用@EnableZuulServer也能够运行不带代理的Zuul服务器,差异是它不会主动增加任何代理过滤器,也没有服务发现和代理 测试运行1:如果配置文件外面没有配置zuul的话,zuul会把Eureka Server外面的服务都读取进去,此时运行的时候,须要用各个服务的serviceId做为ContextPath2:如果配置了zuul,还能够用配置的前缀代替服务的serviceId,而后进行拜访3:如果不心愿间接应用serviceId进行拜访,能够配置ignored-services: '’,例如:zuul.ignored-services='’,当然能够不必*,而是间接把要禁用的服务的serviceId列举进去,用逗号离开 6:传统路由配置所谓的传统路由配置形式就是在不依赖于服务发现机制的状况下,通过在配置文件中具体制订每个路由表达式实例的映射关系来实现api网关对外部申请的路由。 单实例配置:通过zuul.routes.<route>.path与zuul.routes.<route>.url参数对的形式进行配置,如: zuul.routes.cc.path=/cc/**zuul.routes.cc.url=http://localhost:8769多实例配置通过zuul.routes.<route>.path与zuul.routes.<route>.serviceId参数的形式进行配置,联合Ribbon来做负载平衡,且让Ribbon敞开和Eureka的联合,比方: zuul.routes.cc.path=/cc/**#zuul.routes.cc.url=http://localhost:8769zuul.routes.cc.serviceId=ccserviceribbon.eureka.enabled=falseccservice.ribbon.listOfServers=http://localhost:8769/,http://localhost:8768/   这种简略的URL路由不会被执行为HystrixCommand,也不能应用Ribbon对多个URL进行负载平衡 7:服务路由配置spring cloud zuul整合了spring cloud eureka,实现了对服务实例的自动化保护,那么应用服务路由配置的时候,不须要像传统路由配置形式那样为serviceId指定具体服务实例地址,只须要通过zuul.routes.<route>.path与zuul.routes.<route>.serviceId参数对的形式进行配置即可。还能够简化配置,间接设置<route>为具体的serviceId,例如: zuul.routes.service-feign.path=/dd/**请记得开启后面示例中敞开的Ribbon和Eureka的联合。 8:服务路由的默认规定大部分的路由规定机会都会采纳服务名作为内部申请的前缀,zuul曾经主动的帮咱们实现以服务名作为前缀的映射,不须要去配置它。如果不心愿内部能间接拜访,能够应用zuul.ignored-services参数来设置一个服务名匹配表达式来定义不主动创立路由的规定。 9:自定义路由映射关系有时候,为了兼容内部不同版本的客户端程序,咱们须要在微服务接口上定义版本的标记,比方:service-v1、 service-v2,而这样在映射的时候不太好治理。通常的做法是为这些不同版本的微服务利用,生成以版本号作为路由前缀定义规定的路由规定,比方/v1/userservice/,具体示例如下: @Beanpublic PatternServiceRouteMapper serviceRouteMapper(){ return new PatternServiceRouteMapper("(?<name>^.+)-(?<version>v.+$)","${version}/${name}");}门路匹配 在zuul中,路由匹配的门路表达式采纳ant格调定义:1:? 匹配任意单个字符2:* 匹配任意数量的字符3:** 匹配任意数量的字符,反对多级目录留神:当存在多个匹配的路由规定时,匹配后果齐全取决于路由规定的定义程序因为properties的配置内容无奈保障有序,所以当呈现这样的状况的时候,为了保障路由的优先程序,须要应用yml文件来配置,以实现有序的路由规定 10:cookie与头信息默认状况下,spring cloud zuul在申请路由时,会过滤掉http申请头信息中一些敏感信息,避免它们被传递到上游的内部服务器。默认的敏感头信息通过zuul.sensitiveHeaders参数定义,默认包含cookie,set-Cookie,authorization三个属性。这会引发一个常见的问题,应用了spring security,shiro等平安框架构建的web利用,通过spring cloud zuul构建的网关来进行路由时,因为cookie信息无奈传递,web利用将无奈实现登录和鉴权。为了解决这个问题,配置的办法能够为: 1:通过设置全局参数为空来笼罩默认值,如:zuul.sensitiveHeaders=不举荐这种做法,范畴太大2:将指定路由的敏感头设置为空,如:zuul.routes.userservice.sensitiveHeaders=11:重定向问题应用API网关的一个重要起因就是将网关作为对立入口,从而不裸露所有外部服务细节。但咱们在利用外部跳转的url却是具体web利用实例的地址,而不是通过网关的路由地址,该问题的根本原因在于spring cloud zuul在路由申请时,并没有将最后的host信息设置正确,怎么办呢?配置zuul.add-host-header=true即可 12:路由回退12.1:Hystrix和ribbon反对Spring Cloud Zuul默认集成了Hystrix和Ribbon,天然就领有线程隔离和断路器,以及对服务调用的客户端负载平衡性能。 须要留神的是,当应用path与url的映射关系来配置路由规定的时候,对于路由转发的申请不会采纳hystrixCommand来包装,所以这类申请没有线程隔离和断路器的爱护,并且也不会有负载平衡的能力。因而,咱们在应用zuul的时候尽量应用path和serviceId的组合来进行配置,这样不仅能够保障api网关的强壮和稳固,也能用到ribbon的客户端负载平衡性能。所有路由的默认Hystrix隔离模式(ExecutionIsolationStrategy)为SEMAPHORE12.2:Hystrix的路由回退能够通过创立ZuulFallbackProvider类型的bean来提供回退响应zuul首先会去判断是否存在自定义的zuulFallbackProvider,如果有,那么间接回调你自定义实现类的fallbackResponse()办法。如果不存在会走hystrix的fallback逻辑(有可能间接抛出异样)尽管Zuul提供了降级的回调办法fallbackResponse(),然而这个办法是无参的,也就是说此时尽管你可能给调用端返回一个音讯,然而此时你并不知道产生了什么样的异样(也就是说在这里你是获取不到异样信息的)。13:申请路由其它配置路由前缀zuul.prefix:为路由规定减少前缀,例如: zuul.prefix=/user。zuul.strip-prefix(默认为true):这个设置是在转发申请之前,从申请中删除代理前缀 本地跳转通过在serviceId中应用forward来指定须要跳转的服务器资源门路,例如:zuul.routes.api-t.path=/tt/**zuul.routes.api-t.serviceId=forward:/tt 疏忽表达式zuul.ignored-patterns:设置不心愿被api网关进行路由的url表达式。例如:ignoredPatterns: //products/留神:它的范畴并不是针对某个路由,而是对所有路由,所以要小心应用。 路由端点应用@EnableZuulProxy,将启用/routes端点,可返回映射路由的列表。能够通过将endpoints.routes.enabled设置为false来禁用此端点 配置属性zuul.max.host.connections已被两个新属性zuul.host.maxTotalConnections和zuul.host.maxPerRouteConnections替换,别离默认为200和20 ...

July 21, 2020 · 1 min · jiezi

关于spring:使用java8API遍历过滤文件目录及子目录及隐藏文件

1. 应用Files.list()迭代目录及其子目录文件Files.list()能够迭代目录及其子目录文件 Files.list(Paths.get(".")) //当前目录 .forEach(System.out::println);输入: .\filename1.txt.\directory1.\filename2.txt.\Employee.java2. 应用 filter表达式过滤文件过滤器函数援用,isRegularFile示意一般文件 Files.list(Paths.get(".")) .filter(Files::isRegularFile) //过滤器:只保留一般文件,过滤掉文件目录 .forEach(System.out::println);输入后果如下: .\filename1.txt.\filename2.txt.\Employee.java也能够应用lambda表达式进行过滤 Files.list(Paths.get(".")) .filter(s -> s.startsWith("file")) //过滤器:只保留以file结尾的文件及目录 .forEach(System.out::println);3. 应用 Files.newDirectoryStream()迭代目录及其子目录文件另一种更灵便的遍历目录的形式Files.newDirectoryStream(),如果咱们的目录文件又深又多,DirectoryStream能够使迭代目录的速度更快。 Files.newDirectoryStream(Paths.get(".")) .forEach(System.out::println);输入后果与Files.list()成果统一 .\filename1.txt.\directory1.\filename2.txt.\Employee.java4. 应用Files.newDirectoryStream()迭代指定文件后缀名的文件咱们能够为Files.newDirectoryStream()传递第二个参数,指定过滤条件,比方以java(结尾)为后缀名的文件 Files.newDirectoryStream(Paths.get("."), path -> path.toString().endsWith(".java")) .forEach(System.out::println);Output:.\Employee.java5. 遍历目录内的暗藏文件要查找所有暗藏文件,能够在过滤器中应用lambda表达式file -> file.isHidden()。或者,应用java8的办法援用。 final File[] files = new File(".").listFiles(file -> file.isHidden());//orfinal File[] files = new File(".").listFiles(File::isHidden);欢送关注我的博客,外面有很多精品合集本文转载注明出处(必须带连贯,不能只转文字):字母哥博客。感觉对您有帮忙的话,帮我点赞、分享!您的反对是我不竭的创作能源! 。另外,笔者最近一段时间输入了如下的精品内容,期待您的关注。 《手摸手教你学Spring Boot2.0》《Spring Security-JWT-OAuth2一本通》《实战前后端拆散RBAC权限管理系统》《实战SpringCloud微服务从青铜到王者》《VUE深入浅出系列》

July 21, 2020 · 1 min · jiezi

关于spring:Spring事务源码分析专题一JdbcTemplate使用及源码分析

Spring中的数据拜访,JdbcTemplate应用及源码剖析 前言本系列文章为事务专栏剖析文章,整个事务剖析专题将按上面这张图实现 image-20200718220712800 对源码剖析前,我心愿先介绍一下Spring中数据拜访的相干内容,而后层层递进到事物的源码剖析,次要分为两个局部 JdbcTemplate应用及源码剖析Mybatis的根本应用及Spring对Mybatis的整合本文将要介绍的是第一点。 JdbcTemplate应用示例public class DmzService { private JdbcTemplate jdbcTemplate; public void setDataSource(DataSource dataSource) { jdbcTemplate = new JdbcTemplate(dataSource); } /** * 查问 * @param id 依据id查问 * @return 对应idd的user对象 */ public User getUserById(int id) { return jdbcTemplate .queryForObject("select * from `user` where id = ?", new RowMapper<User>() { @Override public User mapRow(ResultSet rs, int rowNum) throws SQLException { User user = new User(); user.setId(rs.getInt("id")); user.setAge(rs.getInt("age")); user.setName(rs.getString("name")); return user; } }, id); } public int saveUser(User user){ return jdbcTemplate.update("insert into user values(?,?,?)", new Object[]{user.getId(),user.getName(),user.getAge()}); }}public class Main { public static void main(String[] args) { ClassPathXmlApplicationContext cc = new ClassPathXmlApplicationContext("tx.xml"); DmzService dmzService = cc.getBean(DmzService.class); User userById = dmzService.getUserById(1); System.out.println("查问的数据为:" + userById); userById.setId(userById.getId() + 1); int i = dmzService.saveUser(userById); System.out.println("插入了" + i + "条数据"); }}数据库中目前只有一条数据: ...

July 21, 2020 · 4 min · jiezi

关于spring:阿里面试官小伙子你给我说一下Spring-Bean初始化的几种常规方式吧

前言通过构造方法实例化通过动态工厂实例化通过实例工厂实例化通过FactoryBean实例化 RumenzA实体类package com.rumenz;public class RumenzA { private String id; private String name; public static RumenzA createRumenzA(){ RumenzA rumenzA=new RumenzA(); rumenzA.setId("123"); rumenzA.setName("入门小站"); return rumenzA; } public RumenzA() { System.out.println("RumenzA 无参构造方法"); } public RumenzA(String id) { this.id = id; System.out.println("ID构造方法"); } // set get省略}构造方法beans.xml<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="rumenz" class="com.rumenz.RumenzA" /><bean id="rumenz1" class="com.rumenz.RumenzA"> <constructor-arg name="id" value="1"/></bean></beans>DemoApplication.javapackage com.rumenz;import org.springframework.context.support.ClassPathXmlApplicationContext;public class DemoApplication { public static void main(String[] args) { ClassPathXmlApplicationContext ca=new ClassPathXmlApplicationContext("beans.xml"); RumenzA rumenzA=(RumenzA)ca.getBean("rumenz"); }}输入xxx.DefaultListableBeanFactory - Creating shared instance of singleton bean 'rumenz'RumenzA 无参构造方法xxx.DefaultListableBeanFactory - Creating shared instance of singleton bean 'rumenz1'ID构造方法动态工厂beans.xml<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="rFactory" class="com.rumenz.RumenzFactory" factory-method="rumenzFactory"/><bean id="rFactory1" class="com.rumenz.RumenzFactory" factory-method="rumenzFactory"> <constructor-arg name="id" value="111"/></bean></beans>RumenzFactory工厂类package com.rumenz;public class RumenzFactory { //静态方法 public static RumenzA rumenzFactory(){ return new RumenzA(); } public static RumenzA rumenzFactory(String id){ return new RumenzA(id); }}DemoApplication.javapackage com.rumenz;import org.springframework.context.support.ClassPathXmlApplicationContext;public class DemoApplication { public static void main(String[] args) { ClassPathXmlApplicationContext ca=new ClassPathXmlApplicationContext("beans.xml"); }}输入xxx.DefaultListableBeanFactory - Creating shared instance of singleton bean 'rFactory'RumenzA 无参构造方法xxx.DefaultListableBeanFactory - Creating shared instance of singleton bean 'rFactory1'ID构造方法实例工厂实例化<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="rFactory" class="com.rumenz.RumenzFactory" /> <bean id="rumenz" factory-bean="rFactory" factory-method="rumenzFactory"></bean> <bean id="rumenz1" factory-bean="rFactory" factory-method="rumenzFactory"> <constructor-arg name="id" value="666"></constructor-arg> </bean></beans>RumenzFactory.javapackage com.rumenz;public class RumenzFactory { //不能用静态方法 public RumenzA rumenzFactory(){ return new RumenzA(); } public RumenzA rumenzFactory(String id){ return new RumenzA(id); }}DemoApplication.javapackage com.rumenz;import org.springframework.context.support.ClassPathXmlApplicationContext;public class DemoApplication { public static void main(String[] args) { ClassPathXmlApplicationContext ca=new ClassPathXmlApplicationContext("beans.xml"); //RumenzA rumenzA=(RumenzA)ca.getBean("rFactory1"); }}输入xxx.DefaultListableBeanFactory - Creating shared instance of singleton bean 'rumenz'RumenzA 无参构造方法xxx.DefaultListableBeanFactory - Creating shared instance of singleton bean 'rumenz1'ID构造方法通过FactoryBean实例化beans.xml<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="rumenz-by-factoryBean" class="com.rumenz.RumenzAFactoryBean"/></beans>RumenzAFactoryBean.javapackage com.rumenz;import org.springframework.beans.factory.FactoryBean;public class RumenzAFactoryBean implements FactoryBean { @Override public Object getObject() throws Exception { return RumenzA.createRumenzA(); } @Override public Class<?> getObjectType() { return RumenzA.class; }}DemoApplication.javapackage com.rumenz;import org.springframework.context.support.ClassPathXmlApplicationContext;public class DemoApplication { public static void main(String[] args) { ClassPathXmlApplicationContext ca=new ClassPathXmlApplicationContext("beans.xml"); RumenzA rumenzA=(RumenzA)ca.getBean("rumenz-by-factoryBean"); }}输入/异步加载bean ...

July 20, 2020 · 2 min · jiezi

关于spring:spring注解驱动开发11-Spring声明式事务

1.数据源pom依赖spring-jdbc:<dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.7.RELEASE</version></dependency>mysql5.7的话, 留神依赖的版本: <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.49</version></dependency>2.dao层:2.1 数据库表构造:CREATE TABLE `t_user` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(50) DEFAULT NULL, `age` int(3) DEFAULT NULL, `gender` varchar(20) DEFAULT NULL, `is_active` tinyint(1) NOT NULL DEFAULT '1', PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf82.2 实体类 TUser.javapackage com.niewj.bean;import lombok.Data;@Datapublic class TUser { private int id; private String name; private int age; private String gender ;}2.3 数据拜访DAO:TUserDao.java package com.niewj.dao;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.stereotype.Repository;import java.util.Random;import java.util.UUID;@Repository("userDao")public class TUserDao { @Autowired private JdbcTemplate jdbcTemplate; public int saveUser() { String name = UUID.randomUUID().toString().replaceAll("-",""); int age = new Random().nextInt(35); String gender = "male"; // 这里写了单引号会报错 String insertSql = "insert into t_user(name, age, gender) values(?, ?, ?)"; int updated = jdbcTemplate.update(insertSql, name, age, gender); // --------- doCalc(); return updated; } // 做一些运算, 有可能异样, 如除法 public void doCalc(){ int value = 20/0; }}3.service层TUserService.java ...

July 20, 2020 · 3 min · jiezi

关于spring:2020腾讯阿里美团字节跳动面试真题整理全网首发面试突击必备

前言最近收到很多粉丝的私信,有工作几年的,也有行将面临毕业的学生党。都是来跟我说金九银十马上到了,本人想去冲击面试一波大厂,问我有没有相干的面试题分享。听到后我也是连忙为大家整顿了一份,话不多说满满的干货都在上面了,情谊提醒,文章篇幅齐全,全是干货缓缓观看!!! Redis什么是Redis?Redis的数据类型?应用Redis有哪些益处?Redis相比Memcached有哪些劣势?Memcache与Redis的区别都有哪些?Redis是单过程单线程的?一个字符串类型的值能存储最大容量是多少?Redis的长久化机制是什么?各自的优缺点?Redis常见性能问题和解决方案:redis过期键的删除策略?Redis的回收策略(淘汰策略) ?为什么Redis须要把所有数据放到内存中?Redis的同步机制理解么?Pipeline有什么益处,为什么要用pipeline?是否应用过Redis集群,集群的原理是什么?Redis集群计划什么状况下会导致整个集群不可用?Redis反对的Java客户端都有哪些?官网举荐用哪个?Jedis与Redisson比照有什么优缺点?Redis如何设置明码及验证明码?说说Redis哈希槽的概念?Redis集群的主从复制模型是怎么的?Redis集群会有写操作失落吗?为什么?Redis集群之间是如何复制的?Redis集群最大节点个数是多少?Redis集群如何抉择数据库?怎么则试Redis的连通性?怎么了解Redis事务?Redis事务相干的命令有哪几个?Redis key的过期工夫和永恒无效别离怎么设置?Redis如何做内存优化?Redis回收过程如何工作的?都有哪些方法能够升高Redis的内存应用状况呢?Redis的内存用完了会产生什么? MySQLMySQL中有哪几种锁?MySQL中有哪些不同的表格?简述在MySQI数据库中MyISM和InnoDB的区别MySQL中InmnoDB反对的四种事务隔离级别名称,以及逐级之间的区别?CHAE和VARCHR的区别?主键和候选键有什么区别?myi samchk是用来做什么的?如果一个表有一-列定义为TIMESTAMP, 将产生什么?你怎么看到为表格定义的所有索引?IIK申明中的%和是什么意思?列比照运算符是什么?BLOB和TEXT有什么区别?MySQL_ fetch_ arr ay和MySQL_ fetch_ object的区别是什么?MyISAM表格将在哪里存储,并且还提供其存储格局?MySQL如何优化DISTINCT?如何显示前50行?能够应用多少列创立索引?NOW ()和CURRENT DATE ()有什么区别?什么是非规范字符串类型?什么是通用SQL函数?MySQL反对事务吗?MySeL里记录货币用什么字段类型好MySQL无关权限的表都有哪几个?列的字符串类型能够是什么?MySQI数据库作公布零碎的存储,一天五万条以上的增里,预计运维三年,怎么优化?锁的优化策略 Spring什么是spring?应用Spring框架的益处是什么?Spr ing由哪些模块组成?外围容器(利用上下文)模块。BeanFactory – BeanFactory 实现举例。XMLBeanFactory解释AP模块解释JBC形象和DAD模块。解释对象/关系映射集成模块。解释WEB模块。Spring置文件什么是Spring IOC容器?IOC的长处是什么?ApplicationContext通常的实现是什么?Bean工厂和Applicati on contexts 有什么区别?一个Spring的利用看起来象什么?什么是Spring的依赖注入?有哪些不同类型的IOC (依赖注入)形式?哪种依赖注入形式你倡议应用,结构器注入,还是Setter办法注入?Spring Beans什么是Spring beans?一个Spring Bean定义蕴含什么?如何给Spring容器提供配置元数据?你怎么定义类的作用域?解释Spring反对的几种bean的作用域。 Java外围知识点Java外围知识点共29个技术模块,从各个角度深入浅出,对重点难点进行全方面解读,图文联合,通俗易懂,让学习成为一种享受。 JVM线程JM内存区域JVM运行时内存垃圾回收与算法JAVA 四中援用类型GC分代收集算法vS 分区收集算法GC垃圾收集器JAVA I0/NI0JVM类加载机制 Java多线程/并发JAVA并发知识库JAVA线程实现/创立形式4种线程池线程生命周期(状态)终止线程4种形式sleep与wait区别start与run区别JAVA后盾线程JAVA锁线程根本办法线程上下文切换同步锁与死锁线程池原理JAVA阻塞队列原理Cycli cBarrier、CountDownLatch、Semaphor e的用法volatile关键字的作用(变量可见性、禁止重排序)如何在两个线程之间共享数据ThreadLoca1作用 (线程本地存储)synchr oni ze Reentr antLock的区别Concur entHashMlap并发Java中 用到的线程调度过程调度算法什么是CAS (比拟并替换-乐观锁机制-锁自旋)什么是AQS (形象的队列同步器) Spring Boot什么是Spring Boot?为什么要用Spr ingBootSpring Boot有哪些长处?Spring Boot的外围注解是哪个?它次要由哪几个注解组成的?运行Spring Boot有哪几种形式如何了解Spring Boot中的Starters?如何在Spring Boot启动的时候运行一些特定的代码?Spring Boot须要独立的容器运行吗?Spring Boot中的监视器是什么?如何应用Spring Boot实现异样解决?你如何了解Spring Boot 中的StartersSpringboot罕用的star ter有哪些Spr ingBoot实现热部署有哪几种形式如何了解Spring Boot配置加载程序Spring Boot的外围配置文件有哪几个?它们的区别是什么?如何集成Spring Boot和ActiveMQ什么是JavaConfig?如何从新加载Spring Boot上的更改,而无需重新启动服务器?Spring Boot中的监视器是什么?如何在Spring Boot中禁用Actuator 端点安全性?如何在自定义端口上运行Spring Boot 应用程序?什么是YAML?如何实现Spring Boot应用程序的安全性?如何集成Spring Boot和ActiveMQ?如何应用Spring Boot 实现分页和排序?什么是Swagger? 你用Spring Boot实现了它吗? ...

July 20, 2020 · 1 min · jiezi

关于spring:真的简单文本文件逐行处理–用java8-Stream流的方式

本文中为大家介绍应用java8 Stream API逐行读取文件,以及依据某些条件过滤文件内容 1. Java 8逐行读取文件在此示例中,我将按行读取文件内容并在控制台打印输出。 Path filePath = Paths.get("c:/temp", "data.txt"); //try-with-resources语法,不必手动的编码敞开流try (Stream<String> lines = Files.lines( filePath )) { lines.forEach(System.out::println);} catch (IOException e) { e.printStackTrace();//只是测试用例,生产环境下不要这样做异样解决}下面的程序输入将在控制台中逐行打印文件的内容。 Neverstorepasswordexceptin mind.2.Java 8读取文件–过滤行在此示例中,咱们将文件内容读取为Stream。而后,咱们将过滤其中蕴含单词"password"的所有行。 Path filePath = Paths.get("c:/temp", "data.txt"); try (Stream<String> lines = Files.lines(filePath)){ List<String> filteredLines = lines .filter(s -> s.contains("password")) .collect(Collectors.toList()); filteredLines.forEach(System.out::println); } catch (IOException e) { e.printStackTrace();//只是测试用例,生产环境下不要这样做异样解决}程序输入。 password咱们将读取给定文件的内容,并查看是否有任何一行蕴含"password"而后将其打印进去。 3.Java 7 –应用FileReader读取文件Java 7之前的版本,咱们能够应用FileReader形式进行逐行读取文件。 private static void readLinesUsingFileReader() throws IOException { File file = new File("c:/temp/data.txt"); FileReader fr = new FileReader(file); BufferedReader br = new BufferedReader(fr); String line; while((line = br.readLine()) != null) { if(line.contains("password")){ System.out.println(line); } } br.close(); fr.close();}欢送关注我的博客,外面有很多精品合集本文转载注明出处(必须带连贯,不能只转文字):字母哥博客。感觉对您有帮忙的话,帮我点赞、分享!您的反对是我不竭的创作能源! 。另外,笔者最近一段时间输入了如下的精品内容,期待您的关注。 ...

July 20, 2020 · 1 min · jiezi

关于spring:利用tox打造自动自动化测试框架

什么是toxtox官网文档的第一句话 standardize testing in Python,意思就是说标准化python中的测试,那是不是很适宜测试人员来应用呢,咱们来看看他到底是什么? 依据官网文档的解释,tox是一个治理测试虚拟环境的命令行工具,能够反对穿件隔离的python环境,在外面能够装置不同版本的python解释器和我的项目的各种依赖库,能够进行自动化测试、打包以及继续集成。 tox能做什么 创立测试虚拟环境运行动态代码剖析与测试工具自动化构建包针对 tox 构建的软件包运行测试查看软件包是否能在不同的 Python 版本/解释器中顺利装置对立继续集成(CI)和基于命令行的测试怎么配置tox装置tox应用pip install tox装置,在命令行执行tox -e envname运行指定的测试环境 tox配置tox的行为既能够通过命令行来管制也能够通过配置文件进行管制,反对有以下三种模式的配置文件 pyproject.tomltox.inisetup.cfg# tox (https://tox.readthedocs.io/) is a tool for running tests# in multiple virtualenvs. This configuration file will run the# tests suite on all supported python versions. To use it, "pip install tox"# and then run "tox" from this directory.[tox]envlist = py36skipsdist = True# 设置pip源和依赖版本indexserver = default = http://mirrors.aliyun.com/pypi/simple/[testenv]deps = pytest records pymysql jinja2 requests objectpath arrow pytest-html redisinstall_command = pip install --trusted-host mirrors.aliyun.com {opts} {packages}[testenv:dev]setenv = env = dev; 通知tox在每个测试环境里运行pytestcommands = pytest --junitxml=junit-{envname}.xml;只运行广告相干的测试用例[testenv:t_a]setenv = env = devcommands = pytest -v tests/ad--junitxml=junit-{envname}.xml;只运行测试环境APP相干测试用例;只运行APP相干测试用例[testenv:t_i]setenv = env = devcommands = pytest -v tests/ivwen --junitxml=junit-{envname}.xml[testenv:t1_i]setenv = env = t1commands = pytest -v tests/ivwen --junitxml=junit-{envname}.xml[testenv:pro]setenv = env = pro; 通过command line往环境变量里写测试还是线上的标识,config依据标识从环境变量里去读取指定文件; 或者通过插件的模式,可能配置各个环境的文件,依据命令行参数指定把那个文件放入指定读取目录command = pytest[testenv:smoke][pytest]markers = smoke getaddopts = -rsxX -l --tb=short --strictxfail_strict = trueminversion = 3.0norecursedirs = .* venv src *.egg dist buildtestpaths = testspython_classes = *Test Test* *Suitjunit_family=xunit1以上配置解释如下: ...

July 19, 2020 · 1 min · jiezi

关于spring:spring注解开发ConfigurationBean

Configuration&Bean应用XML形式首先新建一个maven工程,增加如下依赖 <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.6.RELEASE</version></dependency>其次新建一个bean package com.yefengyu.spring.test.bean;public class Person { private String name; private Integer age; public Person(String name, Integer age){ this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; }}再次创立一个xml配置文件:spring.xml ...

July 19, 2020 · 2 min · jiezi

关于spring:Spring-Aware接口注入

Aware主动注入BeanNameAwareBeanFactoryAwareApplicationContextAwareMessageSourceAwareApplicationEventPublisherAwareResourceLoaderAwareAware接口形容BeanNameAware能够在Bean中失去它在IOC容器中的Bean的实例的名字BeanFactoryAware能够在Bean中失去Bean所在的IOC容器,从而间接在Bean中应用IOC容器的服务。ApplicationContextAware能够在Bean中失去Bean所在的利用上下文,从而间接在Bean中应用上下文的服务。MessageSourceAware在Bean中能够失去音讯源。ApplicationEventPublisherAware在bean中能够失去利用上下文的事件公布器,从而能够在Bean中公布利用上下文的事件。ResourceLoaderAware在Bean中能够失去ResourceLoader,从而在bean中应用ResourceLoader加载内部对应的Resource资源。 在设置Bean的属性之后,调用初始化回调办法之前,Spring会调用aware接口中的setter办法。实例类Holder/Rumenz package com.rumenz;import org.springframework.beans.factory.BeanNameAware;public class Holder implements BeanNameAware { private Rumenz rumenz; public Holder(Rumenz rumenz) { this.rumenz = rumenz; } public Rumenz getRumenz() { return rumenz; } public void setRumenz(Rumenz rumenz) { this.rumenz = rumenz; } @Override public void setBeanName(String name) { System.out.println("BeanName: "+name); }}// Rumenz.javapackage com.rumenz;public class Rumenz { private Integer id; private String name; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; }}配置文件Beans.xml ...

July 19, 2020 · 2 min · jiezi

关于spring:spring-bean-有五种作用域生命周期

spring bean 有五种作用域、两种治理Bean生命周期的形式。1、五种作用域a、Singleton (缺省作用域、单例类型)容器中只存在一个共享的Bean,只有id与Bean定义相匹配,那就会是同一个Bean。在容器启动(实例化)时Bean就实例化和初始化(能够通过lazy-init="true"来设置使得Bean被调用时才初始化)。 b、Prototype (原型类型)对有状态的Bean倡议应用Prototype,对无状态倡议应用Singleton。容器启动时并没有实例化Bean,只有获取Bean时才会被创立,并且每一次都是新建一个对象。 c、request(web的Spring ApplicationContext下)每个HTTP 都会有本人的Bean,当解决完结时,Bean销毁。 d、session(web的Spring ApplicationContext下)每一个Http session有本人的Bean e、global session(web的Spring ApplicationContext下)global session作用域相似于规范的HTTP Session作用域,不过仅仅在基于portlet的web利用中才有意义。Portlet标准定义了全局Session的概念,它被所有形成某个portlet web利用的各种不同的portlet所共享。在global session作用域中定义的bean被限定于全局portlet Session的生命周期范畴内。 2、生命周期 a、单例治理的对象Bean在容器启动时就会实例化和初始化,然而能够通过Bean的设置来设置对象的初始化机会第一种:通过设置<bean> <bean id="ServiceImpl" class="cn.csdn.service.ServiceImpl" lazy-init="true"/>第二种:通过设置<Beans>来批改所有bean默认形式的初始化机会 <beans default-lazy-init="true">b、非单例治理的对象Spring读取xml文件的时候,并不会立即创建对象,而是在第一次申请该bean时才初始化(如调用getBean办法时)。容器只会实例化和初始化Bean,不会销毁Bean。革除prototype作用域的对象并开释任何prototype bean所持有的低廉资源,都是客户端代码的职责。在初始化后交由调用者治理 参考:https://blog.csdn.net/fuzhong... 这篇博客有更加具体介绍。ps:自己学识无限,欢送指出谬误,互相交流学习。

July 18, 2020 · 1 min · jiezi