java基础

前言

新手常用方法
#日常使用分享

常用方法-面试-学习

一.equals和==详细区别
==是判断两个人是不是住在同一个地址,而equals是判断同一个地址里住的人是不是同一个
详解:

  • == 是关系运算符,equals() 是方法,结果都返回布尔值
  • Object 的 == 和 equals() 比较的都是地址,作用相同
    == 作用:
  • 基本类型,比较值是否相等
  • 引用类型,比较内存地址值是否相等
  • 不能比较没有父子关系的两个对象
    equals()方法的作用:
  • JDK 中的类一般已经重写了 equals(),比较的是内容
  • 自定义类如果没有重写 equals(),将调用父类(默认 Object 类)的 equals() 方法,Object 的 equals() 比较使用了 this == obj
  • 可以按照需求逻辑,重写对象的 equals() 方法(重写 equals 方法,一般须重写 hashCode 方法)
    二.–> 有多个实现类的时候
    @Autowired 注释进行自动注入时,Spring容器中匹配候选的Bean数目必须有经且有一个,当匹配不到一个时,有多个候选Bean时会报错 BeanCreationException异常,这样时Spring容许我们通过 @Qualifier 注释指定注入Bean的名称->@Qualifier(“XXX”)-XXX代表是Bean的名称
    三.多数据源配制->事务回滚->AOP->Stack转换为Map
    用的是注解-切面方式Aop

https://blog.csdn.net/qq_31142553/article/details/102768696

四.Java三步运算-{string-List互转}
1.三步运算->

saveOrg.setArea(areaInfo.getDistrictCode()  != null ? Long.valueOf(areaInfo.getDistrictCode()) : null);

2.String->List->Sort
*.第一种->直接转换list,Collections排序-建议

/**
* 格式转换-排序
* @param trialDaysConfiguration
* @return
*/
public static List<Integer> formatConversion(String trialDaysConfiguration){

    List<Integer> longs = new ArrayList<>();
    if (StringUtils.isNotBlank(trialDaysConfiguration)){
        longs = Arrays.stream(trialDaysConfiguration.split("\\,"))
                .map(s -> Integer.valueOf(s.trim()))
                .collect(Collectors.toList());
        Collections.sort(longs);
    }
    return longs;
}

**.转换成int数组,便利,排序-在通过Arrays方法转换成String,在截取–不建议
在这里插入图片描述

五:List增加默认值

https://www.cnblogs.com/javastack/p/10074847.html

List<Integer> list = Arrays.asList(1,2,3);

六: StringUtils

https://blog.csdn.net/ZT1090258642/article/details/92812407

stringUtils的isEmpty和isBlank的区别
当String=' ';时IsEmpty=trueIsBlank=Fales

七:String中的数字取出来,并且排序

String s= "1111lllll111lskksjsdksd1ww2323213";
List<String> stringList = new ArrayList<>();
//正则表达式
**String regex = "[^0-9]";
//String.trim()--去除字符串俩端的空白
**String s1 = Pattern.compile(regex).matcher(s).replaceAll("").trim();
for (int i=0; i<s1.length(); i++){
    stringList.add(s1.substring(i,i+1));
}
List<Integer> collect = stringList.stream().map(m -> Integer.valueOf(m.trim())).collect(Collectors.toList());
//sort正序
Collections.sort(collect);
System.out.println(collect);
//reverse倒序
Collections.reverse(collect);
System.out.println(collect);

八:面试宝典-题

https://blog.csdn.net/qq_41701956/article/details/103253168

****详情解释:

基础

~1.Math.round(-1.5)//-1 因为在数轴上取值时,中间值(0.5)向右取整,所以正 0.5 是往上取整,负 0.5 是直接舍弃
~2.StringBuffer 和 StringBuilder StringBuffer是线程安全的,Builder是线程不安全的,但是效率是最高的,单线程下建议Builder
~3.–>字符串反转

StringBuilder builder = new StringBuilder(s).reverse();

~4.普通类不能包含抽象方法,抽象类可以包含抽象方法 抽象类不能直接实例化,普通类可以直接实例化
~5.Files{exists-检测,createFile-创建文件,delete,move,copy,write,read,copy,size,createDirectory-创建文件夹}

容器

~6.Collections和Collection区别
collection是集合总类,里面直接继承的派生接口是List和Set
collections是工具类,其提供了一系列静态方法
~7.List,Set,Map常用方法

List:add,remove,clear,size,get,contains-包含
Set:add,remove,clear,size,contains->
Map:put,get,remove,clear,containsKey,containsValue,keySet,values,size

~8.HashMap和Hashtable区别
HashMap去掉了HashTable的contains方法,但是加上了containsValue和containsKey方法
HashTable是同步的,HashMap是非同步的,效率较高,且容许null值,而HashTable不容许
~9.HashMap和TreeMap区别
HashMap和TreeMap都是非线城安全,都继承了AbstractMap
HashMap是基于哈希表实现的,是无序的,通常用于Map的插入,删除,和定位
TreeMap是基于红黑树实现的,是有序的,适用于自然顺序或者自定义顺序遍历键(Key)
~10.HashSet的实现->底层是HashMap实现,他(HashSet)的值存放于HashMap的key上
~11.ArrayList和LinkedList的区别->ArrayList底层数据结构是数组,支持随机访问,而LinkedList是双向循环链表,不支持随机访问
~12.实现数组和List之间的相互转换->List->[]{Arrays.toArray}/[]->List{asList}
~13.Array和ArrayList区别->Array可以容纳基本类型和对象,而ArrayList只能容纳对象,Array是指定大小的,而ArrayList大小是固定的
~14.线程安全->Vector(已经不建议使用),Stack-堆栈类,先进后出,hashtable,enumeration->枚举
~15.迭代器Iterator
*迭代器是一种设计模式,它是一个对象可以遍历并选择序列中的对象,"轻量级"对象
*Iterator只能单向移动,继承了Collection接口,第一次调用Iterator的next()方法时,他返回序列的第一个元素
*使用next()方法获得序列中的下一个元素,hasNext()检查序列中是否还有元素,remove()将迭代器新返回的元素删除
*Iterator可以用来便利Set和List,Listiterator只能用来遍历list->可以多向遍历->实现了Iterator接口

线程

~16.并行与并发区别
并行是指俩个或多个事件在同一时刻发生,而并发是指俩个或多个事件在同一时间间隔发生->并行是不同实体的多个事件,并发是同一实体的多个事件
~17.线程简介
*一个进程里面可以有多个线程
*守护线程,是一个服务线程,服务于其他线程的线程

  • 创建线程的方式
    **1.继承Thread类创建线程类
    ***定义了Thread的子类,并重写了该类的run方法,run是该线程的执行体,创建了Thread子类的实例,即是创建了线程对象,调用start方法来启动该线程
    **2.通过Runnable接口创建线程类
    ***定义了Runnable接口的实现类,并重写了该接口的run方法,run同样是该线程的执行体,创建了Runnable的实现类的实例,并根据该实例作为Thread的target来创建Thread对象,调用start来启动该线程
    **3.通过Callable和Future创建线程
    ***创建了Callable接口的实现类,并实现了call方法,call是该线程的执行体,使用FutureTask对象封装了Callable对象的call,使用Future Task对象作为Thread对象的target来创建并启动新线程,Future Task对象的get方法来获取子线程结束后的返回值
    ~18.Runnable和Callable区别->Runnable接口中的run方法返回值是void,做的事是纯粹的执行run方法/Callable接口的call方法是有返回值的,是一个泛型,和·Future、Future Task配合用来获取异步执行的结果
    ~19.wait和sleep区别:
    sleep->是Thread的静态方法,让调用线程进入睡眠状态,不会释放锁,其他线程无法访问这个对象
    wait->是Object类的方法,当一个线程执行wait方法时,他会进入到一个和该对象相关的等待池,同时释放锁,使得其他线程可以访问,可以通过notify,notifyAll方法来唤醒等待的线程
    ~20.notify和notifyAll区别->当线程调用wait方法后,线程会处于该对象的等待池中,当线程调用对象的notify{随机唤醒一个wait线程},当调用notifyAll{时会唤醒所有的wait线程}
    ~21.run是本线程里的,只是线程里的一个函数,而不是多线程,run的执行路径只有一条,所以多线程执行时要使用start方法,而不是run
    ~22.创建线程池的方式:
    *newFixedThreadPool{固定长度的线程池,当线程发生未预期的错误而结束时,线程池会补充一个新的线程}
    *newCachedThreadPool{创建一个可缓存的线程池}
    *newSingleThreadExcutor{这是一个单线程的Exector,特点是能确保依照任务在队列中的顺序来串行执行}
    *newScheduledThreadPool{固定程度的线程池,类似于Timer}
    ~23.线程池的状态->{Running(shutdown->shutdown/shutdownNow->stop),Shutdown(队列为空,执行的任务以为空),Stop(线程池中执行的任务为空),Tidying,->(terminated执行完毕)Terminated}
    ~24.线程中的submit和execute区别->接收的参数不一样/submit有返回值,execute没有/submit方便Exception处理
    ~25.线程安全的体现->原子性{atomic-相斥访问,同一时刻只能有一个线程操作}/可见性{volatile-对主内存的修改可以及时被其他线程看到}/有序性{happens-before}
    ~26.死锁:死锁是指俩个或者俩个以上的进程在执行过程中,由于竞争相互造成的一种阻塞现象,如无外力作用,将无法推进下去
    *死锁的四个必要条件
    **互斥条件{进程被分配到的资源,不容许其他进程访问该资源}
    **请求和保持条件{进程获得一定资源后,又对其他资源发出请求,但是该资源可能被其他进程占有,此时阻塞,但是又对自己获得资源保持不放}
    **不可剥夺条件{是指进程已获得资源,在未使用前,不可被剥夺,只能用完后自己释放}
    **环路等待条件{进程发生死锁后,若干进程之间形成一种头尾相接的循环等待资源关系}
    只要四个条件之一不满足,就不会发生死锁
    ~27.ThreadLoacl->线程局部变量,不在多个线程间共享,任何线程局部变量一旦工作完成后没有释放,java应用就会存在内存泄漏的风险
    ~28.锁->synchronized可以保证方法或者代码运行时,同一时刻只有一个方法进入临界区,可以保证共享变量的内存可见性,java中每个对象都可以作为锁,这是synchronized实现同步的基础
    普通同步方法,锁是当前实例对象/静态同步方法,锁是当前类的class对象/同步方法块,锁是括号里面的对象
    ~29.synchronized和lock区别:
    synchronized是内置关键字,在Jvm里面,无法判断是否是锁的状态,会自动释放锁,可重入,不可中断,非公平,适合代码少量的同步问题
    Lock是个java类,可以判断是否可以获取到锁,需要在finally中手动是否锁,否则容易造成线程死锁,可重入,不可中断,非公平,适合大量代码同步问题

反射

~30.反射主要是指程序可以访问,检测和修改本身状态
提供了->
*在运行时判断任意一个对象所属的类
*在运行时构造任意一个类的对象
*在运行时判断任意一个类所具有的成员变量和方法
*在运行时调用任意一个对象的方法
~31.序列化
为了保存在内存中的各种对象的状态,并且把保存对象的状态在读出来/当你想把内存中的对象状态保存在一个文件中或者数据库中/使用套接字在网络上传送对象的时候/通过RMI传输对象的时候
~32.动态代理:
当想要给实现某个接口的类中的方法,加一些额外的处理,这个代理并不是定义好的,是动态生成的,具有解耦意义,灵活,拓展性强
应用->SpringAop/加事务/加权限/加日志
实现->首先必须定义一个接口,还要有一个InvocationHandler(将实现接口的类的对象传递给它)处理类。再有一个工具类Proxy(习惯性将其称为代理类,因为调用他的newInstance()可以产生代理对象,其实他只是一个产生代理对象的工具类)。利用到InvocationHandler,拼接代理类源码,将其编译生成代理类的二进制码,利用加载器加载,并将其实例化产生代理对象,最后返回。

Java Web

~33.JSP和servlet区别:
*Jsp编译后变成servlet{Jsp本质是servlet,web容器将Jsp代码编译成Jvm能够识别的java类}
*Jsp更擅长表现于页面显示,servlet更擅于逻辑控制
*Jsp是Service的一种简化,Jsp中的Java脚本镶嵌到Jsp容器中,Servlet是个完整的Java类,这个类的Service方法用于生成对客户端的响应
~34.Jsp的内置对象,作用:
9大内置对象:
request{封装客户端请求-接收前端}/response{封装服务器对客户端的响应-返回给前端}/pageContext{通过该对象获取其他对象}/session{封装客户端会话的对象}/application{封装服务器运行环境的对象}
out{输出服务器响应的输出流对象}/config{web应用的配置对象}/page{JSP页面本身-this}/exception{封装页面抛出异常的对象}
四种作用域:
page{代表一个页面的对象和熟悉},request{需要在页面显示的临时数据置身于此作用域},session{代表于某个用户与服务器建立的一次会话相关的对象和属性},application{}
~34.Session工作原理
其实session是一个存在服务器上的类似于散列表的文件,里面有我们需要的信息,在我们需要的时候可以取出来,相当于一个大号的Map,里面存的键就是用户的sessionId
~35.SpringMvc和struts的区别
*拦截机制-底层框架-性能-配置
**struts是类级别的拦截,只能设计为多例,采用fiter实现,容器启动后初始化,服务停止后坠毁,有自己的拦截机制-Interceptor机制,配置文件量比mvc大
**mvc是方法级别的拦截,在Spring整合时,默认时单例的·Singleton,线程是安全的,如果想要改变默认作用域,需要添加@Scope,是独立的Aop方式,底层采用servlet实现,实现了零配置,mvc和spring是无缝的,从项目管理来说安全性也比struts高
~36.如何避免sql注入
1.preparedStatement 2.正则表达式过滤传入的参数 3.字符串过滤 4.JSP中调用该函数检查是否包含非法字符 5.Jsp页面判断代码

异常

~37.throws和throw的区别
throws用来声明一个方法可能抛出所有的异常信息,声明异常但是不处理,往上传,谁调用我就交给谁,throw是指抛出一个具体的异常类型
~38.final,finally,finalize区别
*final可以修饰类,变量,方法,被修饰的全部不可以重写
*finally一般作用于try-catch里,在处理异常时,不管发生什么异常该代码块都会执行
*finalize是一个方法,属于Object类,由垃圾回收器调用finalize(),回收垃圾
~39.简单工厂和抽象工厂:
简单工厂由3个模式组成:
简单工厂:本身很简单而且使用在业务比较简单的情况下,一般是小项目或者具体产品很少拓展的情况
*工厂类角色:这个是本模式的核心,含有一定的商业逻辑和判断逻辑
*抽象产品角色:一般是具体产品继承的父类或者实现的接口,由接口或者抽象类来实现
*具体产品角色:工厂类所创建的对象就是此角色的实例
抽象工厂:它和工厂方法模式的区别就在于需要创建对象的复杂程度上。而且抽象工厂模式是三个里面最为抽象、最具一般性的。抽象工厂模式的用意为:给客户端提供一个接口,可以创建多个产品族中的产品对象
而且使用该模式要满足其中一个条件:
1.系统中多个产品类,而系统一次只能消费一族产品
2.同属于一个产品族的产品及其使用
*抽象工厂角色:这个是工厂模式的核心,与应用程序无关
*具体工厂角色:它含有和具体业务逻辑有关的代码
*抽象产品角色:它是具体产品继承的父类或者实现的接口
*具体产品角色:具体工厂角色所创建的对象就是此角色的实例
Spring/Spring MVC
~40.为什么要使用Spring
*简介
**目的:解决企业开发的复杂性
**功能:使用基本的JavaBean代替EJB,并提供了更多的企业应用功能
**范围:任务java应用
简单来说,Spring是一个轻量级的控制反转(IOC)和面向切面的(Aop)的容器框架
*轻量
从大小与开销方面而言Spring都是轻量的,是非侵入式的,典型的,Spring应用中的对象不依赖于Spring的特定类
*控制反转(IOC)
Spring通过一种称作控制反转的技术促进了松耦合,当应用了IOC,一个对象依赖的其他对象就会通过被动的方式来传递进来,而不是这个对象自己创建或者查找依赖的对象
*面向切面(AOP)
Spring提供了面向切面编程的丰富支持,容许通过分离应用的业务逻辑与系统级服务进行内聚性开发,应用对象只实现他们应该做的-完成业务逻辑-仅此而已
*框架
Spirng可以将简单的组件配置,组合成为复杂的应用,在Spring中,应用对象被声明式组合,典型的是在一个XML文件里,Spring也提供了很多基础功能(事务管理,持久化框架…),将应用逻辑开发留给了你
~41.Spring常用的注入方式:
Spring通过DI(依赖注入)实现IOC(控制反转),常用的注入方式->1.构造方法注入 2.setter注入 3.基于注解注入(Autowrited)
~42.Spring支持的记住bean的作用域
singleton{单例模式}/prototype{原型模式}/request/session{对于每次HTTP Session,使用session定义的Bean豆浆产生一个新实例。同样只有在Web应用中使用Spring时,该作用域才有效}/globalsession{典型情况下,仅在使用portlet context的时候有效}
~43.Spring自动装配bean方式->隐式的bean发现机制和自动装配/在java代码或者XML显示配置
~44.Spirng事务的实现方式:
*编程式事务管理对基于POJO的应用来说是唯一的选择,我们需要在代码中调用beginTransaction(),commit(),rollback()等事务管理相关的方法
*基于TransactionProxyFactoryBean的声明式事务管理
*基于@Transaction的声明式事务
*基于Aspectj AOP 配置事务
~45.spring的事务隔离:
事务隔离级别指的是一个事务对数据的修改与另一个并行的事务的隔离程度,当多个事务同时访问相同数据时,如没有采用隔离机制,会发生->脏读/幻读/不可重复读
~46.Spring MVC的组件:
1.DispatcherServlet{中央控制器,把请求发给具体的控制类} 2.Controller{具体处理请求的控制器} 3.HandlerMapping{映射处理器} 4.ModelAndView{服务层返回的数据和视图层的封装类} 5.ViewResolver{视图解析器} 6.Interceptors{拦截器}

IOC是通过Java的反射机制实现的,统一交给了Spring来管理创建,IOC是设计思想,DI(依赖注入)是实现方式。Aop则是利用了代理模式{动态代理/静态代理}
接口和抽象类有什么区别:

  • 实现:抽象类的子类使用 extends 来继承;接口必须使用 implements 来实现接口。

  • 构造函数:抽象类可以有构造函数;接口不能有。

  • main 方法:抽象类可以有 main 方法,并且我们能运行它;接口不能有 main 方法。

  • 实现数量:类可以实现很多个接口;但是只能继承一个抽象类。

  • 访问修饰符:接口中的方法默认使用 public 修饰;抽象类中的方法可以是任意访问修饰符。
    Java常用容器:

  • 自己总结的思维导图- 思维导图笔记

  • 在这里插入图片描述

  • collection的详细用法:

  • https://www.cnblogs.com/itliucheng/p/5176082.html

HashMap的实现原理:

  • HashMap概述: HashMap是基于哈希表的Map接口的非同步实现。此实现提供所有可选的映射操作,并允许使用null值和null键。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。
  • HashMap的数据结构: 在java编程语言中,最基本的结构就是两种,一个是数组,另外一个是模拟指针(引用),所有的数据结构都可以用这两个基本结构来构造的,HashMap也不例外。HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体。
  • 当我们往Hashmap中put元素时,首先根据key的hashcode重新计算hash值,根绝hash值得到这个元素在数组中的位置(下标),如果该数组在该位置上已经存放了其他元素,那么在这个位置上的元素将以链表的形式存放,新加入的放在链头,最先加入的放入链尾.如果数组中该位置没有元素,就直接将该元素放到数组的该位置上。
  • 需要注意Jdk 1.8中对HashMap的实现做了优化,当链表中的节点数据超过八个之后,该链表会转为红黑树来提高查询效率,从原来的O(n)到O(logn)
    线程的状态:
    线程通常都有五种状态,创建、就绪、运行、阻塞和死亡。
  • 创建状态。在生成线程对象,并没有调用该对象的start方法,这是线程处于创建状态。
  • 就绪状态。当调用了线程对象的start方法之后,该线程就进入了就绪状态,但是此时线程调度程序还没有把该线程设置为当前线程,此时处于就绪状态。在线程运行之后,从等待或者睡眠中回来之后,也会处于就绪状态。
  • 运行状态。线程调度程序将处于就绪状态的线程设置为当前线程,此时线程就进入了运行状态,开始运行run函数当中的代码。
  • 阻塞状态。线程正在运行的时候,被暂停,通常是为了等待某个时间的发生(比如说某项资源就绪)之后再继续运行。sleep,suspend,wait等方法都可以导致线程阻塞。
  • 死亡状态。如果一个线程的run方法执行结束或者调用stop方法后,该线程就会死亡。对于已经死亡的线程,无法再使用start方法令其进入就绪
    Session和Cookie有什么区别:
  • 由于HTTP协议是无状态的协议,所以服务端需要记录用户的状态时,就需要用某种机制来识具体的用户,这个机制就是Session.典型的场景比如购物车,当你点击下单按钮时,由于HTTP协议无状态,所以并不知道是哪个用户操作的,所以服务端要为特定的用户创建了特定的Session,用用于标识这个用户,并且跟踪用户,这样才知道购物车里面有几本书。这个Session是保存在服务端的,有一个唯一标识。在服务端保存Session的方法很多,内存、数据库、文件都有。集群的时候也要考虑Session的转移,在大型的网站,一般会有专门的Session服务器集群,用来保存用户会话,这个时候 Session 信息都是放在内存的,使用一些缓存服务比如Memcached之类的来放 Session。
  • 思考一下服务端如何识别特定的客户?这个时候Cookie就登场了。每次HTTP请求的时候,客户端都会发送相应的Cookie信息到服务端。实际上大多数的应用都是用 Cookie 来实现Session跟踪的,第一次创建Session的时候,服务端会在HTTP协议中告诉客户端,需要在 Cookie 里面记录一个Session ID,以后每次请求把这个会话ID发送到服务器,我就知道你是谁了。有人问,如果客户端的浏览器禁用了 Cookie 怎么办?一般这种情况下,会使用一种叫做URL重写的技术来进行会话跟踪,即每次HTTP交互,URL后面都会被附加上一个诸如 sid=xxxxx 这样的参数,服务端据此来识别用户。
  • Cookie其实还可以用在一些方便用户的场景下,设想你某次登陆过一个网站,下次登录的时候不想再次输入账号了,怎么办?这个信息可以写到Cookie里面,访问网站的时候,网站页面的脚本可以读取这个信息,就自动帮你把用户名给填了,能够方便一下用户。这也是Cookie名称的由来,给用户的一点甜头。所以,总结一下:Session是在服务端保存的一个数据结构,用来跟踪用户的状态,这个数据可以保存在集群、数据库、文件中;Cookie是客户端保存用户信息的一种机制,用来记录用户的一些信息,也是实现Session的一种方式。
    设计模式:

https://mp.weixin.qq.com/s__biz=MzIwMTY0NDU3Nw==&mid=2651938221&idx=1&sn=9cb29d1eb0fdbdb5f976306b08d5bdcc&chksm=8d0f32e3ba78bbf547c6039038682706a2eaf83002158c58060d5eb57bdd83eb966a1e223ef6&scene=21#wechat_redirect

**Aop:

  • AOP(Aspect-Oriented Programming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。OOP引入封装、继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力。也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系。例如日志功能。日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系。对于其他类型的代码,如安全性、异常处理和透明的持续性也是如此。这种散布在各处的无关的代码被称为横切(cross-cutting)代码,在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。
  • 而AOP技术则恰恰相反,它利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为“Aspect”,即方面。所谓“方面”,简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。AOP代表的是一个横向的关系,如果说“对象”是一个空心的圆柱体,其中封装的是对象的属性和行为;那么面向方面编程的方法,就仿佛一把利刃,将这些空心圆柱体剖开,以获得其内部的消息。而剖开的切面,也就是所谓的“方面”了。然后它又以巧夺天功的妙手将这些剖开的切面复原,不留痕迹。
  • 使用“横切”技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处都基本相似。比如权限认证、日志、事务处理。Aop 的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。正如Avanade公司的高级方案构架师Adam Magee所说,AOP的核心思想就是“将应用程序中的商业逻辑同对其提供支持的通用服务进行分离。”
  • 实现AOP的技术,主要分为两大类:一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;二是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码,属于静态代理
    **IOC:
  • 软件系统在没有引入IOC容器之前,对象A依赖于对象B,那么对象A在初始化或者运行到某一点的时候,自己必须主动去创建对象B或者使用已经创建的对象B。无论是创建还是使用对象B,控制权都在自己手上。
  • 软件系统在引入IOC容器之后,这种情形就完全改变了,由于IOC容器的加入,对象A与对象B之间失去了直接联系,所以,当对象A运行到需要对象B的时候,IOC容器会主动创建一个对象B注入到对象A需要的地方。
  • 通过前后的对比,对象A获得依赖对象B的过程,由主动行为变为了被动行为,控制权颠倒过来了,这就是“控制反转”这个名称的由来。
  • 控制反转也叫依赖注入,IOC利用java反射机制,AOP利用代理模式。所谓控制反转是指,本来被调用者的实例是有调用者来创建的,这样的缺点是耦合性太强,IOC则是统一交给spring来管理创建,将对象交给容器管理,你只需要在spring配置文件总配置相应的bean,以及设置相关的属性,让spring容器来生成类的实例对象以及管理对象。在spring容器启动的时候,spring会把你在配置文件中配置的bean都初始化好,然后在你需要调用的时候,就把它已经初始化好的那些bean分配给你需要调用这些bean的类
    **Spring MVC的运行流程:
  1. 用户向服务器发送请求,请求被Spring 前端控制Servelt DispatcherServlet捕获;
  2. DispatcherServlet对请求URL进行解析,得到请求资源标识符(URI)。然后根据该URI,调用HandlerMapping获得该Handler配置的所有相关的对象(包括Handler对象以及Handler对象对应的拦截器),最后以HandlerExecutionChain对象的形式返回;
  3. DispatcherServlet 根据获得的Handler,选择一个合适的HandlerAdapter;(附注:如果成功获得HandlerAdapter后,此时将开始执行拦截器的preHandler(…)方法)
  4. 提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)。 在填充Handler的入参过程中,根据你的配置,Spring将帮你做一些额外的工作:
  • HttpMessageConveter: 将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息
  • 数据转换:对请求消息进行数据转换。如String转换成Integer、Double等
  • 数据根式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等
  • 数据验证: 验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中
  1. Handler执行完成后,向DispatcherServlet 返回一个ModelAndView对象;
  2. 根据返回的ModelAndView,选择一个适合的ViewResolver(必须是已经注册到Spring容器中的ViewResolver)返回给DispatcherServlet ;
  3. ViewResolver 结合Model和View,来渲染视图;
  4. 将渲染结果返回给客户端。
  5. IOC的定义及实现原理—反射

http://blog.csdn.net/it_man/article/details/4402245

AOP的定义实现原理—代理

http://www.cnblogs.com/yanbincn/archive/2012/06/01/2530377.html

AOP的应用的三种实现方式

http://outofmemory.cn/code-snippet/3762/Spring-AOP-learn-example

Spring Cloud简单理解:
~47.Spring Cloud简介:
是一系列框架的集合,他利用了spring boot 的开发便利性巧妙的简化了分布式系统基础设施的开发,如服务注册,配置中心,消息总线,负载均衡,断路器,数据监控等,都可以用spring boot 的开发风格做到一键启动和部署
*eureka{微服务治理,服务注册和实现}
*ribbon{负载均衡,请求重试}
*hystrix{断路器,服务降级,熔断}
*feign{ribbon+hystrix集成,并提供声明式客户端}
*hystrix dashboard 和 turbine{hystrix 数据监控}
*zuul{Api网关,提供为服务的统一入口}
*config{配置中心}
*bus{消息总线,配置刷新}
*sleuth+zipkin{链路追踪}
核心思想:服务拆分与解耦,降低复杂性,微服务强调将功能合理拆解,尽可能保证每个服务的功能单一,亦可根据各个服务自身资源需求,单独部署,单独作横向拓展
~48.Spring Cloud 与 Dubbo 对比
*Dubbo->只是一个远程调用的RPC框架,默认基于长连接,支持多种序列化格式
*Spring Cloud->是一个框架集,提供了一套微服务解决方案(全家桶),基于http调用,Rest Api
~49.服务注册与发现Eureka
Eureka分为服务注册中心,服务提供者,服务消费者,服务消费者都必须指定注册中心,服务提供者提供服务,而服务消费者可以调用提供者的服务
服务发现的接口discoveryClient类是Spring Cloud对服务治理做的一层抽象
*注册中心->失效剔除{默认每隔一段时间(60s)将超时(90s)没有续约的服务剔除出去}/自我保护{Eureka Server在运行期间,会统计心跳失败的比例在15分钟之内低于85%得到保护起来}
*服务提供者->服务注册/服务续约{心跳检查机制-Eureka Server}/服务下线{Rest}
*服务消费者->获取服务{发生Rest请求给服务注册中心->获取上面注册的服务清单}/服务调用{获取服务清单后->通过服务名获取具体服务}
同为注册中心->Eureka/Zookeeper->分布式的CAP理论,C是一致性,A是可用性,P是分区容错性(必备) Eureka是AP,注重可用性,而Zookeeper是CP,注重一致性
Ribbon可以作为服务消费者,实现服务的调用以及客户端的负载均衡
Ribbon底层原理->负载均衡,轮询/重试机制{Eureka由于选择了可用性,所以在服务调用遇到实例故障时,可以使用重试机制}
Feign是一套基于Netflix Feign实现的声明式服务调用客户端,Feign可以作为消费者,底层原理是:动态代理,接口支持Spring Mvc的注解,Feign自带Ribbon,Feign的最终请求都是由Client组件完成的
Hystrix 断路器 服务熔断,雪崩效应{是一种因服务提供者的不可用导致服务调用者的不可用,并且逐渐放大的过程},熔断可以避免服务雪崩
Hystrix 可以进行服务降级,服务隔离,服务熔断
Spring Cloud技术组成:

在这里插入图片描述

Spring Cloud 对比Dubbo:
在这里插入图片描述

简单·理解Redis:
简介:
redis是一个非关系数据库,nosql,常用的数据类型有四种,String(字符串型),hash(散列类型),list(列表类型),set(集合类型),zset(有序集合类型)
用作缓存,主要用途:高性能,高并发,因为内存天然支持高并发
过期策略:{现在采用的是定期删除+惰性删除}
*定期删除:{redis会将每个设置了过期时间的key放入一个独立的字典中,以后会定期便利这个字典来删除到期的key,Redis默认会每秒进行十次过期扫描(100ms一次),过期扫描不会便利过期字典中所有的key,采用贪心策略}
*惰性删除:{是在客户端访问这个key时,redis对key的过期时间进行检查,过期了就会立即删除}
定期删除是集中处理,惰性删除是零散处理
内存淘汰策略:
*noeviction 不会继续服务写请求,都请求可以继续进行,默认的淘汰策略
*volatile-lru 尝试淘汰设置了过期时间地点key,最少使用的key优先被淘汰{使用最多}
*volatile-ttl key的剩余寿命值就是ttl值,ttl越小越优先被淘汰
*volatile-random 淘汰的key是过期key集合的随机的key
持久化策略:
Redis的数据是存在内存中的,若redis发生宕机,数据会丢失,持久化机制俩种{RDB-快照-全量备份/AOF-日志-增量备份}
在Redis4.0以后推出了混合持久化,将rdb文件的内容和增量的AOF日志文件存在一起

mvc全局异常处理

后端定义异常抛出给前端-为用户展示

@RestControllerAdvice
public class MyControllerAdvice {
    /**
     * 全局异常捕捉处理
     * @param exception
     * @return
     */
    @ExceptionHandler(value = Exception.class)
    public Map errorHandler(Exception exception) {
        Map map = new HashMap();
        map.put("code", 100);
        map.put("message", "系统正在更新,请稍后重试");
        return map;
    }

    /**
     * 拦截捕捉自定义异常 ServerRuntimeException.class
     * @param exception
     * @return
     */
    @ExceptionHandler(value = ServerRuntimeException.class)
    public Map myErrorHandler(ServerRuntimeException exception) {
        Map map = new HashMap();
        //暂且默认-1
        map.put("code", "-1");
        map.put("message", exception.getMessage());
        return map;
    }
}

----
public class ServerRuntimeException extends RuntimeException{
    private String message;
    private String code;


    public ServerRuntimeException(String message) {
        super(message);
        this.message = message;
    }


    public ServerRuntimeException(String message, Throwable throwable) {
        super(message, throwable);
        this.message = message;
    }


    public ServerRuntimeException(String code, String message) {
        super(message);
        this.code = code;
        this.message = message;
    }


    public ServerRuntimeException(String code, String message, Throwable cause) {
        super(message, cause);
        this.code = code;
        this.message = message;
    }


    public String getMessage() {
        return message;
    }


    public void setMessage(String message) {
        this.message = message;
    }


    public String getCode() {
        return code;
    }


    public void setCode(String code) {
        this.code = code;
    }
}

javax.ws.rs-jax-rs

又叫Java API for RESTful Services

全局异常定义

  1. 总类
@Provider
public class GenericExceptionMapper implements ExceptionMapper<Throwable> {
    private static Logger logger = LoggerFactory.getLogger(GenericExceptionMapper.class);
    @Override
    public Response toResponse(Throwable exception) {
        if(exception == null) 
           return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();

        logger.error("Server exception: {}. Info: {}" , exception.getClass().getSimpleName(), exception.getMessage());
        logger.error("", exception);
        
        // if api not found
        if (exception.getClass() == NotFoundException.class)
           return Response.status(Response.Status.NOT_FOUND).build();
        
        // if api method type does not match
        if (exception.getClass() == NotAllowedException.class)
           return Response.status(Response.Status.METHOD_NOT_ALLOWED).build();
        
        // if api media type incorrect
        if (exception.getClass() == NotSupportedException.class)
           return Response.status(Response.Status.UNSUPPORTED_MEDIA_TYPE).build();

        // if request parameter incorrect
        if (exception instanceof LtRuntimeException) {
            IErrorStatus errorStatus = ((LtRuntimeException) exception).getErrorStatus();
            RestResponse<Object> restResponse = RestResponse.builder().code(errorStatus.getCode() + "").message(errorStatus.getMessage()).build();
            return Response.status(Response.Status.OK).entity(restResponse).build();
        }

        // if request material advice ServerRuntimeException
        if (exception instanceof ServerRuntimeException) {
            IErrorStatus errorStatus = ((ServerRuntimeException) exception).getErrorStatus();
            RestResponse<Object> restResponse = RestResponse.builder().code(errorStatus.getCode() + "").message(errorStatus.getMessage()).build();
            return Response.status(Response.Status.OK).entity(restResponse).build();
        }

        // for other errors
        String rootError = null;
        if (exception.getCause() != null)
           rootError =  exception.getCause().getMessage();
        // TODO define our internal error code instead of directly sending raw error to the user
        rootError = String.format("Server error: [%s], please contact the administrator!", rootError == null ? exception.getMessage() : rootError);
        logger.error("Root error: {}", rootError);
        String errorResponse = "Server error: please contact the administrator!";
        return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(errorResponse).build();
    }
  1. 每个异常
@Getter
public class ServerRuntimeException extends RuntimeException {

    private IErrorStatus errorStatus;

    /**
     * Construct a {@code LtRuntimeException} with a error status and http status
     *
     * @param errorStatus customized error status
     */
    public ServerRuntimeException(IErrorStatus errorStatus) {
        super(errorStatus.getMessage());
        this.errorStatus = errorStatus;
    }

    /**
     * Construct a {@code LtRuntimeException} with a error status and cause
     *
     * @param errorStatus customized error status
     * @param cause
     */
    public ServerRuntimeException(IErrorStatus errorStatus, Throwable cause) {
        super(errorStatus.getMessage(), cause);
        this.errorStatus = errorStatus;
    }
}

@Getter
public enum ErrorStatus implements IErrorStatus {


    CONTENT_IMAGE_ERROR(10001, "**,**!"),
    ;

    private final int code;

    private final String message;


    ErrorStatus(int code, String message) {
        this.code = code;
        this.message = message;
    }

    /**
     * 根据code获取ErrorStatus
     * @param code
     * @return
     */
    public ErrorStatus getByCode(int code) {
        for (ErrorStatus status : ErrorStatus.values()) {
            if (status.code == code) {
                return status;
            }
        }
        return null;
    }

    @Override
    public String toString() {
        return "{" +
                "\"code\":" + code +
                ", \"message\":\"" + message + "\"" +
                "}";
    }
}

public interface IErrorStatus {

    /**
     * 获取code
     * @return
     */
    int getCode();

    /**
     * 获取消息
     * @return
     */
    String getMessage();
}

基础用法「比较全套」:https://blog.csdn.net/setlilei/article/details/99211804

常用API总结(持续更新)

  1. 假分页
public static List<?> getPageList(List<?> list,int page,int pageSize){
    int totalCount=list.size();
    int pageCount=0;
    int m=totalCount%pageSize;
    if  (m>0){
        pageCount=totalCount/pageSize+1;
    }else{
        pageCount=totalCount/pageSize;
    }
    List<?> subList = Lists.newArrayList();
    for(int i=1;i<=pageCount;i++){
        if(page==i) {
            if (m==0&&page==1){
                subList = list.subList((i-1)*pageSize,pageSize*(i));
            }else{
                if (i==pageCount){
                    subList= list.subList((i-1)*pageSize,totalCount);
                }else{
                    subList= list.subList((i-1)*pageSize,pageSize*(i));
                }
            }
        }
    }
    return subList;
}
  1. 日期–{时间格式相互转换}
//String转换Date
public static Date formatDate(String time) {
    if (StringUtils.isNotEmpty(time)) {
        try {
            return sdf.parse(time);
        } catch (ParseException e) {
            logger.error("parse string to date error.string={}", time);
        }
    }
    return null;
}

//Date转换String
public static String formatDate(Date date) {
    if (Objects.isNull(date)){
        return null;
    }
    FastDateFormat sdf = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss");
    return sdf.format(date);
}

日常工具

IDEA破解

https://blog.csdn.net/weixin_47833466/article/details/119612898

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值