java
熟悉SpringBoot,SpringMvc MyBatis等主流框架
答:springboot简化新应用的初始搭建以及开发过程,该框架使用了特定的方式来
进行配置,从而不再需要定义样板化的配置
Spring Boot特点
1,创建独立的Spring应用程序
2,嵌入的Tomcat,无需部署WAR文件
3,简化Maven配置
4,自动配置Spring
5,提供生产就绪型功能,如指标,健康检查和外部配置
6,绝对没有代码生成和对xml没有配置要求
使用Redis
java使用Redis,首先要下载java redis 驱动jedis的驱动包,
然后在代码中使用Jedis jedis=new Jedis()
java String实例 jedis.set("key","value")
相关命令 :set key value
get key
incr key 键值自增
decr key 键值自减
list(列表)实例 jedis.lpush("列表名","a")
List
redis列表是简单的字符串列表,可以说是一个链表或者说是一个队列
redis集合set是Stirng类型的无序集合,不能出现重复数据
zset(有序集合)实例
数据堂:
熟悉Mybatis,SpringMVC,熟悉redis
J2EE架构设计,了解三层结构,熟悉SOA体系
架构的演变过程由单一的应用架构到垂直的应用架构,再到分布式rpc架构,再到soa流动计算架构
https://blog.csdn.net/aglne/article/details/70210774
rpc--远程过程调用协议,通过网络从远程计算机上请求服务,跨越了传输层和应用层
网络七层协议:从下往上为物理层,数据链路层,网络层,传输层,会话层,表示层和应用层
HTTP协议对应于应用层,主要解决如何包装数据
TCP协议对应于传输层,主要解决数据如何在网络中传输
IP协议对应于网络层
socket是应用层与tcp/ip协议族通信的中间软件抽象层,是它的一组接口
连接的三者本质上没有可比性
三层架构:视图层 服务层 数据层
soa体系:面向服务的架构
有多线程,网络编程经验
答:https://www.cnblogs.com/wxd0108/p/5479442.html
进程:就是一段程序的执行过程
线程:一个进程中可以包含若干个线程
多线程:在一个程序中,这些独立运行的程序偏大叫作线程,多线程是为了同步完成多项任务,
不是为了提高运行效率
多线程:指的是这个程序(一个进程)运行时产生了不止一个线程
并行与并发:
并行:多个cpu实例或者多台机器同时执行一段处理逻辑,是真正的同时。
并发:通过cpu调度算法,让用户看上去同时执行,实际上从cpu操作层面不是真正的同时。
并发往往在场景中有公用的资源,那么针对这个公用的资源往往产生瓶颈,我们会用TPS或者QPS来反应这个系统的处理能力。
线程安全:经常用来描绘一段代码。指在并发的情况之下,该代码经过多线程使用
,线程的调度顺序不影响任何结果。这个时候使用多线程,我们只需要关注系统的内存,cpu是不是够用即可。
反过来,线程不安全就意味着线程的调度顺序会影响最终结果,
同步:Java中的同步指的是通过人为的控制和调度,保证共享资源的多线程访问成为线程安全,来保证结果的准确。
在保证结果准确的同时,提高性能,才是优秀的程序。线程安全的优先级高于性能
熟悉Mysql,Mongo数据库编程以及连接池管理
答:熟悉
熟悉JSP,HTML,JS,CSS,AJAX,XML等前端技术
答:熟悉
熟悉Linux/Unix操作系统,熟练使用tomcat,apache应用服务器
答熟悉
有分布式,高并发系统开发经验值优先
面试
焦点科技 :
问题:
为什么要离职,数据结构hash,设计模式工厂模式优点,多线程,毕业四年内要把java基础搞清楚,(有的公司要求Java基础多,有的要求技术花哨,起码两样都能说一些)
把工厂模式那段代码看看,真实业务配上花哨技术,缓存的实时性,hashmap底层
面试后解答:
现在已经离职了,离职原因:个人职业规划问题(不能说加班时间没事做,那属于工作不饱和,,既然有空闲时间为什么不看java基础)
忠诚度:就说在寻找新机会或新的挑战,我们经理也跟我聊了两次天,我也有点不舍
责任感:现在项目版本迭代刚结束所以这个时候离职,而且离职要花2周进行工作交接,
而现在希望到贵公司承担新的责任,做新的项目拓展视野挑战提升实力
HashMap底层:
答:首先谈一下数据结构:
数组和链表,数组查询快(有索引),增删慢(增删时需要改变其他数据的索引)
而链表(如LinkedHashSet底层)增删快(只需要知道它的前面的和后面的就可以了)查询慢(需要从一个数据分别往前后查)
而hash表是一种寻址容易,增删也容易的数据结构,哈希表其实就是链表的数组,哈希表是由链表加数组组成的,一个长度为n的数组,每个元素存储的是一个链表的头节点,这些元素按照元素的key模上(%)数组长度n得到的值作为在数组中的下标;
所以HashMap是由链表加数组+红黑树组成的,数组是hashmap的主体,链表则是主要为了解决哈希冲突而存在的,如果定位到的数组位置不含链表(当前entry的next指向null),那么对于查找,添加等操作很快,仅需一次寻址即可;如果定位到的位置含链表查询慢,增删快对于添加操作,最新的Entry会加入链表的头部,在jdk1.8中如果哈希桶长度超过8,会将链表转换为红黑树https://blog.csdn.net/bjstyle/article/details/78221429
其实也是一个线性数组,是Entry数组,Entry是hashmap的基本组成单元,每个Entry包含一个key-value键值对;
问题:hashmap底层解决hash冲突的方法
链表+红黑树
设计模式:
工作中接触到了工厂模式
它的优点是什么:
redis查机票(缓存同步的方案),消息队列(财务发送报文),rsf类似于dubbo,下订单的多线程,行程单打印poi,
2018 年 :
思想很重要
*spring 的IOC对象由容器创建,容器是什么?
答:bean工厂
*hashmap的遍历方式
答:1)iterator iterator it =map.entrySet().iterator() while(it.hasNext()){}
3)for(String key : map.keySet())
4)for(Map.Entry
2)for(String v : map.values())
接口基于什么
*了解springboot微服务吗
2018年 升龙科技 :
jackson 接口
2018年7月4日 下午小黑鱼 面试官一副萎样 面试官说结束了你可以走了
*接口与抽象类的区别
答:抽象类中的方法可以有方法体,而接口不可以;
抽象类中的成员变量可以是各种类型的,而接口的成员变量只能是public static final;
(jdk1.8中
接口可以有静态方法,接口里的静态方法必须要有body,而且不需要实现)
一个类只能继承一个抽象类,而一个类可以实现多个接口
*excute线程池里有哪些线程
*avticemq的两种方式和区别
基础流程
在讨论具体方式的时候,我们先看看使用activemq需要启动服务的主要过程。
按照JMS的规范,我们首先需要获得一个JMS connection factory.,通过这个connection factory来创建connection.在这个基础之上我们再创建session, destination, producer和consumer。因此主要的几个步骤如下:
1. 获得JMS connection factory. 通过我们提供特定环境的连接信息来构造factory。
2. 利用factory构造JMS connection
3. 启动connection
4. 通过connection创建JMS session.
5. 指定JMS destination.
6. 创建JMS producer或者创建JMS message并提供destination.
7. 创建JMS consumer或注册JMS message listener.
8. 发送和接收JMS message.
9. 关闭所有JMS资源,包括connection, session, producer, consumer等。
1)发布订阅 (一对多) 发布订阅模式有点类似于我们日常生活中订阅报纸。每年到年尾的时候,邮局就会发一本报纸集合让我们来选择订阅哪一个。在这个表里头列了所有出版发行的报纸,那么对于我们每一个订阅者来说,我们可以选择一份或者多份报纸。比如北京日报、潇湘晨报等。那么这些个我们订阅的报纸,就相当于发布订阅模式里的topic。有很多个人订阅报纸,也有人可能和我订阅了相同的报纸。那么,在这里,相当于我们在同一个topic里注册了。对于一份报纸发行方来说,它和所有的订阅者就构成了一个1对多的关系
2)点对点 (一对一) p2p的过程则理解起来更加简单。它好比是两个人打电话,这两个人是独享这一条通信链路的。一方发送消息,另外一方接收,就这么简单。在实际应用中因为有多个用户对使用p2p的链路
*redis的数据结构
string hash set sortset(zset) list
6379 :redis的默认端口号
*过滤器与拦截器的区别及执行顺序\监听器
答:
springMVC架构:
过滤器的运行依赖于servlet容器,跟框架没关系,跟web.xml中的定义顺序有关
拦截器它们之间的执行顺序跟在SpringMVC的配置文件中定义的先后顺序有关
*springmvc自定义注解
*多线程
2018 年 中软科技 :
cookie和session区别
*1 Cookie是由服务端创建的,通过HttpServletResponse对象的
addCookie(cookie)方法写回客户端,存储在浏览器内存中
2cookie分回话级别的cookie:存储在浏览器的内存中
持久化的cookie:设置了path属性和maxAge属性的cookie称之为持久化的cookie
3 cookie的属性:
name:Cookie名称
value:Cookie的值
path:属性,一般在设置Cookie有效期的时候,配合maxAge属性一起使用或者和domain属性一起做cookie跨域处理
domain:域属性,一般Cookie跨域的时候使用
maxAge属性:单位秒,设置持久化Cookie的必备属性
4 Cookie的API setName()
5 删除Cookie
1)同名Cookie覆盖 Cookie cookie =new Cookie("abc",null)
2)设置Cookie的时间maxAge属性(0,>0)
注意:每一次请求,只要是同一个网站的Cookie,他们path(满足规则)就会携带这个cookie去服务端
*Session是服务端的一个会话技术,
session是基于cookie的,创建完session后会向客户端写一个cookie,这个cookie的名字叫jessionid,值就是session的id属性值,session一旦被创建他就会被赋予一个唯一的id属性值
注意:Session创建的时候首先看cookie当中有没有JESSONID的这个Cookie,如果有取出它的值,和服务端的这些Session的id属性比较,如果有相同的就直接返回该session不再另行创建
2018 年 秦苍科技:
1,final修饰方法不能被重写 final void method(){}
2,break语句只中断当前循环语句
3,***抽象类***
抽象类不能被实例化,只有他的子类能创建对象
抽象类中不一定有抽象方法,
含抽象方法的一定是抽象类
抽象方法一定在抽象类中
4,*String**StringBuffer**StringBuilder* 区别
1)运行速度:
StringBuilder>StringBuffer>String
String为字符串常量,而StringBuilder和StringBuffer均为字符串变量
String创建的对象不可修改,即使拼接其他字符串,也是jvm新创建的对象,原来的对象没变被回收了; 而StringBuilder和StringBuffer的对象是变量,对变量进行操作就是直接对该对象进行更改,而不进行创建和回收的操作,所以速度要比String快很多。
2)线程安全
String 字符串常量
StringBuffer 字符串变量 线程安全的可变字符序列
StringBuilder 字符串变量 线程不安全
3)StringBuffer与StringBuilder
两者比较使用后者,因为StringBuilder单线程方面比strngbuffer性能好
StringBuilder是在StringBuffer后面出来的
4)1.如果要操作少量的数据用String
2.单线程操作字符串缓冲区 下操作大量数据用StringBuilder
3.多线程操作字符串缓冲区 下操作大量数据用StringBuffer
5 *HashMap*,*HashTable*区别,及hasmap原理及hashmap遍历
1:HashTable是线程安全的,HashMap是非线程安全的;
因为hashtable底层对方法使用了同步修饰符synchronized,所以说hashtable是同步的,hashmap不是
2:HashMap的键和值都允许有null值存在,而HashTable则不行.
3: 因为线程安全的问题,HashMap效率比HashTable的要高.
4:hashtabk产生jdk1.1,hashmap产生于jdk1.2-
5:hashmap允许null键,null值,而hashtabl遇到null报空指针异常
因为源码中对null进行了处理,将null的hashCode值定为了0,从而将其存放在哈希表的第0个bucket中
hashmap的原理(数据结构)
底层是哈希表是链表组成的数组,链表的key值模上数组长度决定了它在数组中的位置
hashmap底层是哈希表,是entry对像(每个entry对象表示存储到哈希表中的键值对)的数组组成的,
对于映射到同一哈希桶(数组的位置),使用Entry链表来存储(解决hash冲突)
0 null
1 key&value-key&value
hashmap的遍历方式
答:1)iterator iterator it =map.entrySet().iterator() while(it.hasNext()){}
2)for(String key : map.keySet())
3)for(Map.Entry
4)for(String v : map.values())
6,长度
String []list={"ma","cao","yuan"};
String a="macaoyuan";
System.out.println(list.length);
System.out.println(a.length());
List
array.add(a);
System.out.println(array.size());
数组的长度 a.length;
字符串的长度 a.length()
集合的长度 array.size()
7 数组初始化
*特殊初始化 int [] a={1 ,2 ,3}
注意:特殊初始化,不用new关键字完成,在数组声明的同时完成初始化操作,也称为静态初始化,
数组的存储空间是由编译器完成的
* int [] b =new int [4]
注意:如果数组元素为基本数据类型,在完成new操作后,数组中的元素会自动初始化为空值,
但如果数组元素为引用数据类型,完成new操作后没有赋值就使用的话会报错
*int [] c= new int[]{1,2,3}
*二维数组初始化
//第一种方式:
int a[][]={{1,2,3},{4,5,6}};
//第二种方式;
int[][] ints = new int[4][2];
可以看成是3行1列的数组
ints[i][j] =__; //分别赋值
//第三种方式:第二维的长度可以动态申请
int[][] arr3 = new int[5][];//五行的长度
for(int i=0; i arr3[i]=new int[i+1]; //列的长度每次都变化。每次都要重新申请空间(长度) for(int j=0; j arr3[i][j]= i+j; } 8 sprin的IOC和AOP Spring的核心机制 1)管理Bean 程序主要是通过Spring容器来访问容器中的Bean,ApplicationContext是Spring容器最常用的接口,该接口有如下两个实现类: ClassPathXmlApplicationContext: 从类加载路径下搜索配置文件,并根据配置文件来创建Spring容器。 FileSystemXmlApplicationContext: 从文件系统的相对路径或绝对路径下去搜索配置文件,并根据配置文件来创建Spring容器。 2)ioc 不管是依赖注入,还是控制反转,其含义完全相同 调用者无需主动获取被依赖对象,调用者只要被动接受Spring容器为调用者的成员变量赋值即可 9 多线程 *加锁 synchronized *线程的常用方法 1.start() : 线程调用该方法将启动线程,使之从新建状态进入就绪队列排队,一旦轮到它来享用CPU资源时,就可以脱离创建它的线程独立开始自己的生命周期了。 2.run(): Thread类的run()方法与Runnable接口中的run()方法的功能和作用相同,都用来定义线程对象被调度之后所执行的操作,都是系统自动调用而用户程序不得引用的方法。 3.sleep(int millsecond): 优先级高的线程可以在它的run()方法中调用sleep方法来使自己放弃CPU资源,休眠一段时间。 4.isAlive(): 线程处于“新建”状态时,线程调用isAlive()方法返回false。在线程的run()方法结束之前,即没有进入死亡状态之前,线程调用isAlive()方法返回true. 5.currentThread():该方法是Thread类中的类方法,可以用类名调用,该方法返回当前正在使用CPU资源的线程。 6.interrupt() :一个占有CPU资源的线程可以让休眠的线程调用interrupt()方法“吵醒”自己,即导致休眠的线程发生InterruptedException异常,从而结束休眠,重新排队等待CPU资源。 *线程的创建 继承thread类,重写run方法 实现runable接口,重写run方法 通过 Callable 和 Future 创建线程 class RunnableDemo implements Runnable { private Thread t; private String threadName; RunnableDemo( String name) { threadName = name; System.out.println("Creating " + threadName ); } public void run() { System.out.println("Running " + threadName ); try { for(int i = 4; i > 0; i--) { System.out.println("Thread: " + threadName + ", " + i); // 让线程睡眠一会 Thread.sleep(50); } }catch (InterruptedException e) { System.out.println("Thread " + threadName + " interrupted."); } System.out.println("Thread " + threadName + " exiting."); } public void start () { System.out.println("Starting " + threadName ); if (t == null) { t = new Thread (this, threadName); t.start (); } } } public class TestThread { public static void main(String args[]) { RunnableDemo R1 = new RunnableDemo( "Thread-1"); R1.start(); RunnableDemo R2 = new RunnableDemo( "Thread-2"); R2.start(); } } 编译以上程序运行结果如下: Creating Thread-1 Starting Thread-1 Creating Thread-2 Starting Thread-2 Running Thread-1 Thread: Thread-1, 4 Running Thread-2 Thread: Thread-2, 4 Thread: Thread-1, 3 Thread: Thread-2, 3 Thread: Thread-1, 2 Thread: Thread-2, 2 Thread: Thread-1, 1 Thread: Thread-2, 1 Thread Thread-1 exiting. Thread Thread-2 exiting. 线程池,其实就是一个容纳多个线程的容器,其中的线程可以反复使用,省去了频繁创建线程对象的操作,无需反复创建线程而消耗过多资源 *sleep和waite区别 sleep()方法导致了程序暂停执行指定的时间,让出cpu该其他线程,但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。在调用sleep()方法的过程中,线程不会释放对象锁。而当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备获取对象锁进入运行状态。 10 设计模式 *工厂模式 工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象 优点: 1、一个调用者想创建一个对象,只要知道其名称就可以了。 2、扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。 3、屏蔽产品的具体实现,调用者只关心产品的接口。 缺点:每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。 public class ShapeFactory { //使用 getShape 方法获取形状类型的对象 public Shape getShape(String shapeType){ if(shapeType == null){ return null; } if(shapeType.equalsIgnoreCase("CIRCLE")){ return new Circle(); } else if(shapeType.equalsIgnoreCase("RECTANGLE")){ return new Rectangle(); } else if(shapeType.equalsIgnoreCase("SQUARE")){ return new Square(); } return null; } } *单例模式 目的:保证一个类仅有一个实例,并提供一个访问它的全局访问点 public class SingleObject{ //让构造函数为私有这样就不会被实例化 private SingleObject(){} //创建一个私有对象 private static SingleObject instance =new SingleObject(); public static SingleObject getInstance(){ return instance; } } 枚举(jdk1.5起) 这种实现方式还没有被广泛采用,但这是实现单例模式的最佳方法。它更简洁,自动支持序列化机制,绝对防止多次实例化。 public enum Singleton { INSTANCE; public void whateverMethod() { } } Singletom.INSTANCE就是一个对象了 public enum ProductTypeEnum { FLIGHT("0", "机票"),INSURANCE("1", "保险"),HOTEL("2", "酒店"); private final String code; private final String desc; ProductTypeEnum(String code, String desc) { this.code = code; this.desc = desc; } public String getCode() { return code; } public String getDesc() { return desc; } *建造者模式 将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。 去肯德基,汉堡、可乐、薯条、炸鸡翅等是不变的,而其组合是经常变化的,生成出所谓的"套餐" *观察者模式 一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。 关键代码:在抽象类里有一个 ArrayList 存放观察者们。 11 java面向对象的特征 1)抽象 ` Java中抽象类表示的是一种继承关系,一个类只能继承一个抽象类,而一个类却可以实现多个接口 1. 抽象类不能被实例化(初学者很容易犯的错),如果被实例化,就会报错,编译无法通过。只有抽象类的非抽象子类可以创建对象。 2. 抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。 3. 抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现也就是方法的具体功能。 4. 构造方法,类方法(用static修饰的方法)不能声明为抽象方法。 5. 抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。 2)封装 是指一种将抽象性函式接口的实现细节部分包装,隐藏起来的方法 防止类的代码和数据被外部类定义的代码随机访问 优点:良好的封装能够减少耦合 类内部的结构可以自由修改 可以对成员变量进行更精确的控制 隐藏信息,实现细节,加强了安全性 3)继承 继承就是子类继承父类的特征和行为 通过extends关键字 子类拥有父类非private的属性,方法,子类可以拥有自己的属性和方法,即子类可以对父类进行扩展 子类可以用自己的方式实现父类的方法 单继承,但是可以多重继承 维护性提高,提高代码复用性,但是代码耦合度高 $super和this的用法总结 *this this(参数)调用本类中另一种构造函数;当前对象;用this.成员变量与形参区分 *super super(参数)调用父类某一个构造函数;用super.xxx来引用当前对象父类的成员 $super()和this()必须写在构造方法第一行但是两者不能出现在一个构造函数内,因为使用this()必然会调用本类的另一种构造函数,而另一种构造函数第一行默认有父类super(),若再调用super()就会重复且编译不通过 $每个子类构造方法的第一条语句,都是隐含地调用super(),如果父类没有这种形式的构造函数,那么在编译的时候就会报错。 4)多态 多态就是一个行为的不同形态的表现 条件是存在继承关系,重写,父类引用指向子类对象 12 静态修饰符static 13讲解项目的内容和项目中的技术 2018年 摩卡软件: 好多前端题目: 盒子模型中,的块元素标签 选择器 子父类 sql3表查询 江苏和火 : *拦截器 过滤器 监听器区别 答:--监听器(Listener)就是一个类,监听request(请求域),session(会话域),application(应用程序) HttpSessionAttributeListener ServletRequestAttributeListener ServletContextAttributeListener这个接口监听application域对象中属性增删等事件,其他的各自对应 attributeAdded 方法 当向被监听对象中增加一个属性时,web容器就调用事件监听器的attributeAdded方法进行响应, attributeRemoved attributeReplaced 同理 1)public class MyServletContextAttributeListener implements ServletContextAttributeListener { @Override public void attributeAdded(ServletContextAttributeEvent scab) { String str =MessageFormat.format( "ServletContext域对象中添加了属性:{0},属性值是:{1}" ,scab.getName() ,scab.getValue()); System.out.println(str); } 2)在web.xml文件中注册监听器 3)测试 //往application域对象中添加属性 application.setAttribute("name", "名字"); --过滤器(filter)起到过滤请求的作用,作用在监听器后,servlet之前,对请求进行过滤 --servlet就是对request和response进行处理的容器 --拦截器(interceptor):就是对请求和返回进行拦截 *Jsp内置对象有哪几个 9大对象 9大内置对象 request 请求对象 类型javax.servlet.ServletRequest 作用域 Request reponse 响应对象 类型javax.servlet.ServletResponse 作用域page pageContext 页面上下文对象 类型javax.servlet.jsp.pageContext 作用域page session 会话对象 类型javax.servlet.http.HttpSession 作用域Session application应用程序对象 类型javax.servlet.ServletContext 作用域Application out 输出对象 类型javax javax.servlet.jsp.JspWriter 作用域Page config 配置对象 类型 javax.servlet.ServletConfig 作用域Page page 页面对象 类型 javax.lang.Object 作用域 Page exception 例外对象 类型 javax.lang.Throwable 作用域page 4大作用域 pageContext, request, session, application *SpringMvc获取参数的方式 https://www.cnblogs.com/xiaoxi/p/5695783.html 1)直接把表单参数写在controller形参,适用于get请求 @RequestMapping("/addUser1") public String addUser1(String username,String password) { System.out.println("username is:"+username); 2)使用注解@PathVariabl 接收url的参数 @RequestMapping(value="/addUser4/{username}/{password}",method=RequestMethod.GET) public String addUser4(@PathVariable String username,@PathVariable String password) { 3)用注解@RequestParam绑定请求参数到方法入参 @RequestMapping(value="/addUser6",method=RequestMethod.GET) public String addUser6(@RequestParam("username") String username,@RequestParam("password") String password) { System.out.println("username is:"+username); 4)通过HttpServletRequest接收,post和get都可以(request.getParam) @RequestMapping("/addUser2") public String addUser2(HttpServletRequest request) { String username=request.getParameter("username"); 5)通过一个bean(DTO)来接受,post和get都可以,请求的时候把值塞到bean里面,然后通过bean来接受 @RequestMapping("/addUser3") public String addUser3(UserModel user) { System.out.println("username is:"+user.getUsername()) 6)使用@ModelAttribute注解获取POST请求的FORM表单数据 @RequestMapping(value="/addUser5",method=RequestMethod.POST) public String addUser5(@ModelAttribute("user") UserModel user) { System.out.println("username is:"+user.getUsername()); * 诚迈科技: springMVC常用注解 spring ioc和aop的实际应用 mybatis原理 arrlist和hashmap原理 *sql注入 sql语句中使用#{},这样是经过预编译的是安全的,这样不管输入什么sql打印出来都是? 底层实现原理:在JDBC底层是PrepareStatement类在起作用,它的对象包含了编译好的sql语句,所以sql语句执行时就无需再编译 这样不仅安全还提高效率 sql删除重复订单号 mysql优化: 1)设置最大连接数 2)创建索引 ALTER TABLE 用来创建普通索引、唯一索引、主键索引和全文索引 ALTER TABLE table_name ADD INDEX index_name (column_list); CREATE INDEX可对表增加普通索引或UNIQUE索引以及全文索引,但是不可以对表增加主键索引 CREATE INDEX index_name ON table_name (column_list); 3) IO 使用 转换处理流OutputStreamWriter 可以将字节流转为字符流 New OutputStreamWriter(new FileOutputStream(File file)) 流一般需要不需要关闭,如果关闭的话在用什么方法,一般要在那个代码块里面关闭比较好,处理流是怎么关闭的,如果有多个流互相调用传入是怎么关闭的? 答案 流一旦打开就必须关闭,使用close方法 放入finally语句块中(finally 语句一定会执行) 调用的处理流就关闭处理流 多个流互相调用只关闭最外层的流 io流怎样读取文件的? Icon 使用File对象获取文件路径,通过字符流Reader加入文件,使用字符缓存流BufferedReader处理Reader,再定义一个字符串,循环遍历出文件。代码如下: File file = new File("d:/spring.txt"); try { Reader reader = new FileReader(file); BufferedReader buffered = new BufferedReader(reader); String data = null; while((data = buffered.readLine())!=null){ System.out.println(data); } 字符流复制文件 //创建字符输入流对象 FileReader fr = new FileReader("IODemo.java"); //创建字符输出流对象 FileWriter fw = new FileWriter("d:\\IODemo.java"); //一次读写一个字符 /*int ch; while((ch = fr.read()) != -1) { fw.write(ch); fw.flush(); }*/ //一次读写一个字符数组 int len;//用于存储读到的字符个数 char[] chs = new char[1024]; while((len = fr.read(chs)) != -1) { fw.write(chs,0,len); fw.flush(); } //释放资源 fw.close(); fr.close(); linux常用命令 pwd mkdir rmdir deleteEmptyFolder mv tar -czf tar -xvzf find ./ ! -name "*[0-9]*" | xargs grep --color '重新开/收票' grep '' ./ 卡夫卡与mq的区别 各个ssm框架深入的理解 控制台出来一下立即消失,说明Tomcat没有找到Java的运行时环境 Tomcat中webapps目录下不能直接存放网页格式的文件,否则无法访问到该文件,必须有子目录才能访问该网页文件 redis线程安全吗 redis和JRedis的线程安全 redis本身是单线程的,是线程安全的。 但是Jedis并不是线程安全的,可以通过JedisPool获取线程安全的Redis实例,通过JedisPool实例的方法: Jedis jedis = null; try { jedis = pool.getResource(); /// ... 执行相关的Redis操作 jedis.set("foo", "bar"); String foobar = jedis.get("foo"); jedis.zadd("sose", 0, "car"); jedis.zadd("sose", 0, "bike"); Set } finally { if (jedis != null) { jedis.close(); } } /// ... 当关闭应用程序时: pool.destroy(); *Linux上传文件和下载文件命令行方式 在Linux主机上,安装上传下载工具包rz及sz 只需要安装下面这个包即可,执行下面的安装命令 yum install -y lrzsz 上传: 在Linux命令行下输入rz, rz 下载: 在linux下输入命令 sz 文件名 从前台到后台用到的技术 zookeeper基本原理 https://blog.csdn.net/xinguan1267/article/details/38422149 springboot入门基础进阶 https://www.cnblogs.com/moonlightL/p/7891803.html Java 5,6,7,8,9,10新特性吐血总结 https://www.jianshu.com/p/952be1ff899f (getset)代码简化LOMBOK quartz和spring task定时任务 ehcahe restful风格:http请求:参数在url里面 bootstrap(栅格),ajax上传图片,ajax如何同步或异步改什么 springmvc spring ioc和aop(环绕通知)的实际应用 mybatis dubbo solr fastDFS freemark: 模板+数据模型=输出 ${}传输数据 选择freemark而不选择jsp的原因:实现了严格的mvc分离;处理订单金额大量判断上freemark性能较好一点 支持jsp标签;内置大量常用功能,日期金额格式化html过滤,遍历等等 常用 *import指令 <#import "/lib/common.ftl" as com> *include 指令 <#inclue "包含指定页面的路径"> *<#list planeType as list> #list> *<#if > <#elseif > #if> *<#switch > <#break> <#default> #switch> job tomcat调优: 1.把bio变成nio 2.调整tomcat线程池的大小 3.禁用Ajp协议 4.调整tomcat的JVM参数 Volatile关键字的底层实现原理 Thread和Runnable的区别和联系 string源码 *方法重载和重写的区别? 答:这是两个东西, 重载在一个类里面方法名相同,参数不同的两个方法 重写是在不同类里面的而且必须是集成关系,返回值类型和参数必须相同 &两边都要判断。 当使用&&(短路与)时,则相反,当前面的表达式结果为假时则不会再执行后面的表达式, protect同一个包内可用 *堆和栈的区别? 答:java中为了提高效率,就对数据进行了不同空间的分配,一下五个区域 (1)栈存储局部变量,局部变量有那些:在方法定义中或者在方法声明上定义的变量都称为局部变量 (2)堆存储new出来的东西, (3)方法区 (4)本地方法区(和系统相关) (5)寄存器(cpu使用) *equals比较两个对象内容是否相等,hashcode可以判断两个对象是否是同一对象 所以判断两个对象是否相等必须同时判断equals和hashcode是否相等 *.String能否被继承? 答:不能被继承,因为它是final,常量 *Collection和Collections区别 Collections是个java.util下的类,它包含有各种有关集合操作的静态方法。 Collection是个java.util下的接口,它是各种集合结构的父接口 *数据库两张表同步 *kafka和mq的区别 kafka原理:消息发送时都被发送到一个topic,其本质就是一个目录,而topic由是由一些Partition Logs(分区日志)组成 Kafka集群会保存所有的消息,不管消息有没有被消费;我们可以设定消息的过期时间 1.是否遵守JMS规范 MQ遵守了jms规范,kafka没有遵循jms规范。kafka利用文件系统来管理消息的生命周期 2. 吞吐量 kafka是顺序写磁盘,因此效率非常高。Kafka基于时间或者partition的大小来删除消息,同时broker是无状态的,consumer的消费状态(offset)是由consumer自己控制的(每一个consumer实例只会消费某一个或多个特定partition的数据,而某个partition的数据只会被某一个特定的consumer实例所消费),也不需要broker通过锁机制去控制消息的消费,所以吞吐量惊人,这也是Kafka吸引人的地方。 kafka支持高吞吐率,即使在非常廉价的商用机器上也能做到单机支持每秒100K条以上消息的传输。 MQ的吞吐量各有不同,但是跟kafka比,还是有一定差距。 3. 抗压性 kafka在大数据量下依然保持O(1)的方式提供消息持久化能力,即使对TB级以上数据也能保证常数时间复杂度的访问性能。而MQ则会出现性能下降。 4. 是否支持离线数据处理和实时数据处理 kafka同时支持离线数据处理和实时数据处理。 5. 扩展性比较 kafka支持在线水平扩展 6. 消息安全性 kafka可以保证在绝大多数情况下消息的安全性。当消息算作commit的时候才会暴露给consumer,并保证at-least-once的投递原则。 7. 可用性,稳定容错性 Kafka天然支持HA,leader挂了,follower自动选举出新的leader。 8. 2018年 途牛总部: mq原理,消息发送和消费方,多线程,static加在synorized上,synchronized关键字加到static静态方法上是给Class类上锁 而加到非static静态方法是给对象加锁( Java中每个对象都有一个锁,并且是唯一的,所以加到非静态的锁就是对象锁) *jdk1.8中HashMap的原理 在JDK1.6,JDK1.7中,HashMap采用位桶+链表实现,即使用链表处理冲突,同一hash值的链表都存储在一个链表里。但是当位于一个桶中的元素较多,即hash值相等的元素较多时,通过key值依次查找的效率较低。而JDK1.8中,HashMap采用位桶+链表+红黑树实现,当链表长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查找时间。 简单说下HashMap的实现原理: 首先有一个每个元素都是链表(可能表述不准确)的数组,当添加一个元素(key-value)时,就首先计算元素key的hash值,以此确定插入数组中的位置,但是可能存在同一hash值的元素已经被放在数组同一位置了,这时就添加到同一hash值的元素的后面,他们在数组的同一位置,但是形成了链表,同一各链表上的Hash值是相同的,所以说数组存放的是链表。而当链表长度太长时,链表就转换为红黑树,这样大大提高了查找的效率 *红黑树 1)每个节点是红色或者黑色 2)根节点是黑色 3)每个叶子节点是黑色(这里叶子节点是指为空或null的叶子节点) 4)如果一个节点是红色的,则它的子节点必须是黑色的 5)从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点 其特点就是给数的每一个节点加上了颜色属性,在插入的过程中通过颜色变换和节点旋转调平衡 *红黑树的优势 检索的时候通过平衡来二分查找 对于插入删除等操作效率提高很多 hashmap底层就是链表加上红黑树的一种结构,利用了链表对内存的使用率以及红黑树的高效检索 *二叉树 原理:二叉树是树的特殊一种,特点:1每个节点最多有两个子树,节点的度最大为2;左子树和右子树是有顺序的,次序不能颠倒;即使 某节点只有一个子树,也要区分左右子树 二叉树分为根节点,双亲节点,叶子节点,节点的度不能超多2,左子树小于右子树。 二叉树中存放数据的时候将比父节点大的数放在右节点,将比父节点小的数放在左节点 5 3 7 1 4 6 8 0 2 9 特点面试: 1)在二叉树的第i层最多有2的i-1次方个节点 2)二叉树深度为k(有k层),那么有2的k次方-1个节点 3)若二叉树按照从上到下从左到右依次编号,则若某节点编号为k,则其左右子树根节点编号分别为2k和2k+1; 4)二叉树分类:满二叉树,完全二叉树 满二叉树:高度为h,由2^h-1个节点构成的二叉树称为满二叉树。 *冒泡排序 不断和相邻的数值比较,每趟比较次数减少1,循环n次,大的数沉到右侧 *快速排序 优点:快速排序就是每次排序设置一个基准点,将小于基准点的全放基准点左边,大于基准点的全放基准点右边, 相比于冒泡排序每次只能在相邻的数之间交换,交换次数少距离大,所以速度快 快速排序的每一轮处理其实就是将这一轮的基准数归位 6 1 2 7 9 3 4 5 10 8 以6为基准数 i++ j-- j(即j--)先往左移动,找到一个6的数停下,接下来i(即i++)向右移动找到大于6的数,然后7 和5 就交换位置 6 1 2 5 9 3 4 7 10 8 然后j继续往左(每次必须j先出发) ,找到4,i往右找到了9,然后 9和4交换位置 6 1 2 5 4 3 9 7 10 8 然后j到达3,i也到达3,将基准数6和3交换,以6为基准数交换结束 3 1 2 5 4 6 9 7 10 8 3 1 2 5 4 分别处理 6 左边和6右边 9 7 10 8 左边的以3 为基准数 右边的以9为基准数 以此类推... http://developer.51cto.com/art/201403/430986.htm *activemq面试问题 1)是什么 消息中间件.可以在分布式系统的不同服务之间进行消息的发送和接收 2)解决了什么问题? 可以让系统解耦 3)性能比较 在服务端处理同步发送的性能上: Kafka>RocketMQ>RabbitMQ 4)大概介绍 1个标准:遵守JMS规范(java消息服务,java官方定义的技术规范) 定义了五种不同的消息: TextMessage 字符串 MapMessage 值对 ObjectMessage 序列化的java对象 ByteMessage 字节的数据流 StreamMessage 原始值的数据流 2个角色 Producer(生产者):发消息 Consumer(消费者):收消息 两种消息模式 一对一消息:queue消息,同时一个收 一对多消息:Topic消息,同时可以多个收 5)具体使用 *安装mq服务器 *配置connectionfactory,消息类型,Lmessageistener *具体使用 删除商品-->发送消息-->接收消息 商品状态更新-->发送消息-->接收消息 6)问题 *丢消息:心跳机制mq每隔10s会由服务端发送给客户端一个心跳包,用来判断客户端死没死.当非持久化消息堆积到一定程度发送阻塞,会关闭连接,客户端发出的消息会在缓存中等待处理,心跳机制收不到响应就报异常将缓存中的数据作废,没处理的消息就丢失了 解决方案:用持久化消息;或者启动事务,发生阻塞时,commit()方法会负责的等待服务器返回不会关闭连接 *消息的不均匀消费 开启多个消费者的时候,会发现一个消费者处理了所有消息,其他的消费者啥也不干,应为activemq的prefetch机制,默认一次获取一批1000条消息 解决方案:将prefetch设为1,每次处理一条消息,处理完再去取 *mysql常见问题(待补充) 1:数据库事务隔离级别 读未提交 :一个事务可以读另一未提交事务的数据,会造成脏读 读已提交 : 若有事务对数据进行更新操作,要等待更新操作完成后才能读取数据,可以解决脏读,会造成不可重复读问题 oracle的默认隔离级别 重复读 : 开始读取数据时,不再允许修改操作 mysql的默认事务隔离级别 会造成幻读 序列化 : 最高的事务隔离级别,事务串行化顺序执行,可以避免脏读、不可重复读与幻读。但是这种事务隔离级别效率低下,比较耗数据库性能,一般不使用 2:数据库事务的四大特性 *原子性:事务同生共死 *一致性:事务处理前后数据的状态要保持一致 *隔离性:不同事务之间不能互相干扰 *持久性:事务对数据的改变是永久性的 3 存储过程与触发器的区别 存储过程和触发器都是SQL语句集;触发器不可用CALL调用,而是在用户执行某些语句后自动调用; 4分表与分区 分表 真正的分表,每张表对应三个文件;提高MYSQL的并发能力; 分区 表中的数据分成多个区块;突破磁盘的读写能力; 5 索引的优缺点 优点 提高查询效率 缺点 降低了更新效率 6 存储过程 存储过程是一些预编译的SQL语句,执行效率较高 *set和 list区别 set 无序无索引不可重复 list 有序有索引可以重复 *kafka和mq的区别 kafka的消息安全性比mq高 kafka吞吐量比mq高 kafka效率高 kafka稳定性可靠性抗压 kafka支持离线数据和实时数据处理