面试题总结

1、重载(Overload)和重写(Override)的区别
答:方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为重载;重写发生在子类与父类之间,重写要求子类被重写方法与父类被重写方法有相同的参数列表,有兼容的返回类型,比父类被重写方法更好访问,不能比父类被重写方法声明更多的异常(里氏代换原则)。重载对返回类型没有特殊的要求,不能根据返回类型进行区分。
2、=和equals的区别
答:对于=来说,基本类型和引用类型中的作用是不同的:
基本类型:值
应用类型:引用地址
对于equals来说,本质上是==,只不过Integer和String重写了equals方法,变成了值比较,也就是缺省时比较引用是否相同,重写了之后是值比较
3、进程和线程
答:进程:在操作系统中能够独立运行,并且作为资源分配的基本单位。它表示运行中的程序。系统运行一个程序就是一个进程从创建、运行到消亡的过程。
线程:是一个比进程更小的执行单位,能够完成进程中的一个功能,也被称为轻量级进程。一个进程在其执行的过程中可以产生多个线程。
4、多线程面试题:现在有T1、T2、T3三个线程,你怎样保证T2在T1执行完后执行,T3在T2执行完后执行?
问:现在有T1、T2、T3三个线程,你怎样保证T2在T1执行完后执行,T3在T2执行完后执行?
答:要保证T1、T2、T3三个线程顺序执行,可以利用Thread类的join方法。
问:join方法的作用?
答: Thread类中的join方法的主要作用就是同步,它可以使得线程之间的并行执行变为串行执行。当我们调用某个线程的这个方法时,这个方法会挂起调用线程,直到被调用线程结束执行,调用线程才会继续执行。
问:join方法传参和不传参的区别?
答:join方法中如果传入参数,则表示这样的意思:如果A线程中掉用B线程的join(10),则表示A线程会等待B线程执行10毫秒,10毫秒过后,A、B线程并行执行。需要注意的是,jdk规定,join(0)的意思不是A线程等待B线程0秒,而是A线程等待B线程无限时间,直到B线程执行完毕,即join(0)等价于join()。
问:join与start调用顺序问题
答:join方法必须在线程start方法调用之后调用才有意义。这个也很容易理解:如果一个线程都没有start,那它也就无法同步了。因为执行完start方法才会创建线程。
问:join方法实现原理
答:join方法是通过调用线程的wait方法来达到同步的目的的。例如A线程中调用了B线程的join方法,则相当于在A线程中调用了B线程的wait方法,当B线程执行完(或者到达等待时间),B线程会自动调用自身的notifyAll方法唤醒A线程,从而达到同步的目的。
问:回归到题目,手写一个确保T1、T2、T3的执行顺序的代码

public class JoinTestSync {
    public static void main(String[] args) throws InterruptedException {
        // TODO Auto-generated method stub
        ThreadJoinTest1 t1 = new ThreadJoinTest1("今天");
        ThreadJoinTest1 t2 = new ThreadJoinTest1("明天");
        ThreadJoinTest1 t3 = new ThreadJoinTest1("后天");
        /*
         * 通过join方法来确保t1、t2、t3的执行顺序
         * */
        t1.start();
        t1.join();    
        t2.start();
        t2.join();
        t3.start();
        t3.join();
    }
    

}


class ThreadJoinTest1 extends Thread{
    public ThreadJoinTest1(String name){
        super(name);
    }
    @Override
    public void run(){
        for(int i=0;i<5;i++){
            System.out.println(this.getName() + ":" + i);
        }
    }
}
复制代码
执行结果

复制代码
今天:0
今天:1
今天:2
今天:3
今天:4
明天:0
明天:1
明天:2
明天:3
明天:4
后天:0
后天:1
后天:2
后天:3
后天:4

5、Sleep和Wait的区别:
答:
Sleep是线程的静态方法,是线程用来控制自身流程的,也就是说它会使线程暂停执行一段时间,把执行的机会给其他的线程,等睡眠时间一过,自动苏醒【不会释放锁】
Wait是Object方法,他是用于线程之间的通讯(中间人),改方法会使当前拥有该对象锁的线程等待,知道有其他的线程调用notify、notifyall或者wait超时才会苏醒 【会释放锁】
Sleep那都能用,wait只能用于同步方法或者同步代码块中
6、Java中Lock接口比synchronized块的优势是什么
答:lock接口在多线程和并发编程中最大的优势是它们为读和写分别提供了锁
【关键字】synchronized 是Java内置的关键字,使用后会自动释放锁
Lock是java.util.concurrent.Locks 包下的一个接口,必须要手动释放。特别是在发生异常时,需要在 finally 块中进行手动释放,否则会发生死锁行为
【中断】Lock可响应中断,而synchronized 不能响应中断,并且Lock提供了更丰富的方法实现
【锁类型】synchronized 是非公平锁+悲观锁,即不能保证等待锁线程的顺序,
乐观锁 + Lock的实现 ReentrantLock 可通过实例化true or false 的构造参数实现公平锁和非公平锁,默认为非公平锁
【状态】synchronized无法判断是否获取锁的状态,Lock可以判断是否获取到锁;
【代码量】Lock锁适合大量同步的代码的同步问题,synchronized锁适合代码少量的同步问题。
7、为什么我们调用start()方法时会执行run()方法,为什么我们不能直接调用run()方法?
答:调用start()方法时你将创建新的线程,并且执行在run()方法里的代码。但是如果你直接调用run()方法,它不会创建新的线程也不会执行调用线程的代码
8、Java中你怎样唤醒一个阻塞的线程
答:如果线程遇到了IO阻塞,我并且不认为有一种方法可以中止线程。如果线程因为调用wait()、sleep()、或者join()方法而导致的阻塞,你可以中断线程,并且通过抛出InterruptedException来唤醒它

9、什么是Spring
答:Spring是一个分层的JavaSE/EE full-stack(一站式)轻量级开源框架,是一种非侵入式(non-invasive)框架,它可以使应用程序代码对框架的依赖最小化。
  方便解耦、简化开发:Spring就是一个大工厂,可以将所有对象的创建和依赖关系的维护工作都交给Spring容器的管理,大大的降低了组件之间的耦合性。
  支持AOP:Spring提供了对AOP的支持,它允许将一些通用任务,如安全、事物、日志等进行集中式处理,从而提高了程序的复用性。
  支持声明式事务处理:只需要通过配置就可以完成对事物的管理,而无须手动编程。
  支持多数主流框架的集成:如hibernate、mybatis、struts等
10、什么是IOC?谈谈对IOC的理解
  IOC(Inversion of Control):控制反转,将对象的创建权反转(交给)Spring,Spring会根据配置文件去创建实例和管理各个实例之间的依赖关系,对象与对象之间松散耦合,也利于功能的复用。说白了就是,IOC让对象的创建不用去new了,可以由spring自动生产,使用java的反射机制,根据配置文件在运行时动态的去创建对象以及管理对象,并调用对象的方法。
  IOC还有一种叫法:DI(Dependency Injection)依赖注入,这两个名词其实是同一个意思,要深入理解的话就是:IOC是一种设计模式,是一种思想,相当于一个容器,而DI就好比是实现IOC的一种方式。
11、什么是AOP?谈谈对AOP的理解
  AOP(Aspect Oriented Programming)面向切面编程,是OOP(面向对象编程)的延伸。
  用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被命名为“切面”(Aspect),减少系统中的重复代码,降低了模块间的耦合度,同时提高了系统的可维护性。可用于权限认证、日志、事务处理。
  Spring中的AOP代理离不开Spring的IOC容器,代理的生成,管理及其依赖关系都是由IOC容器负责。AOP实现的关键在于代理模式,AOP代理主要分为静态代理和动态代理。静态代理的代表为AspectJ;动态代理则以Spring AOP为代表。AspectJ是静态代理的增强,也被称为编译时增强;Spring AOP 又被称为运行时增强。静态代理与动态代理区别在于生成AOP代理对象的时机不同,相对来说AspectJ的静态代理方式具有更好的性能,但是AspectJ需要特定的编译器进行处理,而Spring AOP则无需特定的编译器处理。
  Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理:JDK动态代理只提供接口的代理,不支持类的代理。核心InvocationHandler接口和Proxy类,InvocationHandler 通过invoke()方法反射来调用目标类中的代码,动态地将横切逻辑和业务编织在一起;接着,Proxy利用 InvocationHandler动态创建一个符合某一接口的的实例, 生成目标类的代理对象。
12、什么是Spring Bean
Spring Bean就是被Spring IOC容器初始化,装配和管理的Java对象。
命周期:实例化 -> 属性赋值 -> 初始化 -> 销毁
13、Spring基于xml注入依赖的方式有哪些?
  set方法注入、构造器注入、静态工厂注入、实例工厂注入
14、Spring事务管理的方式有哪些?
  编程式事务管理(了解)
  声明式事务管理(重点):声明式事务管理建立在AOP之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。声明式事务最大的优点就是不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明(或通过基于@Transactional注解的方式),便可以将事务规则应用到业务逻辑中。
  7中事务传播方式
   propagation_required
   propagation_supports
   propagation_requires_new
   propagation_not_supproted
   propagation_mandatory
   propagation_never
   propagation_nested
   四种隔离级别(isolation)
隔离级别:未提交读、提交读、可重复读、可串行化
15、Spring的通知
前置、后置、环绕、异常、最终

16、VUE
轻量级框架:只关注视图层,是一个构建数据的视图集合,大小只有几十kb;
简单易学:国人开发,中文文档,不存在语言障碍 ,易于理解和学习;
双向数据绑定:保留了angular的特点,在数据操作方面更为简单;
组件化:保留了react的优点,实现了html的封装和重用,在构建单页面应用方面有着独特的优势;
视图,数据,结构分离:使数据的更改更为简单,不需要进行逻辑代码的修改,只需要操作数据就能完成相关操作;
虚拟DOM:dom操作是非常耗费性能的, 不再使用原生的dom操作节点,极大解放dom操作,但具体操作的还是dom不过是换了另一种方式;
运行速度更快:相比较与react而言,同样是操作虚拟dom,就性能而言,vue存在很大的优势。
17、父子组件传值
父 【props】 子 子 【$emit】 父
18、什么是 vue 生命周期?有什么作用?
答:每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做 生命周期钩子 的函数,这给了用户在不同阶段添加自己的代码的机会。(ps:生命周期钩子就是生命周期函数)例如,如果要通过某些插件操作DOM节点,如想在页面渲染完后弹出广告窗, 那我们最早可在mounted 中进行。
生命周期钩子:8个阶段 创建前/后,载入前/后,更新前/后,销毁前/后。【beforeCreate, created, beforeMount, mounted,beforeUpdate,updated,destroy】
19、vuex有哪几种属性?
答:有五种,分别是 State、 Getter、Mutation 、Action、 Module
state => 基本数据(数据源存放地)
getters => 从基本数据派生出来的数据
mutations => 提交更改数据的方法,同步!
actions => 像一个装饰器,包裹mutations,使之可以异步。
modules => 模块化Vuex

20、抽象类(abstract class)和接口(interface)有什么异同?
不同点:
● 抽象类中可以定义构造器,接口不能;
● 抽象类可以有抽象方法和具体方法,接口不能有具体方法;
● 接口中的成员全都是 public 的,抽象类中的成员可以使用private、public、protected、默认等修饰;
● 抽象类中可以定义成员变量,接口中只能是常量;
● 有抽象方法的类必须被声明为抽象类,而抽象类未必要有抽象方法;
● 抽象类中可以包含静态方法,接口中不能有静态方法;
● 一个类只能继承一个抽象类,一个类可以实现多个接口;
相同点:
● 不能够实例化;
● 可以将抽象类和接口类型作为引用类型;
● 一个类如果继承了某个抽象类或者实现了某个接口都需要对其中的抽象方法全部进行实现,否则该类仍然需要被声明为抽象类;

21、abstract class和interface有什么区别?(抽象类与接口的区别)
声明方法的存在不去实现他的类被叫做抽象类(abstrct class),它用于要创建一个体现某些基本行为的类,并为该类声明方法,但不能在类终中实现该类的情况,不能创建abstract类的实例。然而可以创建一个变量,其类型就是一个抽象类,并让他指向具体的子类的一个实例。不能有抽象构造函数或抽象静态方法,abstract类的子类为他们的父类中的所有抽象方法提供实现,否则他们也是抽象类为,取而代之,在子类中是实现该方法。知道其行为的其他类可以在类中实现这些方法。
接口(interface)是抽象类的变体,在接口中,所有方法都是抽象的。多继承性可通过实现这样的接口而获得。接口中的所有方法都是抽象的,没有一个有程序体,接口只可以定义static final成员变量,接口的实现与子类相似,除了个实现类不能从从接口定义中继承行为,当类实现特殊的接口时,他定义(即将程序给予)多有这种接口的犯法,然后,它可以在实现了该接口的类的任何对象上调用接口的方法,由于抽象类,它允许使用接口名作为应用变量的类型。通常的动态联编将生效,引用可以转换到接口类型或从接口类型转换,instanceof运算符可以用来决定某对象的类是实现了接口。

22、什么是 Spring Boot
Spring Boot 是 Spring 开源组织下的子项目,是 Spring 组件一站式解决方案,主要是简化了使用 Spring 的难度,简省了繁重的配置,提供了各种启动器,开发者能快速上手。
独立运行、简化配置、自动配置、无代码生成和XML配置、应用监控、上手容易

23、运行 Spring Boot 有哪几种方式?
1)打包用命令或者放到容器中运行
2)用 Maven/ Gradle 插件运行
3)直接执行 main 方法运行

24、Spring Boot 有哪几种读取配置的方式?
Spring Boot 可以通过 @PropertySource,@Value,@Environment, @ConfigurationProperties 来绑定变量
加载顺序
1)properties文件;
2)YAML文件;
3)系统环境变量;
4)命令行参数;

25、什么是Spring Cloud
Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、智能路由、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。
Spring Cloud并没有重复制造轮子,它只是将各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过Spring Boot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。

26、Reids的特点  
Redis本质上是一个Key-Value类型的内存数据库,整个数据库统统加载在内存当中进行操作,定期通过异步操作把数据库数据flush到硬盘上进行保存。因为是纯内存操作,Redis的性能非常出色,每秒可以处理超过 10万次读写操作,是已知性能最快的Key-Value DB。
  Redis的出色之处不仅仅是性能,Redis最大的魅力是支持保存多种数据结构,此外单个value的最大限制是1GB,不像 memcached只能保存1MB的数据,因此Redis可以用来实现很多有用的功能,比方说用他的List来做FIFO双向链表,实现一个轻量级的高性 能消息队列服务,用他的Set可以做高性能的tag系统等等。另外Redis也可以对存入的Key-Value设置expire时间,因此也可以被当作一 个功能加强版的memcached来用。
Redis的主要缺点是数据库容量受到物理内存的限制,不能用作海量数据的高性能读写,因此Redis适合的场景主要局限在较小数据量的高性能操作和运算上。
(1) 速度快,因为数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1)
(2) 支持丰富数据类型,支持string,list,set,sorted set,hash
(3) 支持事务,操作都是原子性,所谓的原子性就是对数据的更改要么全部执行,要么全部不执行
(4) 丰富的特性:可用于缓存,消息,按key设置过期时间,过期后将会自动删除
27、Redis是单进程单线程的
redis利用队列技术将并发访问变为串行访问,消除了传统数据库串行控制的开销
28、什么是Nginx?
Nginx是一个 轻量级/高性能的反向代理Web服务器,他实现非常高效的反向代理、负载平衡,他可以处理2-3万并发连接数,跨平台、配置简单、反向代理、高并发连接,而且Nginx内置的健康检查功能:如果有一个服务器宕机,会做一个健康检查,再发送的请求就不会发送到宕机的服务器了。重新将请求提交到其他的节点上。
使用Nginx的话还能:
节省宽带:支持GZIP压缩,可以添加浏览器本地缓存
稳定性高:宕机的概率非常小
接收用户请求是异步的
29、Nginx怎么处理请求的?
nginx接收一个请求后,首先由listen和server_name指令匹配server模块,再匹配server模块里的location,location就是实际地址

30、ArrayList、LinkedList、Vector的区别
ArrayList:数组,不安全
Vector:数组,安全
LinkedList:双向链表,不安全
数组:可以根据下标快速查找,所以大部分情况下,查询快。但是如果要进行增删操作的时候,会需要移动修改元素后面的所有元素,所以增删的开销比较大,数组的对增删操作的执行效率低。而采用数组作为数据存储结构的ArrayList、Vector也存在这些特性,查询速度快(可以根据下标直接取,比迭代查找更快),增删慢。
链表:增加和删除元素方便,增加或删除一个元素,仅需处理结点间的引用即可。就像人手拉手连成一排,要增加或删除某个人只要附近的两个人换一个人牵手,对已经牵好手的人没影响。无论在哪里换人耗费的资源和时间都是一样的。但是查询不方便,需要一个个对比,无法根据下标直接查找。而采用链表结构存储的LinkedList也有这些特性,增删方便,查询慢(指的是随机查询,不是顺序查询)。

31、算法
二分法查找:折半查找,每次查询时,将数据分为前后两部分,在用中值和待搜索的值进行比较,如果搜索值>中值 在后半段查找依次进行
只适用于有序的数据
裴波那切数列:“黄金分割数列”“兔子数列”
前一项与后一项之比越来越接近黄金分割数值-0.618
第三项开始(包含第三项)=前两项之和
冒泡排序:通过相邻数据的交换达到排序的目的
选择排序:每一轮循环找到最小的值,依次排列数组最前面
插入排序:依次把当前循环的元素,通过对比插入到合适的位置的排序算法
快速排序:“改进版的冒泡”“左右开弓”
堆排序:二叉树(该结点的键要大于左子树中所有结点的键,而小于右子树中所有结点的键)+对结构

32、Hashmap hashtable的区别
① HashMap 是Hashtable 的轻量级实现(非线程安全的实现),他们都完成了Map 接口,
主要区别
②【空值】HashMap 允许空(null)键值(key),而Hashtable 不允许
③【效率】由于非线程安全,效率上HashMap可能高于Hashtable。
④【contains】HashMap 把Hashtable 的contains 方法去掉了,改成containsvalue 和containsKey。因为contains方法容易让人引起误解。
⑤【来源】Hashtable 继承自Dictionary 类,而HashMap 是Java1.2 引进的Map interface 的一个实现。
⑥【Synchronize】Hashtable 的方法是Synchronize 的,而HashMap 不是,在多个线程访问Hashtable 时,不需要自己为它的方法实现同步,而HashMap 就必须为之提供外同步。

33、乐观锁与悲观锁
乐观锁是一种乐观思想,即认为读多写少,遇到并发写的可能性低,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,采取在写时先读出当前版本号,然后加锁操作(比较跟上一次的版本号,如果一样则更新),如果失败则要重复读-比较-写的操作。Java中的乐观锁基本都是通过CAS操作实现的,CAS 是一种更新的原子操作,比较当前值跟传入值是否一样,一样则更新,否则失败。
悲观锁是就是悲观思想,即认为写多,遇到并发写的可能性高,每次去拿数据的时候都认为别人会修改,所以每次在读写数据的时候都会上锁,这样别人想读写这个数据就会block直到拿到锁。
Java中的悲观锁就是Synchronized,AQS框架下的锁则是先尝试cas乐观锁去获取锁,获取不到,才会转换为悲观锁,如 RetreenLock。

34、在什么情况下索引会失效
①【or】如果条件中有or,即使其中有条件带索引也不会使用
②【复合索引】对于多列索引,不是使用的第一部分,则不会使用索引
③【like】like查询是以%开头
④【字符串】如果列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不使用索引
⑤【MySQL】如果mysql认为全表扫面要比使用索引快

35、Mysql中有哪几种锁?
①表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。
②行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
③页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。

36、SQL标准定义的四个隔离级别为:
read uncommited :读到未提交数据
read committed:脏读,不可重复读
repeatable read:可重读
serializable :串行事物

37、Thymeleaf
①特点:
a、动静结合:Thymeleaf 在有网络和无网络的环境下皆可运行,即它可以让美工在浏览器查看页面的静态效果,也可以让程序员在服务器查看带数据的动态页面效果。这是由于它支持 html 原型,然后在 html 标签里增加额外的属性来达到模板+数据的展示方式。浏览器解释 html 时会忽略未定义的标签属性,所以 thymeleaf 的模板可以静态地运行;当有数据返回到页面时,Thymeleaf 标签会动态地替换掉静态内容,使页面动态显示。
b、开箱即用:它提供标准和spring标准两种方言,可以直接套用模板实现JSTL、 OGNL表达式效果,避免每天套模板、该jstl、改标签的困扰。同时开发人员也可以扩展和创建自定义的方言。
c、多方言支持:Thymeleaf 提供spring标准方言和一个与 SpringMVC 完美集成的可选模块,可以快速的实现表单绑定、属性编辑器、国际化等功能。
d、与SpringBoot完美整合,SpringBoot提供了Thymeleaf的默认配置,并且为Thymeleaf设置了视图解析器,我们可以像以前操作jsp一样来操作Thymeleaf。代码几乎没有任何区别,就是在模板语法上有区别。
②语法:Thymeleaf的主要作用是把model中的数据渲染到html中,因此其语法主要是如何解析model中的数据
a、Thymeleaf通过${}来获取model中的变量,注意这不是el表达式,而是ognl表达式,但是语法非常像。

					<h1>
    					你好:<span th:text="${user.name}">请跟我来</span>
					</h1>
				
				## 感觉跟el表达式差不多的。区别在于,我们的表达式写在一个名为:th:text的标签属性中,这个叫做指令
			b、指令:Thymeleaf中所有的表达式都需要写在"指令"中,指令是HTML5中的自定义属性,在Thymeleaf中所有指令都是以th:【浏览器不支持H5用data-th-text】开头,因为表达式${user.name}是写在自定义属性中,因此在静态环境下,表达式的内容会被当做是普通字符串,浏览器会自动忽略这些指令,这样就不会报错了。如果我们不经过SpringMVC,而是直接用浏览器打开编写的页面:在静态环境下,th指令不会被识别,但是也不会报错,而是显示<span>标签的缺省默认值:"请跟我来"

指令的设计,正是Thymeleaf的高明之处,也是它优于其它模板引擎的原因。动静结合的设计,使得无论是前端开发人员还是后端开发人员可以完美契合。
另外,th:text指令出于安全考虑,会把表达式读取到的值进行处理,防止html的注入。
例如,

你好

将会被格式化输出为 l t ; p lt;p lt;pgt;你好 l t ; / p lt;/p lt;/plt;。
如果想要不进行格式化输出,而是要输出原始内容,则使用th:utext来代替.
		ognl提供了类似js的语法方式:例如:${user.name} 可以写作${user['name']}

首先在 h2上 用 th:object="${user}"获取user的值,并且保存

然后,在h2内部的任意元素上,可以通过 *{属性名}的方式,来获取user中的属性,这样就省去了大量的user.前缀了

<h2 th:object="${user}">
    <p>Name: <span th:text="*{name}">Jack</span>.</p>
    <p>Age: <span th:text="*{age}">21</span>.</p>
    <p>friend: <span th:text="*{friend.name}">Rose</span>.</p>
</h2>

ognl表达式本身就支持方法调用

<h2 th:object="${user}">
    <p>FirstName: <span th:text="*{name.split(' ')[0]}">Jack</span>.</p>
    <p>LastName: <span th:text="*{name.split(' ')[1]}">Li</span>.</p>
</h2>

hymeleaf内置对象

Thymeleaf中提供了一些内置对象,并且在这些对象中提供了一些方法,方便我们来调用。获取这些对象,需要使用#对象名来引用。

一些环境相关对象

对象 作用
#ctx 获取Thymeleaf自己的Context对象
#requset 如果是web程序,可以获取HttpServletRequest对象
#response 如果是web程序,可以获取HttpServletReponse对象
#session 如果是web程序,可以获取HttpSession对象
#servletContext 如果是web程序,可以获取HttpServletContext对象

Thymeleaf提供的全局对象:

对象 作用
#dates 处理java.util.date的工具对象
#calendars 处理java.util.calendar的工具对象
#numbers 用来对数字格式化的方法
#strings 用来处理字符串的方法
#bools 用来判断布尔值的方法
#arrays 用来护理数组的方法
#lists 用来处理List集合的方法
#sets 用来处理set集合的方法
#maps 用来处理map集合的方法
举例

我们在环境变量中添加日期类型对象

@GetMapping(“test3”)
public String show3(Model model){
model.addAttribute(“today”, new Date());
return “hello3”;
}
在页面中处理

今天是: 2018-04-25

方法_字面值
有的时候,我们需要在指令中填写基本类型如:字符串、数值、布尔等,并不希望被Thymeleaf解析为变量,这个时候称为字面值。

字符串字面值

使用一对’引用的内容就是字符串字面值了:

你正在观看 template 的字符串常量值.

th:text中的thymeleaf并不会被认为是变量,而是一个字符串

数字字面值

数字不需要任何特殊语法, 写的什么就是什么,而且可以直接进行算术运算

今年是 1900.

两年后将会是 1902.

布尔字面值

布尔类型的字面值是true或false:

你填的是true
这里引用了一个th:if指令,跟vue中的v-if类似

方法_拼接
我们经常会用到普通字符串与表达式拼接的情况:


字符串字面值需要用’’,拼接起来非常麻烦,Thymeleaf对此进行了简化,使用一对|即可:


运算
需要注意: 内 部 的 是 通 过 O G N L 表 达 式 引 擎 解 析 的 , 外 部 的 才 是 通 过 T h y m e l e a f 的 引 擎 解 析 , 因 此 运 算 符 尽 量 放 在 {}内部的是通过OGNL表达式引擎解析的,外部的才是通过Thymeleaf的引擎解析,因此运算符尽量放在 OGNLThymeleaf{}外进行。

算术运算

支持的算术运算符:+ - * / %

//21
//false
比较运算

支持的比较运算:>, <, >= and <= ,但是>, <不能直接使用,因为xml会解析为标签,要使用别名。

注意 == and !=不仅可以比较数值,类似于equals的功能。

可以使用的别名:gt (>), lt (<), ge (>=), le (<=), not (!). Also eq (==), neq/ne (!=).

条件运算

三元运算


默认值

有的时候,我们取一个值可能为空,这个时候需要做非空判断,可以使用 表达式 ?: 默认值简写:


当前面的表达式值为null时,就会使用后面的默认值。

注意:?:之间没有空格。

循环
循环也是非常频繁使用的需求,我们使用th:each指令来完成:

假如有用户的集合:users在Context中。

Onions 2.41 ${users} 是要遍历的集合,可以是以下类型:

Iterable,实现了Iterable接口的类

Enumeration,枚举

Interator,迭代器

Map,遍历得到的是Map.Entry

Array,数组及其它一切符合数组结果的对象

在迭代的同时,我们也可以获取迭代的状态对象:

Onions 2.41 stat对象包含以下属性:

index,从0开始的角标

count,元素的个数,从1开始

size,总元素个数

current,当前遍历到的元素

even/odd,返回是否为奇偶,boolean值

first/last,返回是否为第一或最后,boolean值

逻辑判断
有了if和else,我们能实现一切功能_

Thymeleaf中使用th:if 或者 th:unless ,两者的意思恰好相反。

老油条
如果表达式的值为true,则标签会渲染到页面,否则不进行渲染。

以下情况被认定为true:

表达式值为true

表达式值为非0数值

表达式值为非0字符

表达式值为字符串,但不是"false",“no”,“off”

表达式不是布尔、字符串、数字、字符中的任何一种

其它情况包括null都被认定为false

分支控制switch
这里要使用两个指令:th:switch 和 th:case

用户是管理员

用户是经理

用户是别的玩意

需要注意的是,一旦有一个th:case成立,其它的则不再判断。与java中的switch是一样的。

另外th:case="*"表示默认,放最后。

JS模板
模板引擎不仅可以渲染html,也可以对JS中的进行预处理。而且为了在纯静态环境下可以运行,其Thymeleaf代码可以被注释起来:

在script标签中通过th:inline="javascript"来声明这是要特殊处理的js脚本

语法结构:

const user = /[[Thymeleaf表达式]]/ “静态环境下的默认值”;
因为Thymeleaf被注释起来,因此即便是静态环境下, js代码也不会报错,而是采用表达式后面跟着的默认值。且User对象会被直接处理为json格式。

https://page.om.qq.com/page/OwDfdkHuO8_3mbMUM_8GBM1w0

SpringMVC 面试题
什么是Spring MVC ?简单介绍下你对springMVC的理解?
Spring MVC是一个基于MVC架构的用来简化web应用程序开发的应用开发框架,它是Spring的一个模块,无需中间整合层来整合 ,它和Struts2一样都属于表现层的框架。在web模型中,MVC是一种很流行的框架,通过把Model,View,Controller分离,把较为复杂的web应用分成逻辑清晰的几部分,简化开发,减少出错,方便组内开发人员之间的配合。

SpringMVC的流程?
1554179581152
(1)用户发送请求至前端控制器DispatcherServlet;
(2) DispatcherServlet收到请求后,调用HandlerMapping处理器映射器,请求获取Handle;
(3)处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet;
(4)DispatcherServlet通过HandlerAdapter处理器适配器调用处理器;
(5)执行处理器(Handler,也叫后端控制器);
(6)Handler执行完成返回ModelAndView;
(7)HandlerAdapter将Handler执行结果ModelAndView返回给DispatcherServlet;
(8)DispatcherServlet将ModelAndView传给ViewReslover视图解析器进行解析;
(9)ViewReslover解析后返回具体View;
(10)DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)
(11)DispatcherServlet响应用户。
果 相当于转发器,有了DispatcherServlet 就减少了其它组件之间的耦合度。

Springmvc的优点:
如下:
(1)它是基于组件技术的。全部的应用对象,无论控制器和视图,还是业务对象之类的都是 java组件.并且和Spring提供的其他基础结构紧密集成
(2)不依赖于Servlet API(目标虽是如此,但是在实现的时候确实是依赖于Servlet的)
(3)可以任意使用各种视图技术,而不仅仅局限于JSP
(4) 支持各种请求资源的映射策略
(5)它应是易于扩展的

Spring MVC的主要组键?
六个主要组件:
(1)前端控制器 DispatcherServlet(不需要程序员开发)
作用:接收请求、响应结果 相当于转发器,有了DispatcherServlet 就减少了其它组件之间的耦合度。
(2)处理器映射器HandlerMapping(不需要程序员开发)
作用:根据请求的URL来查找Handler
(3)处理器适配器HandlerAdapter
注意:在编写Handler的时候要按照HandlerAdapter要求的规则去编写,这样适配器HandlerAdapter才可以正确的去执行Handler。
(4)处理器Handler(需要程序员开发)
(5)视图解析器 ViewResolver(不需要程序员开发)
作用:进行视图的解析 根据视图逻辑名解析成真正的视图(view)
(6)视图View(需要程序员开发jsp)
View是一个接口, 它的实现类支持不同的视图类型(jsp,freemarker,pdf等等)

springMVC和struts2的区别有哪些?
区别:
(1)springmvc的入口是一个servlet即前端控制器(DispatchServlet),而struts2入口是一个filter过虑器(StrutsPrepareAndExecuteFilter)。
(2)springmvc是基于方法开发(一个url对应一个方法),请求参数传递到方法的形参,可以设计为单例或多例(建议单例),struts2是基于类开发,传递参数是通过类的属性,只能设计为多例。
(3)Struts采用值栈存储请求和响应的数据,通过OGNL存取数据,springmvc通过参数解析器是将request请求内容解析,并给方法形参赋值,将数据和视图封装成ModelAndView对象,最后又将ModelAndView中的模型数据通过reques域传输到页面。Jsp视图解析器默认使用jstl。

SpringMVC怎么样设定重定向和转发的?
举例:
(1)在返回值前面加"forward:“就可以让结果转发,譬如"forward:user.do?name=method4”
(2)在返回值前面加"redirect:“就可以让返回值重定向,譬如"redirect:http://www.baidu.com”

SpringMvc怎么和AJAX相互调用的?
通过Jackson框架就可以把Java里面的对象直接转化成Js可以识别的Json对象。具体步骤如下 :
(1)加入Jackson.jar
(2)在配置文件中配置json的映射
(3)在接受Ajax方法里面可以直接返回Object,List等,但方法前面要加上@ResponseBody注解。

SpringMvc里面拦截器是怎么写的:
有两种写法,一种是实现HandlerInterceptor接口,另外一种是继承适配器类,,接着在接口方法当中,实现处理逻辑;然后在SpringMvc的配置文件中配置拦截器即可:

mvc:interceptors



mvc:interceptor
<mvc:mapping path="/modelMap.do" />

</mvc:interceptor>
</mvc:interceptors>
copy
如何解决POST请求中文乱码问题,GET的又如何处理呢?
(1)解决post请求乱码问题:
在web.xml中加入:

CharacterEncodingFilter org.springframework.web.filter.CharacterEncodingFilter encoding utf-8 CharacterEncodingFilter /* copy (2)get请求中文参数出现乱码解决方法有两个:

①修改tomcat配置文件添加编码 URIEncoding="utf-8"与工程编码一致,如下:

copy ②另外一种方法对参数进行重新编码:ISO8859-1是tomcat默认编码,需要将tomcat编码后的内容按utf-8编码。

String userName = new String(request.getParamter(“userName”).getBytes(“ISO8859-1”),“utf-8”)
copy
Spring MVC的异常处理 ?
答:可以将异常抛给Spring框架,由Spring框架来处理;我们只需要配置简单的异常处理器,在异常处理器中添视图页面即可。

SpringMvc的核心入口类是什么,Struts1,Struts2的分别是什么:
答:SpringMvc的是DispatchServlet,Struts1的是ActionServlet,Struts2的是StrutsPrepareAndExecuteFilter。

SpringMvc的控制器是不是单例模式,如果是,有什么问题,怎么解决?
答:是单例模式,所以在多线程访问的时候有线程安全问题,不要用同步,会影响性能的,解决方案是在控制器里面不能写字段。

SpingMvc中的控制器的注解一般用那个,有没有别的注解可以替代?
答:一般用@Conntroller注解,表示是表现层,不能用用别的注解代替。

@RequestMapping注解用在类上面有什么作用?
答:是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。

怎么样把某个请求映射到特定的方法上面?
答:直接在方法上面加上注解@RequestMapping,并且在这个注解里面写上要拦截的路径。

如果在拦截请求中,我想拦截get方式提交的方法,怎么配置?
答:可以在@RequestMapping注解里面加上method=RequestMethod.GET。

怎么样在方法里面得到Request,或者Session?
答:直接在方法的形参中声明request,SpringMvc就自动把request对象传入。

如果想在拦截的方法里面得到从前台传入的参数,怎么得到?
答:直接在形参里面声明这个参数就可以,但必须名字和传过来的参数一样。

如果前台有很多个参数传入,并且这些参数都是一个对象的,那么怎么样快速得到这个对象?
答:直接在方法中声明这个对象,SpringMvc就自动会把属性赋值到这个对象里面。

SpringMvc中函数的返回值是什么?
答:返回值可以有很多类型,有String, ModelAndView,但一般用String比较好。

SpringMvc用什么对象从后台向前台传递数据的?
答:通过ModelMap对象,可以在这个对象里面用put方法,把对象加到里面,前台就可以通过el表达式拿到。

SpringMvc中有个类把视图和数据都合并的一起的,叫什么?
答:ModelAndView。

怎么样把ModelMap里面的数据放入Session里面?
答:可以在类上面加上@SessionAttributes注解,里面包含的字符串就是要放入session里面的key。

当一个方法向AJAX返回特殊对象,譬如Object,List等,需要做什么处理?
答:要加上@ResponseBody注解。

事务,是为了保障逻辑处理的原子性、一致性、隔离性、永久性。
通过事务控制,可以避免因为逻辑处理失败而导致产生脏数据等等一系列的问题。

传播行为7中:
PROPAGATION_REQUIRED:有则使用,无则新建
PROPAGATION_SUPPORTS:有则使用,无则不用
PROPAGATION_MANDATORY:强制事务
PROPAGATION_REQUIRES_NEW:每次都创建一个新事务
PROPAGATION_NOT_SUPPORTED:不支持事务
PROPAGATION_NEVER:不能出现事务
PROPAGATION_NESTED:嵌套事务
事务隔离级别:
Read Uncommited
Read Commited
Repeatable Read
Serializable

@SpringBootApplication
@EnableAutoConfiguration
@Configuration
@ComponentScan
@Service
@RestController
@ResponseBody
@AutoWired
@RequestMapping

redis 分布式锁原理一
过程分析:

A尝试去获取锁lockkey,通过setnx(lockkey,currenttime+timeout)命令,对lockkey进行setnx,将value值设置为当前时间+锁超时时间;
如果返回值为1,说明redis服务器中还没有lockkey,也就是没有其他用户拥有这个锁,A就能获取锁成功;
在进行相关业务执行之前,先执行expire(lockkey),对lockkey设置有效期,防止死锁。因为如果不设置有效期的话,lockkey将一直存在于redis中,其他用户尝试获取锁时,执行到setnx(lockkey,currenttime+timeout)时,将不能成功获取到该锁;
执行相关业务;
释放锁,A完成相关业务之后,要释放拥有的锁,也就是删除redis中该锁的内容,del(lockkey),接下来的用户才能进行重新设置锁新值。

1、为什么使用线程池,线程池有什么作用?
  线程池,就是一个池子,存放指定数量的线程来执行任务,处理完任务的线程不进行回收,而是阻塞等待下一个任务,避免了频繁的创建和销毁线程,达到了线程的重用。
2、如何创建一个线程池?
  最常用的,使用ThreadPoolExecutor实现类来创建线程池
3、如何关闭一个线程池?
  ExecutorService提供了两种方法来关闭线程池,shutdown()和shutdownNow()
  (1) shutdown:拒收新的任务,立马关闭正在执行的任务,可能会引起报错,需要异常捕获
(2) shutdownNow:拒收新的任务,等待任务执行完毕,要确保任务里不会有永久等待阻塞的逻辑,否则会导致线程关闭不了 
不是马上关闭,要想等待线程池关闭,还需要调用waitFermination来阻塞等待
4、submit()和execute()方法的区别?
  execute()方法在Executor()接口中,且是接口中唯一的方法
  submit()方法在ExecutorService中,ExecutorService接口继承Executor 接口
  execute()方法,开启线程执行池中的任务
  submit()方法,也可以做到execute()的作用,它还可以返回执行结果,它的 功能是提交指定的任务去执行并且返回Future对象(即执行的结果)
  submit()和execute()的区别:
  (1) 接收的参数不一样
  (2) submit()方法有返回值Future,而execute()方法没有返回值
  (3) submit()方法方便处理Exception异常,意思就是,你在task里会抛出checked或者unchecked exception, 而又希望外面的调用者能够感知这些exception并作出及时的处理,  用 submit,通过捕获Future.get抛出的异常

总结:Executors中FixedThreadPool指定使用无界队列LinkedBlockingQueue会导致内存溢出,所以,最好使用ThreadPoolExecutor自定义线程池

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值