1.1.排序:
快排:
选择排序:将第一个和后面每一个比较 最小的放前面。
public static void sort( int[] arr){
//外层循环的是轮数
for( int j=0; j
for ( int i =j+1; i< arr.length ; i++){
if( arr [j] < arr[i ]){
int temp =arr[j] ;
arr[j] =arr [i ] ;
arr[i] = temp;
}
}
}
}
package demo2;
public class Demo2 {
public static void main(String[] args) {
int[] arr = { 3, 2, 4, 8, 7, 1 };
sort1(arr);
sort2(arr);
}
// 冒泡排序
public static void sort2(int[] arr) {
int temp = 0;
for(int m=0;m
if (arr[i] < arr[i + 1]) {
temp = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = temp;
}
}
}
for (int m : arr) {
System.out.print(m + " “);
}
}
1.3.”=="和equals方法究竟有什么区别?
操作符专门用来比较两个变量的值是否相等,也就是用于比较变量所对应的内存中所存储的数值是否相同,要比较两个基本类型的数据或两个引用变量是否相等,只能用操作符。
equals方法是用于比较两个独立对象的内容是否相同,就好比去比较两个人的长相是否相同,它比较的两个对象是独立的。
字符串的比较基本上都是使用equals方法。
如果你编写的类希望能够比较该类创建的两个实例对象的内容是否相同,那么你必须覆盖equals方法,
string str=null不分配内存 ,空对象 。
string str= string.Empty;分配字节为0的内存,有指针指向
1.4.object中有哪些方法
protected Object clone() 创建并返回此对象的一个副本。
boolean equals(Object obj) 指示某个其他对象是否与此对象“相等”。
Class extendsObject> getClass() 返回一个对象的运行时类。
int hashCode() 返回该对象的哈希码值。
String toString() 返回该对象的字符串表示。
void notify() 唤醒在此对象监视器上等待的单个线程。
void notifyAll() 唤醒在此对象监视器上等待的所有线程。
void wait() 导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。
void wait(long timeout) 导致当前的线程等待,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量。
void wait(long timeout, int nanos) 导致当前的线程等待,直到其他线程调用此对象的 notify()
protected void finalize() 当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。
1.5.Integer与int的区别
int是java提供的8种原始数据类型之一。Java为每个原始类型提供了封装类,Integer是java为int提供的封装类。int的默认值为0,而Integer的默认值为null,即Integer可以区分出未赋值和值为0的区别
基本数据类型包括byte、int、char、long、float、double、boolean和short。
引用数据类型 :类 接口 数组
1.6.小算法
取出数组或者集合中重复元素及次数
可以先定义一个hashMap ,再遍历集合,定义一个计数器count=1。然后进行判断,若map.get(string)!=null .使count = hs.get(string) + 1。否则map.put(String,count)。即可得到一个map key是值,count就是对应的次数
HashMap
for (String string : l) {
Integer count = 1;
if(hs.get(string) != null) {
count = hs.get(string) + 1;
}
hs.put(string, count);
}
System.out.println(hs);
System.out.print(“重复的有:”);
for (String key : hs.keySet()) {
if (hs.get(key)!=null&hs.get(key)>1) {
System.out.print(key+" ");
}
}
去除两个List集合重复
List list=new ArrayList();
list.add(1); list.add(2); list.add(4); list.add(1); list.add(2); list.add(5);
List tempList= new ArrayList();
for(Integer i:list){
if(!tempList.contains(i)){
tempList.add(i);
}
}
for(Integer i:tempList){
System.out.println(i);
}
法二:
List listTemp= new ArrayList();
Iterator it=list.iterator();
while(it.hasNext()){
int a=it.next();
if(listTemp.contains(a)){
it.remove();
}
else{
listTemp.add(a);
}
}
法三:
HashSet h = new HashSet(list);
list.clear();
list.addAll(h);
return list;
两double类型数相除
/** * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指 * 定精度,以后的数字四舍五入 * * @param v1 被除数 * @param v2 除数 * @param scale 表示表示需要精确到小数点以后几位。 * @return 两个参数的商 /
public static double div(double v1, double v2, int scale) {
if (scale < 0) {
hrow new IllegalArgumentException(“The scale must be a positive integer or zero”);
}
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue(); }
编写一个程序,输入n,求n!(用递归的方式实现)。
publilc static long fac(int n){
if(n<=0) return 0;
if(n==1) return 1;
else return nfac(n-1);
}
public static void main(String[] args){
Syso(fac(6)
}
1.7.单例模式
Singleton模式主要作用是保证一个类在内存中的对象唯一性。
如何保证对象唯一性:
1.不允许其他程序用new创建该对象
2.在该类创建一个本类实例
3.对外提供一个方法让其他程序可以获取该对象
一般Singleton模式通常有几种种形式:
第一种形式:
public class Single {
private static Single instance =new Single(); //通过new在本类中创建一个本类对象
private Single() {} //私有化该类构造函数 注意这是private 只供内部调用
public static Single getInstance() { //定义一个共有的方法,将创建的对象返回
return instance;
}
}
第二种形式:
public class Singleton {
private static Singleton instance = null;
private Singleton() {}
public static synchronized Singleton getInstance() {
//这个方法比上面有所改进,不用每次都进行生成对象,只是第一次
//使用时生成实例,提高了效率!
if (instance==null)
instance=new Singleton();
return instance; }
}
其他形式:
定义一个类,它的构造函数为private的,所有方法为static的。
一般认为第一种形式要更加安全些
对于饿汉写法而言,它并不会出现线程安全问题,而对于懒汉写法在多线程的情况下就可能会造成线程安全问题,主要是因为在创建实例的时候,可能会创建出多个实例
Final :
final修饰的类不能被继承
修饰的方法不能被子类重写
修饰的变量是常量,只能赋值一次
成员变量 与静态变量 区别 :生命周期不同(随对象创建与随类加载创建) 调用方式不同
实例变量与类变量 存储位置(堆内存与方法区共享数据)
静态代码块;随着类的加载而执行,只执行一次作用:给类初始化
构造代码块;可以有所有对象进行初始化
构造函数:给对应的对象进行针对初始化。
构造函数执行后对象才算创建完成。
1.8.抽象类和接口区别:
相同点:都是不断向上抽取而来
不同点:抽象类需要被继承,只能单继承。 接口需要被实现,可以多实现。
抽象类 可以定义抽象和飞抽象 接口 只能定义抽象方法
抽象类的继承是 定义该体系的基本共性内容
接口的实现是 定义体系额外功能
1.9.Get 和post
get 将请求信息封装到了请求消息的请求行中,在地址栏可以看到数据 ,不安全,提交数据有量的限制(不超过1KB)。
post 将请求信息封装到了请求体中 ,在地址栏不能看到提交的数据 ,安全,提交数据理论上没限制
在服务端还有个区别:
如果出现将中文提交到tomcat服务器,服务器默认会用iso8859-1进行解码,会出现乱码,通过iso8859-1进行编码
再用指定的中文码表解码即可。 对于get和post提交都有效
同步和异步:
线程同步是指 多个线程同时访问同一资源,等待资源访问结束,浪费时间,效率低
异步是指 访问资源,在空闲等待时同时访问其他资源,实现多线程机制
线程:是程序执行流的最小单元,一个标准的线程有线程id,当前指令指针,寄存器集合和堆栈组成
有五种状态:新建状态,就绪状态,运行状态,阻塞状态,死亡状态
1.10. Apache Common 工具类
Dbutils:提供对jdbc的操作封装简化数据查询记录读取操作
Beanutils:提供对javabean进行各种操作,克隆对象,属性等
Collections: 集合框架的操作
DBCP:数据库连接池服务
FileUpload:文件上传
Email:对javamail封装
1.11.集合
原问题:java语言中集合与数组的区别?
1、数组特点高效、保存基本类型,集合带array的底层由数组实现,还有一部分由链表或者树
2、数组大小固定(巨大缺点,内存中一定连续),集合各种实现吧!
3、数组只能放一种类型,集合不考虑泛型可以存很多类型。
4、集合放原始类型其实是通过装箱拆箱来实现的,说白了以前原生类型只能用数组,现在集合也可以了。因为这个改进,所以现在基本上除了性能外,均推荐使用集合。
集合:Collection体系、Map体系。
Collection体系:单列集合的共性操作规则。
List:列表,可以重复,有下标,拥有特有的迭代器ListIterator。
ArrayList:底层是可变数组。增删慢,查询快。不安全
LinkedList:底层是链表结构,增删快,查询慢。不安全。有头和尾,特有的头尾操作的方法。可以模
拟数据结构(堆栈、队列)。
Vector:底层是可变数组,增删,查询都慢。安全。被ArrayList代替。
Enumeration:它是古老的迭代器,被Iterator代替。
Set:不能存放重复元素。
HashSet:底层是哈希表。不保证存取的顺序。保证对象唯一需要依赖对象的hashCode和equals方法。
因此给HashSet中存放的对象需要重写Object类中的hashCode和equals方法。
TreeSet:底层是二叉树结构。保证对象唯一和排序需要依赖对象的比较方法(compareTo),对象要具
备比较方法,需要实现Comparable接口。
如果对象具备的比较功能不适合需求,或者对象本身不具备比较功能,这时我们可以自己指定比较器对象(Comparator)。然后将这个对象传递给TreeSet集合。
LinkedHashSet:它是HashSet的子类,底层是哈希表和链表组合。它可以保证存取的顺序。
Map体系:双列集合的共性操作规则。存放的是具有一定对应关系的数据。key值是不能重复的。
HashMap:底层是哈希表,不保证存取顺序。主要作用在key上。key是自定义对象,需要复写hashCode
和equals方法。
TreeMap:底层是二叉树,作用在key上。key是自定义对象,需要实现Comparable接口,或者给集合
传递Comparator对象。
Hashtable:它底层是哈希表,安全。被HashMap代替。
LinkedHashMap:它是HashMap的子类,可以保证存取的顺序。底层链表和哈希表。
Map集合的遍历,不能直接使用Iterator,而需要将Map集合转成单列集合。
keySet方法,将Map中的所有key取出存放在Set集合中。遍历Set集合,得到每个key值,然后调用Map中的get方法,进而获取到key对应的value值。
entrySet方法。将Map中的key和value组成Entry对象(key和value对应关系对象)。存储在set中,遍历set集合,得到Entry对象,然后调用getKey和getValue方法得到key和value。
values方法:获取到的是Map中的所有value值,存放在Collection集合中。
1.11.1.HashTable , HashMap,TreeMap 区别
1.hashTable线程同步, hashMap非线程同步。
2.HashTable 不允许存在<键值> 为空值, HashMap允许<键值> 为空值
3.HashTable 使用Enumeration迭代器遍历, HashMap 使用Iterator
4.HashTable 数组的默认大小是11, 增加方式是old*2+1。 HashMap 中数组的默认大小是16,以2的指数倍增长。
1.12.IO
//一次读取多个字节数据
public static void method3() throws IOException {
//创建输入流对象和需要被读取的文件进行关联
FileInputStream fis = new FileInputStream(“d:/aa.txt”);
/*
* 定义数组充当临时的容器,存储每次从文件中读取到的若干个字节数据。
* 一般定义的数组如果是存储读取到的数据,这个数组一般会是1024的整数倍
/
byte[] buf = new byte[1024];
//定义变量,记录每次给数组中存储的字节个数
int len = 0;
//使用循环读取数据
while( ( len = fis.read( buf ) ) != -1 ){
/
for( int i = 0 ; i < len ; i++ ){
System.out.print(buf[i]+" ");
}
*/
System.out.println(new String( buf , 0 , len ));
}
//关流
fis.close();
}
//使用循环读取文件中的数据 ,一次读取一个
public static void method2() throws IOException {
//创建输入流对象和需要被读取的文件进行关联
FileInputStream fis = new FileInputStream("d:/aa.txt");
//定义变量记录每次读取到的字节数据
int ch = 0;
//使用while循环读取数据
while( ( ch = fis.read( ) ) != -1 ){
System.out.println(ch);
}
//关流
fis.close();
}
Java NIO提供了与标准IO不同的IO工作方式:
Channels and Buffers(通道和缓冲区):标准的IO基于字节流和字符流进行操作的,而NIO是基于通道(Channel)和缓冲区(Buffer)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。
Asynchronous IO(异步IO):Java NIO可以让你异步的使用IO,例如:当线程从通道读取数据到缓冲区时,线程还是可以进行其他事情。当数据被写入到缓冲区时,线程可以继续处理它。从缓冲区写入通道也类似。
Selectors(选择器):Java NIO引入了选择器的概念,选择器用于监听多个通道的事件(比如:连接打开,数据到达)。因此,单个的线程可以监听多个数据通道。
1.13.stringbuffer与stringbuild的实现机制?
StringBuffer:它是字符串的缓冲区容器,它中可以保存任何的数据,可以对其中的这些数据进行增 删 改 查 操作。
最后StringBuffer会把容器内数据转成字符串。而StringBuffer是一个安全的容器。 多线程
StringBuilder类是StringBuffer的等价类,只是StringBuilder它在单线程操作的时候,效率比StringBuffer高。单线程 。
StringBufferd支持并发操作,线性安全的,适合多线程中使用。StringBuilder不支持并发操作,线性不安全的,不适合多线程中使用。新引入的StringBuilder类不是线程安全的,但其在单线程中的性能比StringBuffer高。
1.14.动态代理
使用反射技术,动态的获取到需要调用的方法。在调用方法之前,可以做各种数据验证操作。
ClassLoader loader, 获取到当前加载ProxyClass类的类加载器对象
Class>[] interfaces, 取到被代理类实现的所有接口
InvocationHandler h 拦截外界调用方法的。只要外界调用任何方法,都会导致invoke方法执行
)
1.16.Filter与interceptor区别:
Filter基于回调函数,我们需要实现的filter接口中doFilter方法就是回调函数,
而interceptor则基于java本身的反射机制,这是两者最本质的区别。
是aop思想的一种实现 前置后置拦截器
Filter对所有资源和请求进行拦截 配在xml范围大
Interceptor只能拦截请求
1.17.Forward&Redirect区别
重定向:是页面跳转,共产生两次请求,两次响应url地址显示第二次资源路径(对用户可见)302 +location
转发:只会发生一次请求一次响应,转发是服务器内部行为(对用户不可见)传输数据不会丢失
1.18.Servlet
1.是sun公司提供一门用于动态web资源资源的技术
2.基于Request-Response编程模型
tomcat web服务器创建 当服务器启动时 执行相应init方法 对servlet进行初始化
1.19.session与cookie的区别,两者如何获取值?
Cookie:主要用在保存客户端,其值在客户端与服务端之间传送,不安全,存储的数据量有限。保存的是字符串
Session:保存在服务端,每一个session在服务端有一个sessionID作一个标识。存储的数据量大,安全性高。占用服务端的内存资源。保存的是对象
1.19.1.Js中闭包
各种专业文献上的“闭包”(closure)定义非常抽象,很难看懂。我的理解是,闭包就是能够读取其他函数内部变量的函数。
由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成“定义在一个函数内部的函数”。
所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。
1.20.Jsp
九大内置对象
out(JspWriter):等同与response.getWriter(),用来向客户端发送文本数据;
config(ServletConfig):对应“真身”中的ServletConfig;
page(当前JSP的真身类型):当前JSP页面的“this”,即当前对象;
pageContext(PageContext):页面上下文对象,它是最后一个没讲的域对象;
exception(Throwable):只有在错误页面中可以使用这个对象;
request(HttpServletRequest):即HttpServletRequest类的对象;
response(HttpServletResponse):即HttpServletResponse类的对象;
application(ServletContext):即ServletContext类的对象;
session(HttpSession):即HttpSession类的对象,不是每个JSP页面中都可以使用,如果在某个JSP页面中设置<%@page session=”false”%>,说明这个页面不能使用session。
四大域
application:整个应用程序
session:整个会话(一个会话中只有一个用户)
request:一个请求链!
pageContext:一个jsp页面!
1.21.Jsp和Servlet的区别?
1.22.Json
介绍:JSON:它是一种数据的表示格式。只是这种格式的数据,可以直接被解析成JS对象。
主要用在前台和后台的数据交互过程中的数据传输的介质
1.23. 生命周期
在web学习中遇到声明周期相关的对象:
HttpSession:
创建的时间:在jsp或者servlet中第一次调用getSession()或者getSession(true) 创建
销毁时间:1、服务器不正常关闭时;2、session的有效时间到;3、调用的invalidate方法
Servlet:
创建时间:一般情况下是在某个客户端第一次访问这个Servlet程序的时候创建。特殊情况下,可以在web.xm文件中的注册Servlet的标签中配置seervlet的创建启动时间。
销毁时间:1、关闭服务器;2、Servlet所在的项目从服务器中被移除
过滤器的生命周期:
创建时间:服务器启动的时候,当服务器加载到当前这个项目之后,项目中配置的所有过滤器一次进行创建和初始化。
销毁::1、关闭服务器;2、所在的项目从服务器中被移除
反射:
反射中需要掌握
Class类的含义:代表任意一个class文件对象。
获取Class对象的三种方式:
使用getClass方法
使用.class属性
使用Class类中的forName方法
获取(反射)类中的成员:
反射成员变量 Field ,反射到的成员变量赋值,调用set方法,获取值调用get方法
反射成员方法 Method ,反射到的方法运行需要调用invoke方法
反射构造方法 Constructor 反射到的构造方法执行,就会创建出对象newInstance方法
动态代理:使用反射技术,动态的获取到需要调用的方法,然后再使用反射技术调用方法之前,作各种数据验证操作
1.24.谈谈jdbc?
1.Sun公司提供的一套连接数据库规范API,加载数据库驱动,连接数据源;
2.获取连接、创建statement对象,业务操作发送sql、关闭资源
3.好处,操作数据快,不足频繁关闭资源,代码冗余多;
4.弥补不足,hibernate、mybatis等框架
1.24.1.Statement和parparedStatement的区别?Sql注入?如何防止
1.parparedStatement支持预编译,Statement不支持
2.parparedStatement可防止sql注入,更加安全。Statement不行
3.parparedStatement支持动态设置参数,Statement不支持
Sql注入:通过sql语句的拼接达到无参数查询数据库。
1.25.Spring
spring 是基于IOC和aop的一套编程框架。IOC:即控制反转,通过引入工厂,将对象创建权利,交给工厂来创建管理。利用这种思想可以很好实现模块之间的解耦。 AOP称为面向切面编程,是一种编程思想,采取横向抽取机制,取代传统纵向继承体系重复性代码的编写方式。基于代理思想,对原目标对象,创建代理对象。在不修改原对象代码情况下,通过代理对象,调用增强功能的代码,从而对原有的业务方法进行增强。
Spring优点:
1.降低组件之间的耦合性,实现软件各层之间的解耦。
2.AOP的很好支持,方便面向切面编程。可提供众多服务,如事务管理,权限控制,日志记录等
3.对主流的框架提供了很好的集成支持,如Hibernate,Struts2,JPA等
Spring提供了JavaEE各层的解决方案,表现层:SpringMVC,持久层:JdbcTemplate、ORM框架整合,业务层:IoC、AOP、事务控制。
IOC : 控制反转 引入工厂(第三者), BeanFactory(实际上是一个接口),在程序中通常BeanFactory的子接口ApplicationContext。扩展国际化处理 事件传递,bean自动装配,各层context实现
DI:依赖注入,在Spring框架负责创建Bean对象时,动态的将依赖对象注入到Bean组件(简单的说,可以将另外一个bean对象动态的注入到另外一个bean中。
DI和IoC是同一件事情,都是将对象控制权交给第三方(Spring)管理,只是站在不同角度而已。
【面试题】 BeanFactory和FactoryBean的区别?
BeanFactory:是一个工厂(其实是构建了一个spring上下文的环境,容器),用来管理和获取很多Bean对象,
FactoryBean:是一个Bean生成工具,是用来获取一种类型对象的Bean,它是构造Bean实例的一种方式。
AOP (Aspect Oriented Programing) 称为:面向切面编程,它是一种编程思想。
AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码的编写方式(性能监视、事务管理、权限控制、缓存优化,日志记录等)。AOP的很好支持,方便面向切面编程
AOP 思想: 基于代理思想,对原来目标对象,创建代理对象,在不修改原对象代码情况下,通过代理对象,调用增强功能的代码,从而对原有业务方法进行增强 !
Spring AOP编程两种方式:springAOP使用纯java实现,传统SpringAOP 编程。
支持第三方 AOP框架(AspectJ),实现另一种 AOP编程:推荐
Aspect切面:增强代码 Advice和 切入点 Pointcut 的结合。哪些方法 怎样增强
Spring AOP是基于动态代理的,基于两种动态代理机制:JDK动态代理和CGLIB动态代理
Spring AOP 优先对接口进行代理 (使用Jdk动态代理)
如果目标对象没有实现任何接口,才会对类进行代理 (使用cglib动态代理)
AspectJ切面编程 确定目标(bean)—编写通知—配置切点切面
bean构造的方式?4种:默认构造器、静态工厂、实例工厂、工厂Bean接口
属性依赖注入的三种方式:
第一种:构造器参数注入
第二种:setter方法属性注入(setter方法的规范-JavaBean规范)
第三种:接口注入
Spring 框架规范中通过配置文件配置的方式,只支持构造器参数注入和setter方法属性注入,不支持接口注入 !
Bean的作用域
1.Bean的作用域可以通过Bean标签的scope属性进行设置,Bean的作用域包括:
默认情况下 scope=“singleton”,那么该Bean是单例,任何人获取该Bean实例的都为同一个实例;
scope=“prototype”,任何一个实例都是新的实例;
scope=“request”,在WEB应用程序中,每一个实例的作用域都为request范围;
scope=“session”,在WEB应用程序中,每一个实例的作用域都为session范围;
注意:在默认情况下,Bean实例在被Spring容器初始化的时候,就会被实例化,默认调用无参数的构造方法。在其它情况下,Bean将会在获取实例的时候才会被实例化。
2.Bean可以通过指定属性init-method指定初始化后执行的方法,以及通过指定属性destroy-method销毁时执行的方法。
语法:
事物管理
Spring事务管理高层抽象主要包括3个接口,Spring的事务主要是由他们共同完成的:
PlatformTransactionManager:事务管理器—主要用于平台相关事务的管理(提交,回滚,获取事物状态)
TransactionDefinition: 事务定义信息(隔离、传播、超时、只读)—通过配置如何进行事务管理。
TransactionStatus:事务具体运行状态—事务管理过程中,每个时间点事务的状态信息。
事务的传播行为PropagationBehavior:7种 3类
REQUIRED、REQUIRES_NEW、NESTED 区分
REQUIRED 一个事务(默认,推荐)
REQUIRES_NEW 两个事务
NESTED 一个事务,事务可以设置保存点,回滚到保存点 ,选择提交或者回滚
1.26.Mybaits
一级缓存和二级缓存
Mybatis的一级缓存的作用域是session,当opensession()后,如果执行相同的sql,mybatis不进行执行sql,而是从缓存中命中返回。没有命中则执行sql,从数据库中查询
Mybatis的二级缓存即查询缓存,它的作用域是一个mapper的namespace,即在同一个namespace中查询sql可以从缓存中获取数据。二级缓存是可以跨SqlSession的,不同session。
对象中的某个对象映射 association
集合的映射 一对多collection
resultMap和resultType区别
resultMap:指的是定义好了的id的,是定义好的resyltType的引用
查询语句中,resultMap属性指向属性的标签的id
resultMap 元素,它是 MyBatis 中最重要最强大的元素,它能提供级联查询,缓存等功能
使用resultType进行输出映射,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功。
如果查询出来的列名和pojo的属性名不一致,通过定义一个resultMap对列名和pojo属性名之间作一个映射关系。
resultType:适合使用返回值得数据类型是非自定义的,即jdk的提供的类型
resultMap:适合使用返回值是自定义实体类的情况
1.27. MVC原理
C代表Controller,负责用户界面和业务逻辑层的通信控制,一方面接收来自用户界面的输入,识别用户动作(如点击按钮等),调用相应Model中的方法,另一方面处理来自Model的事件和返回的执行结果,调用适当的View显示给用户,Controller主要由Servlet完成。
M代表Model,负责整个解决方案的业务逻辑实现,底层的数据库也由Model访问和操作;
V代表View,负责系统向用户的展示,主要由HTML及JSP等完成;
1.28.Struts2和springMVC的区别?
共同点:都是MVC框架;
1)核心不同,struts2入口(基于)是filter过滤器,核心思想是拦截器。springmvc入口是DispatcherServlet,是基于servlet的;
2)执行效率上,Struts2基于类的,多例;Springmvc基于方法基于servlet的,第一次创建的时候是基于类,创建类之后第二次就不创建,单例的;
3)Struts2功能比较强,有很多标签可以使用,预定义的拦截器,国际化,流程比较复杂,所以性能没有springmvc好;springmvc因为是单例的所以性能优于struts2。
4)Struts2是类级别,springMVC是方法级别的;
5)springMVC是spring的一部分,跟spring整合的话能更好些;
Struts2比springMVC出世早。
#{}与 的 区 别 : 1 、 {}的区别: 1、 的区别:1、字符串拼接,# 参数站位相当于jdbc中的? 只是表示站位,与参数的名字无关。
2、KaTeX parse error: Expected 'EOF', got '#' at position 12: 不能够防止sql注入,#̲可以防止sql注入的 3、可以替换sql语句任何一个内容,#只能替换参数
4、$如果操作字符串,需要在sql中使用单引号。 #不需要(不需要判断数据类型)
通常使用#。
选择获取参数的时候,首要选择的# 的方式(1、可以防止sql注入,2、可以不用考虑数据类型,简化书写,3、sql是参数的话的sql,预编译的sql,速度会块一些)
当#用不了的时候,去选择 例 如 , s q l 需 要 改 变 是 表 名 的 情 况 , 就 可 使 用 例如 ,sql需要改变是表名的情况,就可使用 例如,sql需要改变是表名的情况,就可使用的方式。
1.29.Springmvc
五种映射:
标准映射、ant风格的url映射、占位符映射(PathVariable)、限制请求方法映射、限定请求参数(requestParam)
1.30.Mybatis&Hibernate:区别
两者相同点
Hibernate与MyBatis都可以是通过SessionFactoryBuider由XML配置文件构建SessionFactory,然后由SessionFactory 生成Session,最后由Session来开启执行事务和SQL语句。其中SessionFactoryBuider,SessionFactory,Session的生命周期都是差不多的。
Hibernate和MyBatis都支持JDBC和JTA事务处理。
Mybatis优势
MyBatis可以进行更为细致的SQL优化,可以减少查询字段。
MyBatis容易掌握,而Hibernate门槛较高。
Hibernate优势
Hibernate的DAO层开发比MyBatis简单,Mybatis需要维护SQL和结果映射。
Hibernate对对象的维护和缓存要比MyBatis好,对增删改查的对象的维护要方便。
Hibernate数据库移植性很好,MyBatis的数据库移植性不好,不同的数据库需要写不同SQL。
Hibernate有更好的二级缓存机制,可以使用第三方缓存。MyBatis本身提供的缓存机制不佳。
Hibernate是轻量级JavaEE应用的持久层解决方案,是一个关系数据库ORM框架。
个人看来,涉及到大数据的系统使用Mybatis比较好,因为优化较方便。涉及到数据量不是很大且对优化没有那么高的要求的话使用hibernate进行开发。
Hibernate的抓取策略(查询优化)
类级别的抓取策略:针对查询对象本身的抓取策略。 两种:立即检索和延迟检索
关联属性级别的抓取策略:针对通过对象导航访问关联属性的抓取策略。
批量抓取策略。
Hibernate中提供了两个级别的缓存:
一级缓存 是session级别的缓存,它是属于事务范围的缓存,生命周期是session的生命周期, (一个线程 绑定一个Session, 对应一份一级缓存, 一级缓存无法实现多用户之间数据共享),它是hibernate的内置缓存,由hibernate管理的,一般情况下无需进行干预.
二级缓存 是sessionFactory 级别的缓存,它属于进程级别的缓存 (一个项目 只会对应一个SessionFactory对象, sessionFactory缓存数据 实现多用户之间共享 ),二级缓存是可插拔的。(解耦合思想)
一级缓存的快照是由Hibernate来维护的,用户可以更改一级缓存(PO对象的属性值),但无法手动更改快照!
快照的主要能力(作用)是:用来更新数据!当刷出缓存的时候,如果一级缓存和快照不一致,则更新数据库数据。
【能力扩展】快照可以用来更新数据,而且,可以用来更新部分数据。
缓存同步的顺序是:默认先放一级缓存,然后再从一级缓存同步到二级缓存。二级缓存的数据是可以来自于一级缓存的。
1.31.Spring 7大功能模块的作用
核心容器(Spring core)
核心容器提供spring框架的基本功能。Spring以bean的方式组织和管理Java应 用中的各个组件及其关系。Spring使用BeanFactory来产生和管理Bean,它是工厂模式的实现。BeanFactory使用控制反转 (IoC)模式将应用的配置和依赖性规范与实际的应用程序代码分开。BeanFactory使用依赖注入的方式提供给组件依赖。
Spring上下文(Spring context)
Spring上下文是一个配置文件,向Spring框架提供上下文信息。Spring上下文包括企业服务,如JNDI、EJB、电子邮件、国际化、校验和调度功能。
Spring面向切面编程(Spring AOP)
通过配置管理特性,Spring AOP 模块直接将面向方面的编程功能集成到了 Spring框架中。所以,可以很容易地使 Spring框架管理的任何对象支持 AOP。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖 EJB 组件,就可以将声明性事务管理集成到应用程序中。
Spring DAO模块
DAO模式主要目的是将持久层相关问题与一般的的业务规则和工作流隔离开来。Spring 中的DAO提供一致的方式访问数据库,不管采用何种持久化技术,Spring都提供一直的编程模型。Spring还对不同的持久层技术提供一致的DAO方式的异常层次结构。
Spring ORM模块
Spring 与所有的主要的ORM映射框架都集成的很好,包括hibernate、JDO实现、TopLink和IBatis SQL Map等。Spring为所有的这些框架提供了模板之类的辅助类,达成了一致的编程风格。
Spring Web模块
Web上下文模块建立在应用程序上下文模块之上,为基于Web的应用程序提供了上下文。Web层使用Web层框架,可选的,可以是Spring自己的MVC框架,或者提供的Web框架,如Struts、Webwork、tapestry和jsf。
Spring MVC框架(Spring WebMVC)
MVC框架是一个全功能的构建Web应用程序的MVC实现。通过策略接口,MVC框架变成为高度可配置的。Spring的MVC框架提供清晰的角色划分:控制器、验证器、命令对象、表单对象和模型对象、分发器、处理器映射和视图解析器。Spring支持多种视图技术。
1.31.1.属性依赖注入的三种方式
什么是Bean属性的注入?就是对一个对象的属性赋值。有三种方式:
第一种:构造器参数注入
第二种:setter方法属性注入(setter方法的规范-JavaBean规范)
第三种:接口注入
Spring 框架规范中通过配置文件配置的方式,只支持构造器参数注入和setter方法属性注入,不支持接口注入 !
1.32.JDBC和Hibernate的比较:
相同点:
1.都是JAVA的数据库操作中间件。
2.两者对于数据库进行直接操作的对象都不是线程安全的,都需要及时关闭。
3.两者都可以对数据库的更新操作进行显式的事物处理。
不同点:
1.使用的SQL语言不同,JDBC是基于关系型数据库的标准SQL语言,Hibernate使用的是HQL(Hibernate query language)语言。
2.操作的对象不同:JDBC操作的是数据,将数据通过SQL语句直接传送到数据库中执行,而Hibernate操作的是持久化对象,由底层持久化对象的数据更新到数据库中。
3.数据状态不同:JDBC操作的数据时“瞬时"的,变量值无法与数据库中的值保持一致,而Hibernate操作的数据时刻持久的,就是持久化对象的数据属性的值时可以跟数据库中的值保持一致的。
4.内存消耗:采用JDBC的无疑是最省内存的,Hibernate的次之
5、运行效率:如果JDBC的代码写的非常优化,那么JDBC架构运行效率最高,但是实际项目中,这一点几乎做不到,这需要程序员非常精通JDBC,运用Batch语句,调整PreapredStatement的Batch Size和Fetch Size等参数,以及在必要的情况下采用结果集cache等等。而一般情况下程序员是做不到这一点的。因此Hibernate架构表现出最快的运行效率。
6、开发效率:在大的项目,特别是持久层关系映射很复杂的情况下,Hibernate效率高的惊人,JDBC次之
延迟加载是罪魁祸首,所谓“成也萧何,败也萧何”。
有时发现查询速度很慢,检查才发现是我没有启用延迟加载,造成递归的数据都被加载进来了。
如果加上了延迟加载,那么许多页面将无法使用,必须在程序里进行代码级别的递归的延迟加载数据的读取。
1 用hql来写查询语句,这是最高效的办法(推荐)
2 用jdbc,脱离了hibernate范畴,缓存方面和乐观所方面会出现不一致,而且语句变得繁琐了(不推荐)
3 将前台要用到的实体,独立设计成单独的类,没有任何关联,都是单表,用到的只是hibernate的封装以及简单的or映射
4 在大数据量系统中都会遇到类似的问题,我的解决方法是少用一对多关联映射或者不用一对多关联,设置关联少的数据表,用SQL语句做关联的查询,hibernate中映射的配置
lazy都为false
1.33.Oracle
索引:相当于一本书的目录。(数据库中的索引相当于字典的目录(索引)),它的作用就是提升查询效率。
(
通过指针(地址)加速Oracle 服务器的查询速度。
提升服务器的i/o性能(减少了查询的次数);)
原理:Oracle会自动在表空间中建立一个对象,开辟一块空间,建立索引。自动根据索引字段进行分组,并且将数据的地址(RowId)存放到索引的空间中。 查询时,Oracle会自动判断,条件字段上有没有建立索引,如果有,则优先从索引查询相关数据。
游标:基于数据库的表返回结果集,也可以理解为游标就是个结果集,但该结果集是带向前移动的指针的,每次只指向一行数据。
作用:用于临时存储一个查询返回的多行数据(结果集),通过遍历游标,可以逐行访问处理该结果集的数据。
PLSQL:是Oracle对sql语言的过程化扩展
指在SQL命令语言中增加了过程处理语句(如分支、循环等),使SQL语言具有过程处理能力。(具有编程的能力)
存储过程:就是一块PLSQL语句包装起来,起个名称
plsql是存储过程的基础。
java是不能直接调用plsql的,但可以通过存储过程这些对象来调用
数据库触发器:是一个与表相关联的、存储的PL/SQL程序,每当一个特定的数据操作语句(Insert,update,delete)在指定的表上发出时,Oracle自动地执行触发器中定义的语句序列。
触发器就是在执行某个操作(增删改)的时候触发一个动作(一段程序)。
Delete和truncate区别:
delete逐条删除,truncate先摧毁表,再重建 。
最根本的区别是:delete是DML(可以回滚,还能闪回),truncate是DDL(不可以回滚 )
Delete不会释放空间,truncate会(当确定一张表的数据不再使用,应该使用truncate)
delete会产生碎片,truncate不会。
Mysql和oracle分页
Mysql:使用limit关键字分页 后面是 起始下标和需要要查询的行数
Oracle:一般根据RONUM使用三层嵌套 ,大概思路是 最内层是不进行分页的原始查询语句,第二层控制最大值,最外层控制最小值
SELECT * FROM ( SELECT A.*, ROWNUM RN FROM
(SELECT * FROM TABLE_NAME) A WHERE ROWNUM <= 40 ) WHERE RN >= 21
1.34.REST
REST是一种设计风格,是WEB服务的一种架构风格,是一种思想
REST通常基于HTTP,URI和XML,JSON,HTML广泛流行的协议和标准
是一种面向资源的架构
REST架构原则:
网络上的所有事物都可以抽象为资源
每个资源都有唯一的标识符
对资源的操作不会改变资源的标识符
同一资源有多种变现形式:xml json
GET 获取资源
POST 创建资源
PUT 修改资源状态
DELETE 删除资源
资源的展现:
XML JSON
REST:安全性 幂等性:多次操作返回的结果一致
RESTful Web Service是一种常见REST的应用 遵循了REST风格的WEB服务
200操作成功
201 POST 对象创建成功
202 请求被接受
204 操作成功没有数据返回
400 参数列表错误
405 http方法不正确
500内部错误
什么是restful?
REST 指的是一组架构约束条件和原则。满足这些约束条件和原则的应用程序或设计就是 RESTful。
综合上面的解释,我们总结一下什么是RESTful架构:
(1)每一个URI代表一种资源;
(2)客户端和服务器之间,传递这种资源的某种表现层;
(3)客户端通过四个HTTP动词,对服务器端资源进行操作,实现"表现层状态转化"。
1.35.Rabbitmq:
介绍:Massage Queue消息队列:应用程序与应用程序之间的通信
AMQP高级消息队列协议:Advanced Message Queuing Protocol
开发语言:Erlang – 面向并发的编程语言。
六种消息队列:15672
<1>简单队列:生产者将消息发送到队列,消费者从队列中获取消息。
<2>work模式:一个生产者、2个消费者 一个消息只能被一个消费者获取。
<3>订阅模式:
1个生产者,多个消费者
2、每一个消费者都有自己的一个队列
3、生产者没有将消息直接发送到队列,而是发送到了交换机
4、每个队列都要绑定 到交换机
5、生产者发送的消息,经过交换机,到达队列,实现,一个消息被多个消费者获取的目的
(缺点消息会被每个消费者获取)
<4>路由模式
交换机类型 。有一个key 只有这个key与生产者的key相同时才会接受 也就是消费者有选择性的接受消息
<5>通配符模式
使用MQ实现商品数据的同步优势:
1、降低系统间耦合度
2、便于管理数据的同步
使用spring-AMQP spring项目
启动:rabbitmq-plugins enable rabbitmq_management
查看状态:# rabbitmqctl
1.35.1.队列和交换机的绑定关系
使用什么队列模式?
使用通配符模式
后台:定义rabbitmq连接工厂、定义管理、定义交换机、定义模板
消息内容
在后台中将消息发送到交互机
前台系统和搜索系统接受消息
后台系统 添加商品 更改商品 删除商品
前台系统 删除redis中的缓存
搜索系统 如果是更改 或者添加 ,将商品添加到缓存 如果是delete就删除缓存
方案:
1、将Item对象做json序列化发送
a)数据大
b)有些数据其他人是可能用不到的
2、发送商品的id、操作类型
实现:
1、在配置文件中将队列和交换机完成绑定
2、可以在管理界面中完成绑定
a)绑定关系如果发生变化,需要修改配置文件,并且服务需要重启
b)管理更加灵活
c)更容易对绑定关系的权限管理,流程管理
1.36.Redis:
(nosql非关系型数据库)
介绍:Redis是一个开源的使用C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库
数据结构:redis提供五种数据类型:string,hash,list,set及zset
特性:(1)支持多种数据类型的存储
(2)内存存储与持久化
(3)简单稳定 对于sql更加简单 不同语言的支持 基于c语言开发 代码量少
(4)功能丰富 支持键的生存时间 按一定规则删除键 可用作缓存 队列 消息订阅
Redis应用场景:
1.缓存:大大的提高了用户的访问速度,提高了用户的体验度
2.多系统间session不能共享
3.解决cookie容量问题 临时存储商品
Redis持久化:就是将数据保存到磁盘,机器宕机或者重启数据不丢失,如果存储到内存中的数据,会丢失。
1.两种持久化方式:RDB AOF
(1)a.RDB通过快照完成 通过配置文件的条件指定(指定时间,改动键的个数):
当在指定时间内被改动的键的个数大雨指定数值 进行快照
b.快照过程:使用fork函数复制一份当前进程 父进程继续接受处理客户端发来的命令,子进程将内存数据写入硬盘临时文件 写完临时文件替换RDB文件
c.手动快照:SAVE和BGSAVE
(2)AOF
持久化的策略是将发送给客户端的每一条命令记录 默认文件名appendonly.aof
当redis服务器重启后,会将执行该aof文件,达到数据恢复的目的。
1、安装
2、基本命令,ping、del、keys、exists、help
3、掌握字符串数据类型,set、get、append、strlen、mset
4、生存时间,expire、ttl
5、Jedis基本使用
6、Jedis连接池、集群jedis使用
启动redis cd /user/local/redis cd/bin ./redis-server redis.conf (ps aux|grep redis)
启动solr cd/user/local/solr/ ll cd tomcat/bin/startup.sh
Negix start nginx.exe
Linux命令
cd /usr 切换到指定目录
ll : 查看目录内容
mkdir abc 创建abc文件夹(目录
退出: :q
不保存退出(有变更): :q!
保存退出: :wq
1.37.nginx常用命令
start nginx.exe //启动、 linux:./nginx 非root不能占用80端口
nginx.exe –s stop //停止
nginx.exe –s reload // 重新加载配置文件
修改配置文件:conf/nginx.conf
1、nginx的反向代理、负载均衡。
2、solrCloud
a)Zookeeper。集群管理软件、
i.配置文件的集中管理
ii.集群管理
b)Tomcat实例,每个tomcat实例就是一个solr实例。
c)告诉solr zookeeper的地址及端口号。
d)使用url命令创建collection指定分片
e)使用url命令删除没有用的collection。
Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,其特点是占有内存少,并发能力强。官方测试nginx能够支支撑5万并发链接
应用场景
http服务器。Nginx是一个http服务,可以独立提供http服务。可以做网页静态服务器。
虚拟主机。可以实现在一台服务器虚拟出多个网站。例如个人网站使用的虚拟主机。
反向代理,负载均衡。当网站的访问量达到一定程度后,单台服务器不能满足用户的请求时,需要用多台服务器集群 可以使用nginx做反向代理。并且多台服务器可以平均分担负载,不会因为某台服务器负载高宕机而某台服务器闲置的情况。
图片服务器的搭建。使用ftp+http配合,实现图片服务。ftp服务使用vsftpd实现,http服务使用nginx实现。
反向代理
nginx只做请求的转发,后台有多个http服务器提供服务,nginx的功能就是把转发给后面的服务器,决定哪个服务器提供服务
如果同一个域名下有多台服务器提供服务,此时需要nginx负载均衡。
例如Web服务器、FTP服务器、企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务。
nginx作为负载均衡服务器,用户请求先到达nginx,再由nginx根据负载配置将请求转发至tomcat服务器
负载均衡:分摊到多个操作单元上进行执行
通过upstream指令指定一个负载均衡器的名称test.net
Nginx负载均衡支持4种调度算法
1 轮询(默认)weight指定轮询权值,weight值越大,分配的访问几率越高,主要用于后端服务器性能不均的情况
IP-hash 每个请求按ip的hash结果分配,这样同一个ip访客固定一个后端服务器 解决动态网页存在的session共享问题。
Fair 根据后端服务器的响应时间来分配请求,时间短的优先分配
Url-hash 按访问url的hash结果分配,使每个url定向到同一个后端服务器
nginx的高可用:
解决高可用的方案就是添加冗余 。
所有请求都到了nginx。如果nginx服务器宕机后端web服务将无法提供服务,影响严重。需建立一个备份机。主和备都运行高可用监控程序。
keepalived+nginx实现主备。
keepalived是集群管理中保证集群高可用的一个服务软件,防单点故障。
虚拟ip绑定主机 备机启用,将虚拟ip绑定到备机,提供服务。
nginx进程和keepalived不同时存在问题/。nginx进程检测脚本。判断nginx进程是否存在,不存在就将keepalived进程杀掉
1.38.EasyUI
Datagrid数据表格,是jquery easyui 功能最强大,最重要的一个插件 ,简化开发
数据表格: 数据列表显示、分页、排序、编辑
1.39.Zookeeper
ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件.
提供的功能包括:配置维护、域名服务、分布式同步、组服务等。
ZooKeeper是以Fast Paxos算法为基础的,Paxos 算法存在活锁的问题,即当有多个proposer交错提交时,有可能互相排斥导致没有一个proposer能提交成功,而Fast Paxos作了一些优化,通过选举产生一个leader (领导者),只有leader才能提交proposer,具体算法可见Fast Paxos。因此,要想弄懂ZooKeeper首先得对Fast Paxos有所了解。[3]
ZooKeeper的基本运转流程:
1、选举Leader。
2、同步数据。
3、选举Leader过程中算法有很多,但要达到的选举标准是一致的。
4、Leader要具有最高的执行ID,类似root权限。
5、集群中大多数的机器得到响应并follow选出的Leader。
2.2.Sql优化
1.避免在复杂查询中使用like%%
前台:把查询条件做成下拉列表,直接提供
后台:先查出一部分记录放进临时表,再进行复杂关联
2索引:不要在建立索引的数据列上进行操作,如计算
3Where语句
避免用in、not in、or、having
可以用exist和not exist代替,having用where代替,不行就拆分
4避免用*。。别名,count(1)或者主键
5.排序(避免使用distinct、order by等,会启动sql引擎)
6尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该考虑改写
7对于and,应该尽量把假的放到右边。
对于or,应该尽量把真的放到右边。where条件子句的解析顺序:从右到左
8子查询虽然很灵活,但是执行效率并不高(可以使用连接查询(JOIN)代替子查询,连接查询时不需要建立临时表,其速度比子查询快)
9 使用表的别名(Alias)
10 用TRUNCATE替代DELETE,删除表时
11 避免使用耗费资源的操作 带有DISTINCT,UNION,INTERSECT,ORDER BY的SQL语句会启动SQL引擎
12 应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描 (尽可能的使用 NOT NULL填充数据库)
13尽可能的使用 varchar/nvarchar 代替 char/nchar
2.3.数据库结构优化
一个好的数据库设计方案对于数据库的性能往往会起到事半功倍的效果。
需要考虑数据冗余、查询和更新的速度、字段的数据类型是否合理等多方面的内容。
2.3.1.将字段很多的表分解成多个表
对于字段较多的表,如果有些字段的使用频率很低,可以将这些字段分离出来形成新表。
因为当一个表的数据量很大时,会由于使用频率低的字段的存在而变慢。
2.3.2.增加中间表
对于需要经常联合查询的表,可以建立中间表以提高查询效率。(对于统计报表)
通过建立中间表,将需要通过联合查询的数据插入到中间表中,然后将原来的联合查询改为对中间表的查询。
2.3.3.增加冗余字段
设计数据表时应尽量遵循范式理论的规约,尽可能的减少冗余字段,让数据库设计看起来精致、优雅。但是,合理的加入冗余字段可以提高查询速度。
表的规范化程度越高,表和表之间的关系越多,需要连接查询的情况也就越多,性能也就越差。
注意:
冗余字段的值在一个表中修改了,就要想办法在其他表中更新,否则就会导致数据不一致的问题。