面向接口编程
Future模式
策略模式
享元模式
装饰器模式
UML
Java代理模式与动态代理
Java 模板模式
String.valueOf(age);
覆写equals时推荐使用getClass进行类型判断。而不是使用instanceof。
匿名内部类使用的形参为何要为final
同时实现接口和继承,如果继承的类中已经存在接口中的方法,可以不再重写该方法
interface CanFight {
void fight();
}
interface CanSwim {
void swim();
}
interface CanFly {
void fly();
}
public class ActionCharacter {
public void fight(){
}
}
public class Hero extends ActionCharacter implements CanFight,CanFly,CanSwim{
public void fly() {
}
public void swim() {
}
/** * 对于fight()方法,继承父类的,所以不需要显示声明 */
}
内部类 使用内部类最吸引人的原因是:每个内部类都能独立地继承一个(接口的)实现,所以无论外围类是否已经继承了某个(接口的)实现,对于内部类都没有影响。
在我们程序设计中有时候会存在一些使用接口很难解决的问题,这个时候我们可以利用内部类提供的、可以继承多个具体的或者抽象的类的能力来解决这些程序设计问题。可以这样说,接口只是解决了部分问题,而内部类使得多重继承的解决方案变得更加完整。
内部类实现多重继承
根据源文件名得到目标文件名,注意要用正则表达式,注意.的转义。
String destFileName = f.getName().replaceAll("\.java$", ".jad");
listFiles方法接受一个FileFilter对象,这个FileFilter对象就是过虑的策略对象,不同的人提供不同的FileFilter实现,即提供了不同的过滤策略。
Pattern.compile(args).matches();
Pattern pattern=Pattern.compile(args);
pattern.matcher(fileName).matches();
匿名内部类中使用该类的局部变量必须final
方法返回值类型为实现接口的对象策略模式
Class.forName
String为什么final将方法或类声明为final主要目的是:确保它们不会再子类中改变语义。String类是final类,这意味着不允许任何人定义String的子类。换言之,如果有一个String的引用,它引用的一定是一个String对象,而不可能是其他类的对象。
——《Java核心技术 卷I》
immutable
java Class类//将类型也作为参数传入的,无须进行类型转换操作了 static User findUser(int id,String name,Class clazz){ 参数可以指定为类名
Java 反射
FileInputStream fis = new FileInputStream("src/com/weijia/domain/daoconfig.properties");
prop.load(fis);
String className = prop.getProperty("userDaoClass");
Class> clazz = Class.forName(className);
userDao = (UserDao)clazz.newInstance();
fis.close();
ReflectionToStringBuilder.toString
String类的intern()方法
单例模式使用内部类来维护单例的实现,JVM内部的机制能够保证当一个类被加载的时候,这个类的加载过程是线程互斥的。
Java解析XML
overriding、overload
transient
Volatile
默认equals方法
Class.forName
反射demo .getDeclaredFields 获取类的所有方法 获取类的所有属性
StringBuilder也是一个可变的字符串对象,他与StringBuffer不同之处就在于它是线程不安全的,基于这点,它的速度一般都比StringBuffer快。与StringBuffer一样,StringBuider的主要操作也是append与insert方法。这两个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符添加或插入到字符串生成器中。/* 非静态内部的创建需要依赖于外围类 */ OuterClass.InnerClass2 inner2 = new OuterClass().new InnerClass2();成员内部类中要注意两点,第一:成员内部类中不能存在任何static的变量和方法;第二:成员内部类是依附于外围类的,所以只有先创建了外围类才能够创建内部类。
抽象类,接口
1.语法层面上的区别
1)抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法;
2)抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的;
3)接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法;
4)一个类只能继承一个抽象类,而一个类却可以实现多个接口。
2.设计层面上的区别
1)抽象类是对一种事物的抽象,即对类抽象,而接口是对行为的抽象。
2)设计层面不同,抽象类作为很多子类的父类,它是一种模板式设计。而接口是一种行为规范,它是一种辐射式设计。
Object有哪些方法Object是所有类的父类,任何类都默认继承Object。Object类到底实现了哪些方法?
1.clone方法
保护方法,实现对象的浅复制,只有实现了Cloneable接口才可以调用该方法,否则抛出CloneNotSupportedException异常。
2.getClass方法
final方法,获得运行时类型。
3.toString方法
该方法用得比较多,一般子类都有覆盖。
4.finalize方法
该方法用于释放资源。因为无法确定该方法什么时候被调用,很少使用。
5.equals方法
该方法是非常重要的一个方法。一般equals和==是不一样的,但是在Object中两者是一样的。子类一般都要重写这个方法。
6.hashCode方法
该方法用于哈希查找,重写了equals方法一般都要重写hashCode方法。这个方法在一些具有哈希功能的Collection中用到。
一般必须满足obj1.equals(obj2)==true。可以推出obj1.hash- Code()==obj2.hashCode(),但是hashCode相等不一定就满足equals。不过为了提高效率,应该尽量使上面两个条件接近等价。
7.wait方法
wait方法就是使当前线程等待该对象的锁,当前线程必须是该对象的拥有者,也就是具有该对象的锁。wait()方法一直等待,直到获得锁或者被中断。wait(long timeout)设定一个超时间隔,如果在规定时间内没有获得锁就返回。
调用该方法后当前线程进入睡眠状态,直到以下事件发生。
(1)其他线程调用了该对象的notify方法。
(2)其他线程调用了该对象的notifyAll方法。
(3)其他线程调用了interrupt中断该线程。
(4)时间间隔到了。
此时该线程就可以被调度了,如果是被中断的话就抛出一个InterruptedException异常。
8.notify方法
该方法唤醒在该对象上等待的某个线程。
9.notifyAll方法
该方法唤醒在该对象上等待的所有线程。
finialize
hashcode默认实现
equals与==的默认实现
JBoss优化
Jdbc总结
CPU load参数与性能的关系
性能调优工具工具:JMap JStat sar top
Tomcat调优
Java Stack Queue
Enumeration
Arrays.sort(list,String.CASE_INSENSITIVE_ORDER)
Scanner
treemap
concurrentHashMap 装载因子
阻塞队列
volatile
队列
ReentrantLock
Set实现
ArrayList 单数组
NavigableMap
Arrays.copyOf
基本数据类型是不可能泛型化的,我们经常需要使用到Arrays这个工具的asList()方法将其转换成列表。方便是方便,但是有时候会出现莫名其妙的问题。如下:
public static void main(String[] args) {
int[] datas = new int[]{
1,2,3,4,5};
List list = Arrays.asList(datas);
System.out.println(list.size());
}
————Output:
1
结果是1,是的你没有看错, 结果就是1。但是为什么会是1而不是5呢?先看asList()的源码
public static List asList(T... a) {
return new ArrayList(a);
}
注意这个参数:T…a,这个参数是一个泛型的变长参数,我们知道基本数据类型是不可能泛型化的,也是就说8个基本数据类型是不可作为泛型参数的,但是为什么编译器没有报错呢?这是因为在java中,数组会当做一个对象来处理,它是可以泛型的,所以我们的程序是把一个int型的数组作为了T的类型,所以在转换之后List中就只会存在一个类型为int数组的元素了。所以我们这样的程序System.out.println(datas.equals(list.get(0)));输出结果肯定是true。当然如果将int改为Integer,则长度就会变成5了。
Arrays.asListpublic static List asList(T... a) {
return new ArrayList(a);
}
Arrays.asList返回的ArrayList并不是java.util.ArrayList,只是Arrays的内部类。该类只提供了一些基本的操作,
1、size:元素数量
2、toArray:转换为数组,实现了数组的浅拷贝。
3、get:获得指定元素。
4、contains:是否包含某元素。
asList返回的是一个长度不可变的列表。数组是多长,转换成的列表是多长,我们是无法通过add、remove来增加或者减少其长度的
System.arraycopy方法,该方法是个JNI函数,是在JVM中实现的public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length);
数组的类名int[] array00 = new int[10]; System.out.println(“一维数组:” + array00.getClass().getName()); int array01 = new int10; System.out.println(“二维数组:” + array01.getClass().getName()); int[] array02 = new int10[10]; System.out.println(“三维数组:” + array02.getClass().getName());
一维数组:[I
二维数组:[[I
三维数组:[[[I
数组是什么,在java中它就是对象。一个比较特殊的对象int[] array = new int[10]; System.out.println(“array的父类是:” + array.getClass().getSuperclass()); System.out.println(“array的类名是:” + array.getClass().getName());
array的父类是:class java.lang.Object
array的类名是:[I
JVM空闲判断
内存优化:便于回收,减少类变量
java 堆和栈理解,哪个大
java中变量在内存中的分配
1、类变量(static修饰的变量):在程序加载时系统就为它在堆中开辟了内存,堆中的内存地址存放于栈以便于高速访问。静态变量的生命周期–一直持续到整个”系统”关闭
2、实例变量:当你使用java关键字new的时候,系统在堆中开辟并不一定是连续的空间分配给变量(比如说类实例),然后根据零散的堆内存地址,通过哈希算法换算为一长串数字以表征这个变量在堆中的”物理位置”。 实例变量的生命周期–当实例变量的引用丢失后,将被GC(垃圾回收器)列入可回收“名单”中,但并不是马上就释放堆中内存
3、局部变量:局部变量,由声明在某方法,或某代码段里(比如for循环),执行到它的时候在栈中开辟内存,当局部变量一但脱离作用域,内存立即释放 附:java的内存机制 Java 把内存划分成两种:一种是栈内存,另一种是堆内存。
在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配,当在一段代码块定义一个变量时,Java 就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java 会自动释放掉为该变量分配的内存空间,该内存空间可以立即被另作它用。
堆内存用来存放由 new 创建的对象和数组,在堆中分配的内存,由 Java 虚拟机的自动垃圾回收器来管理。在堆中产生了一个数组或者对象之后,还可以在栈中定义一个特殊的变量,让栈中的这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或者对象,引用变量就相当于是为数组或者对象起的一个名称。引用变量是普通的变量,定义时在栈中分配,引用变量在程序运行到其作用域之外后被释放。而数组和对象本身在堆中分配,即使程序运行到使用 new 产生数组或者对象的语句所在的代码块之外,数组和对象本身占据的内存不会被释放,数组和对象在没有引用变量指向它的时候,才变为垃圾,不能在被使用,但仍然占据内存空间不放,在随后的一个不确定的时间被垃圾回收器收走(释放掉)。
堆大小:虚拟内存-1GB 栈默认大小1M
Jvm垃圾回收标记在哪里?
垃圾回收算法
内存泄漏和内存溢出区别
如何判断内存泄露
Java内存和回收
Java profile和jvm性能调优
Java垃圾回收
GC算法分为哪几类
内存泄露的类型结合实际场景分析解决
深入理解JVM(七)——Class文件结构
异常使用指南应该在下列情况下使用异常。
1、在恰当的级别处理问题(在知道该如何处理异常的情况下才捕获异常)。
2、解决问题并且重新调用产生异常的方法。
3、进行少许修补,然后绕过异常发生的地方继续执行。
4、用别的数据进行计算,以代替方法预计会返回的值。
5、把当前运行环境下能做的事情尽量做完。然后把相同(不同)的异常重新抛到更高层。
6、终止程序。
7、进行简化。
8、让类库和程序更加安全。(这既是在为调试做短期投资,也是在为程序的健壮做长期投资)
异常的使用误区尽可能的减小try块!!!
保证所有资源都被正确释放。充分运用finally关键词。
catch语句应当尽量指定具体的异常类型,而不应该指定涵盖范围太广的Exception类。 不要一个Exception试图处理所有可能出现的异常。
既然捕获了异常,就要对它进行适当的处理。不要捕获异常之后又把它丢弃,不予理睬。 不要做一个不负责的人。有四种选择:
1、处理异常。对所发生的的异常进行一番处理,如修正错误、提醒。再次申明ex.printStackTrace()算不上已经“处理好了异常”.
2、重新抛出异常。既然你认为你没有能力处理该异常,那么你就尽情向上抛吧!!!
3、封装异常。这是LZ认为最好的处理方法,对异常信息进行分类,然后进行封装处理。
4、不要捕获异常。
在异常处理模块中提供适量的错误原因信息,组织错误信息使其易于理解和阅读。
不要在finally块中处理返回值。
不要在构造函数中抛出异常
throw和throws
throws是方法抛出异常。在方法声明中,如果添加了throws子句,表示该方法即将抛出异常,异常的处理交由它的调用者,至于调用者任何处理则不是它的责任范围内的了。所以如果一个方法会有异常发生时,但是又不想处理或者没有能力处理,就使用throws吧!而throw是语句抛出异常。它不可以单独使用,要么与try…catch配套使用,要么与throws配套使用。
//使用throws抛出异常
public void f() throws MyException{
try {
FileReader reader = new FileReader("G:\\myfile\\struts.txt");
Scanner in = new Scanner(reader);
System.out.println(in.next());
} catch (FileNotFoundException e) {
throw new MyException("文件没有找到", e); //throw
}
}
http://www.cnblogs.com/peida/archive/2013/04/24/3036689.html
java.util.concurrent
interrupt()唤醒休眠线程,休眠线程发生InterruptedException异常
Java并发编程 Executor框架
Java高级:线程同步lock与unlock使用
Java处理多线程concurrent机制
多线程实际场景应用和遇到的问题
线程池的原理
Java线程面试题 Top 50 - ImportNewhttp://www.importnew.com/12773.html
ThreadGroup
CAS
40个Java多线程问题总结 http://www.imooc.com/wap/article?article_id=3306
Executors.newSingleThreadScheduledExecutor()
线程安全
Timer
JSON兼容性问题 Date
file path name分别代表什么
文件锁
scanner
FileNameFilter
StringReader
字节数组 String对象
管道 其他数据源的合并作为数据源
自定义序列化
常见框架中的NIO NettyNginx
IO模式
网络IO模型
NIO
利用序列化实现对象的拷贝
当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法,但是它仍然要根据继承链中方法调用的优先级来确认方法,该优先级为:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)。
public class A {
public String show(D obj) {
return ("A and D");
}
public String show(A obj) {
return ("A and A");
}
}
public class B extends A{
public String show(B obj){
return ("B and B");
}
public String show(A obj){
return ("B and A");
}
}
public class C extends B{
}
public class D extends B{
}
public class Test {
public static void main(String[] args) {
A a1 = new A();
A a2 = new B();
B b = new B();
C c = new C();
D d = new D();
System.out.println("1--" + a1.show(b));
System.out.println("2--" + a1.show(c));
System.out.println("3--" + a1.show(d));
System.out.println("4--" + a2.show(b));
System.out.println("5--" + a2.show(c));
System.out.println("6--" + a2.show(d));
System.out.println("7--" + b.show(b));
System.out.println("8--" + b.show(c));
System.out.println("9--" + b.show(d));
}
}
运行结果:
1--A and A 2--A and A 3--A and D 4--B and A 5--B and A 6--A and D 7--B and B 8--B and B 9--A and D
http post
依赖注入容器
Spring context:component-scan context:exclude-filter
Spring启动component-scan类扫描加载过程—源码分析
spring加载原理流程
Spring的通知类型
spring注入类型
在Spring容器中为一个bean配置依赖注入有三种方式:
· 使用属性的setter方法注入 这是最常用的方式;
· 使用构造器注入;
· 使用Filed注入(用于注解方式).
使用属性的setter方法注入
首先要配置被注入的bean,在该bean对应的类中,应该有要注入的对象属性或者基本数据类型的属性。例如:为UserBiz类注入UserDAO,同时为UserBiz注入基本数据类型String,那么这时,就要为UserDAO对象和String类型设置setter方法.,用于进行依赖注入。
如何配置该bean呢?
<bean id="userBiz" class="com.text.biz.impl.UserBizImpl">
<property name="userDao">
<ref>userDaoref>
property>
bean>
以上就是一个使用属性的setter方法的方式进行依赖注入。
使用构造器注入
第一,在PersonBiz类中注入PersonDAO和一个String类型的数据;在该类中,不用为PersonDAO属性和String数据类型的属性设置setter方法,但是需要生成该类的构造方法;如下:
public class PersonBizImpl implements PersonBiz {
// 声明"依赖对象"PersonDAO
PersonDAO personDao = null;
// 声明"依赖的基本数据类型"
String str = null;
// 生成无参构造方法
public PersonBizImpl() {
super();
}
// 生成带参构造方法
public PersonBizImpl(PersonDAO personDao, String str) {
super();
this.personDao = personDao;
this.str = str;
}
public void addPerson() {
this.personDao.addPerson();
System.out.println(str);
}
}
第二,在配置文件中配置该类的bean,并配置构造器,在配置构造器中用到了节点,该节点有四个属性:
· index是索引,指定注入的属性,从0开始,如:0代表personDao,1代表str属性;
· type是指该属性所对应的类型,如Persondao对应的是com.aptech.dao.PersonDAO;
· ref 是指引用的依赖对象;
· value 当注入的不是依赖对象,而是基本数据类型时,就用value;
如下:
<bean id="personDao" class="com.aptech.dao.impl.PersonDAOImpl">bean>
<bean id="personBiz" class="com.aptech.biz.impl.PersonBizImpl">
<constructorarg index="0" type="com.aptech.dao.PersonDAO"ref="personDao">constructor-arg>
<constructor-arg index="1" value="Spring学习">constructor-arg>
bean>
使用字段(Filed)注入(用注解方式)
在Spring中,注入依赖对象可以采用手工装配或自动装配,在实际应用开发中建议使用手工装配,因为自动装配会产生许多未知情况,开发人员无法预见最终的装配结果。
手工装配依赖对象又分为两种方式:
一种是在XML文件中,通过在bean节点下配置;如上面讲到的使用属性的setter方法注入依赖对象和使用构造器方法注入依赖对象都是这种方式。
另一种就是在java代码中使用注解的方式进行装配,在代码中加入@Resource或者@Autowired、
怎样使用注解的方式来为某个bena注入依赖对象呢?
首先,我们需要在Spring容器的配置文件applicationContext.Xml文件中配置以下信息,该信心是一个Spring配置文件的模板:
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
">
beans>
注意:只有配置了红色部分的代码才可以引入注解的命名空间,否则报错。 以上的配置隐式的注册了多个对注释进行解析的处理器:AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、PersistenceAnnotationBeanPostProcessor等。
其次,在配置文件中打开节点,告诉Spring容器可以用注解的方式注入依赖对象;其在配置文件中的代码如下:
<beans>
……
<context:annotation-config>context:annotation-config>
……
beans>
第三,在配置文件中配置bean对象,如下:
<bean id="userDao" class="com.springtest.dao.impl.UserDAOImpl">bean>
<bean id="userBiz" class="com.springtest.biz.impl.UserBizImpl">bean>
第四,在需要依赖注入的BIZ类中,声明一个依赖对象,不用生成该依赖对象的setter方法,并且为该对象添加注解:
public class UserBizImpl implements UserBiz {
@Resource(name="userDao")
private UserDAO userDao = null;
public void addUser() {
this.userDao.addUser();
}
}
其中,在Java代码中可以使用@Autowired或@Resource注解方式进行Spring的依赖注入。两者的区别是:@Autowired默认按类型装配,@Resource默认按名称装配,当找不到与名称匹配的bean时,才会按类型装配。
比如:我们用@Autowired为上面的代码UserDAO接口的实例对象进行注解,它会到Spring容器中去寻找与UserDAO对象相匹配的类型,如果找到该类型则将该类型注入到userdao字段中;
如果用@Resource进行依赖注入,它先会根据指定的name属性去Spring容器中寻找与该名称匹配的类型,例如:@Resource(name=”userDao”),如果没有找到该名称,则会按照类型去寻找,找到之后,会对字段userDao进行注入。
通常我们使用@Resource。
使用注解注入依赖对象不用再在代码中写依赖对象的setter方法或者该类的构造方法,并且不用再配置文件中配置大量的依赖对象,使代码更加简洁,清晰,易于维护。
在Spring IOC编程的实际开发中推荐使用注解的方式进行依赖注入。
依赖注入—自动装配
Spring中提供了自动装配依赖对象的机制,但是在实际应用中并不推荐使用自动装配,因为自动装配会产生未知情况,开发人员无法预见最终的装配结果。
自动装配是在配置文件中实现的,如下:
<bean id="***" class="***" autowire="byType">
只需要配置一个autowire属性即可完成自动装配,不用再配置文件中写,但是在类中还是要生成依赖对象的setter方法。
Autowire的属性值有如下几个:
· byType 按类型装配 可以根据属性类型,在容器中寻找该类型匹配的bean,如有多个,则会抛出异常,如果没有找到,则属性值为null;
· byName 按名称装配 可以根据属性的名称在容器中查询与该属性名称相同的bean,如果没有找到,则属性值为null;
· constructor 与byType方式相似,不同之处在与它应用于构造器参数,如果在容器中没有找到与构造器参数类型一致的bean,那么将抛出异常;
· autodetect 通过bean类的自省机制(introspection)来决定是使用constructor还是byType的方式进行自动装配。如果发现默认的构造器,那么将使用byType的方式。
http返回码301、302
http文件上传
udp 校验
tcp粘包
CGI 技术
HTTP 302 304
SSL与TSL的区别
跨域
上传文件进度
TCP UDP
不同服务器的分工http://www.zhihu.com/question/32212996虽然Tomcat也可以认为是HTTP服务器,但通常它仍然会和Nginx配合在一起使用:动静态资源分离——运用Nginx的反向代理功能分发请求:所有动态资源的请求交给Tomcat,而静态资源的请求(例如图片、视频、CSS、JavaScript文件等)则直接由Nginx返回到浏览器,这样能大大减轻Tomcat的压力。负载均衡,当业务压力增大时,可能一个Tomcat的实例不足以处理,那么这时可以启动多个Tomcat实例进行水平扩展,而Nginx的负载均衡功能可以把请求通过算法分发到各个不同的实例进行处理应用服务器往往是运行在 HTTP Server 的背后,执行应用,将动态的内容转化为静态的内容之后,通过 HTTP Server 分发到客户端。
https://pic1.zhimg.com/f776616d42a2cc63010ca562c618a968_r.png
Tomcat 静态资源Gzip
Jpa
监听器 过滤器
Filter应用场景、生命周期、部署注意事项Filter的应用场景
通过对filter过滤器的了解,可以得知在以下三种情况下可以做些处理:
1> 通过控制对chain.doFilter的方法的调用,来决定是否需要访问目标资源。
比如,可以在用户权限验证等等。判断用户是否有访问某些资源的权限,有权限放行,没权限不执行chain.doFilter方法。
2> 通过在调用chain.doFilter方法之前,做些处理来达到某些目的。
比如,解决中文乱码的问题等等。可以在doFilter方法前,执行设置请求编码与响应的编码。甚至可以对request接口进行封装装饰来处理get请求方式的中文乱码问题(重写相应的request.getParameter方法)。
3> 通过在调用chain.doFilter方法之后,做些处理来达到某些目的。
比如对整个web网站进行压缩。在调用chain.doFilter方法之前用类A对response对象进行封装装饰,重写getOutputStream和重写getWriter方法。在类A内部中,将输出内容缓存进ByteArrayOutputStream流中,然后在chain.doFilter方法执行后,获取类A中ByteArrayOutputStream流缓存数据,用GZIPOutputStream流进行压缩下。
五、Filter实现拦截的原理
Filter接口中有一个doFilter方法,当开发人员编写好Filter类实现doFilter方法,并配置对哪个web资源进行拦截后,WEB服务器每次在调用web资源的service方法之前(服务器内部对资源的访问机制决定的),都会先调用一下filter的doFilter方法。
六、Filter生命周期
和Servlet一样Filter的创建和销毁也是由WEB服务器负责。不过与Servlet区别的是,它是1>在应用启动的时候就进行装载Filter类(与Servlet的load-on-startup配置效果相同)。2>容器创建好Filter对象实例后,调用init()方法。接着被Web容器保存进应用级的集合容器中去了等待着,用户访问资源。3>当用户访问的资源正好被Filter的url-pattern拦截时,容器会取出Filter类调用doFilter方法,下次或多次访问被拦截的资源时,Web容器会直接取出指定Filter对象实例调用doFilter方法(Filter对象常驻留Web容器了)。4>当应用服务被停止或重新装载了,则会执行Filter的destroy方法,Filter对象销毁。
注意:init方法与destroy方法只会直接一次。
七、Filter部署应用注意事项
1> filter-mapping标签中servlet-name与url-pattern。
Filter不仅可以通过url-pattern来指定拦截哪些url匹配的资源。而且还可以通过servlet-name来指定拦截哪个指定的servlet(专门为某个servlet服务了,servlet-name对应Servlet的相关配置)。
2> filter-mapping标签中dispatcher。
指定过滤器所拦截的资源被 Servlet 容器调用的方式,可以是REQUEST,INCLUDE,FORWARD和ERROR之一,默认REQUEST。用户可以设置多个 子元素用来指定 Filter 对资源的多种调用方式进行拦截。
REQUEST:
当用户直接访问页面时,Web容器将会调用过滤器。如果目标资源是通过RequestDispatcher的include()或forward()方法访问或ERROR情况时,那么该过滤器就不会被调用。
INCLUDE:
如果目标资源是通过RequestDispatcher的include()方法访问时,那么该过滤器将被调用。除此之外,该过滤器不会被调用。
FORWARD:
如果目标资源是通过RequestDispatcher的forward()方法访问时,那么该过滤器将被调用,除此之外,该过滤器不会被调用。
ERROR:
如若在A.jsp页面page指令中指定了error属性=examError.jsp,那么A.jsp中若出现了异常,会跳转到examError.jsp中处理。而在跳转到examError.jsp时,若过滤器配置了ERROR的dispather那么则会拦截,否则不会拦截。
filter 国际化 设置编码
JPA
Session cookie 与页面配合
Spring @service
springmvc框架原理和strust比较
配置SpringMVC视图
防止多人登陆 ,控制一个用户只能登录一次,不能在其他地方重新登录org.springframework.security.web.session.HttpSessionEventPublisher
IntrospectorCleanupListener 解决java.beans.Introspector导致的内存泄漏解决方案:
在WEB.XML 中配置监听器:
org.springframework.web.util.IntrospectorCleanupListener
原因:
在Web应用程序关闭时IntrospectorCleanupListener将会刷新JDK的JavaBeans的Introspector缓存。在你的web.xml中注册这个listener来确保Web应用程序的类加载器以及其加载的类正确的释放资源。
spring中的提供了一个名为 org.springframework.web.util.IntrospectorCleanupListener的监听器。它主要负责处理由 JavaBeans Introspector的使用而引起的缓冲泄露。spring中对它的描述如下:
它是一个在web应用关闭的时候,清除JavaBeans Introspector的监听器.web.xml中注册这个listener.可以保证在web 应用关闭的时候释放掉与这个web 应用相关的class loader 和由它管理的类如果你使用了JavaBeans Introspector来分析应用中的类,Introspector 缓冲中会保留这些类的引用.结果在你的应用关闭的时候,这些类以及web 应用相关的class loader没有被垃圾回收.
不幸的是,清除Introspector的唯一方式是刷新整个缓冲.这是因为我们没法判断哪些是属于你的应用的引用.所以删 除被缓冲的introspection会导致把这台电脑上的所有应用的introspection都删掉.需要注意的是,spring 托管的bean不需要使用这个监听器.因为spring它自己的introspection所使用的缓冲在分析完一个类之后会被马上从javaBeans Introspector缓冲中清除掉.应用程序中的类从来不直接使用JavaBeans Introspector.所以他们一般不会导致内部查看资源泄露.但是一些类库和框架往往会产生这个问题.例如:Struts 和Quartz.单个的内部查看泄漏会导致整个的web应用的类加载器不能进行垃圾回收.在web应用关闭之后,你会看到此应用的所有静态类资源(例如单 例).这个错误当然不是由这个类自 身引起的。
quartz 对于Web容器来说,最忌讳应用程序私自启动线程,自行进行线程调度,像Quartz这种在web容器内部默认就自己启动了10线程进行异步job调度的框架本身就是很危险的事情,很容易造成servlet线程资源回收不掉,所以我一向排斥使用quartz。
quartz还有一个问题就是不支持cluster。导致使用quartz的应用都没有办法做群集。
mybatis事物的配置和使用场景
mybatis #和$区别
hibernate1.3 Hibernate的核心接口
在Hibernate中,其核心接口主要有以下五个:
(1)Configuration接口。该类抽象了负责加载Hibernate的配置及映射信息,一个Configuration对象实例代表一个应用程序中Java类型到SQL数据库映射的完整集合,Configuration被用来构建一个SessionFactory,映射定义则由不同的XML映射定义文件编译而来。
(2)SessionFactory接口。其为一个Java接口,它是针对单个数据库映射关系经过编译得到的内存镜像。单个项目通常只需一个SessionFactory,当该项目需操作多个数据库时,必须为每个数据库指定一个SessionFactory。
(3)Session接口。该接口对于开发人员来说很重要,表示应用程序与数据持久层之间交互操作的一个单线程对象,此对象生存期很短。其隐藏了JDBC连接,同时也是Hibernate事务(Transcation)的工厂。
(4)Transaction接口。Hibernate通过Transaction来声明事务边界。Hibernate可以配置为JDBC、JTA或CMT三种事务之一。
(5)Query。在Hibernate中,HQL语言是Hibernate提供的一个非常强大的面向对象的查询语言,其语言特性与SQL语言非常类似。
hibernate 数据的三个状态
如果优化Hibernate
Hibernate有哪5个核心接口
hibernate查询方式
Struts总结
struts 拦截器
struts.xml中result的type有哪些类型?
struts Exception处理机制
struts 类型转换
struts 国际化
struts 上传下载
Struts 权限过滤器使用
数据库查询分页
数据库连接池
MySQL 事务 命令行 jdbc
MySQL 存储过程 与 调用
MySQL replace
索引
触发器
视图
数据库三范式
SQL注入实际场景分析解决
避免SQL注入的方法
ALTER TABLE teacher_t DEFAULT CHARSET 'UTF8';ALTER DATABASE test CHARSET 'utf8';
INSERT into device_management.ca_card_style_tb(ca_card_style) (SELECT b.CACardStyle from idtvdevmng.CA_Card_Style_tb b )
update user set money=money-10 where id=1
drop table if exists Book
SQL like语句注入like查询时,如果用户输入的值有”“和”%”,则会出现这种情况:用户本来只是想查询”abcd“,查询结果中却有”abcd_”、”abcde”、”abcdf”等等;用户要查询”30%”(注:百分之三十)时也会出现问题。 防止SQL注入防止SQL注入,我们需要注意以下几个要点: 1.永远不要信任用户的输入。对用户的输入进行校验,可以通过正则表达式,或限制长度;对单引号和 双”-“进行转换等。 2.永远不要使用动态拼装sql,可以使用参数化的sql或者直接使用存储过程进行数据查询存取。 3.永远不要使用管理员权限的数据库连接,为每个应用使用单独的权限有限的数据库连接。 4.不要把机密信息直接存放,加密或者hash掉密码和敏感的信息。 5.应用的异常信息应该给出尽可能少的提示,最好使用自定义的错误信息对原始错误信息进行包装 6.sql注入的检测方法一般采取辅助软件或网站平台来检测,软件一般采用sql注入检测工具jsky,网站平台就有亿思网站安全平台检测工具。MDCSOFT SCAN等。采用MDCSOFT-IPS可以有效的防御SQL注入,XSS攻击等。
MySQL存储过程的优缺点
MySQL 索引:存储结构,是不是越多越好
MySQL锁与语句调用
用户权限
在 MySQL5.7 中 user 表的 password 已换成了authentication_string。
注意:在注意需要执行 FLUSH PRIVILEGES 语句。 这个命令执行后会重新载入授权表。
如果你不使用该命令,你就无法使用新创建的用户来连接mysql服务器,除非你重启mysql服务器。
你可以在创建用户时,为用户指定权限,在对应的权限列中,在插入语句中设置为 ‘Y’ 即可,用户权限列表如下:
Select_priv
Insert_priv
Update_priv
Delete_priv
Create_priv
Drop_priv
Reload_priv
Shutdown_priv
Process_priv
File_priv
Grant_priv
References_priv
Index_priv
Alter_priv
除非你使用 LIKE 来比较字符串,否则MySQL的WHERE子句的字符串比较是不区分大小写的。 你可以使用 BINARY 关键字来设定WHERE子句的字符串比较是区分大小写的。
如下实例
root@host# mysql -u root -p password;
Enter password:*******
mysql> use RUNOOB;
Database changed
mysql> SELECT * from runoob_tbl \
WHERE BINARY runoob_author='sanjay';
Empty set (0.02 sec)
为了处理这种情况,MySQL提供了三大运算符:
IS NULL: 当列的值是NULL,此运算符返回true。
IS NOT NULL: 当列的值不为NULL, 运算符返回true。
<=>: 比较操作符(不同于=运算符),当比较的的两个值为NULL时返回true。
关于 NULL 的条件比较运算是比较特殊的。你不能使用 = NULL 或 != NULL 在列中查找 NULL 值 。
在MySQL中,NULL值与任何其它值的比较(即使是NULL)永远返回false,即 NULL = NULL 返回false 。
MySQL中处理NULL使用IS NULL和IS NOT NULL运算符。
正则表达式
http://www.runoob.com/mysql/mysql-regexp.html
SELECT name FROM person_tbl WHERE name REGEXP ‘^st’;
索引
索引分单列索引和组合索引。单列索引,即一个索引只包含单个列,一个表可以有多个单列索引,但这不是组合索引。组合索引,即一个索包含多个列。
创建索引时,你需要确保该索引是应用在 SQL 查询语句的条件(一般作为 WHERE 子句的条件)。
实际上,索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录。
上面都在说使用索引的好处,但过多的使用索引将会造成滥用。因此索引也会有它的缺点:虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件。
建立索引会占用磁盘空间的索引文件。
创建索引
有四种方式来添加数据表的索引:
ALTER TABLE tbl_name ADD PRIMARY KEY (column_list): 该语句添加一个主键,这意味着索引值必须是唯一的,且不能为NULL。
ALTER TABLE tbl_name ADD UNIQUE index_name (column_list): 这条语句创建索引的值必须是唯一的(除了NULL外,NULL可能会出现多次)。
ALTER TABLE tbl_name ADD INDEX index_name (column_list): 添加普通索引,索引值可出现多次。
ALTER TABLE tbl_name ADD FULLTEXT index_name (column_list):该语句指定了索引为 FULLTEXT ,用于全文索引。
创建临时表
如果你退出当前MySQL会话,再使用 SELECT命令来读取原先创建的临时表数据,那你会发现数据库中没有该表的存在,因为在你退出时该临时表已经被销毁了。
CREATE TEMPORARY TABLE SalesSummary (
-> product_name VARCHAR(50) NOT NULL
-> , total_sales DECIMAL(12,2) NOT NULL DEFAULT 0.00
-> , avg_unit_price DECIMAL(7,2) NOT NULL DEFAULT 0.00
-> , total_units_sold INT UNSIGNED NOT NULL DEFAULT 0
);
复制表
SHOW CREATE TABLE runoob_tbl \G;
修改数据表名,执行SQL语句
INSERT INTO clone_tbl (runoob_id,
-> runoob_title,
-> runoob_author,
-> submission_date)
-> SELECT runoob_id,runoob_title,
-> runoob_author,submission_date
-> FROM runoob_tbl;
元数据
查询结果信息 数据库和数据表的信息 服务器信息
SELECT VERSION( ) 服务器版本信息
SELECT DATABASE( ) 当前数据库名 (或者返回空)
SELECT USER( ) 当前用户名
SHOW STATUS 服务器状态
SHOW VARIABLES 服务器配置变量
自增序列
在MySQL的客户端中你可以使用 SQL中的LAST_INSERT_ID( ) 函数来获取最后的插入表中的自增列的值 Java如何获取
重置序列
mysql> ALTER TABLE insect DROP id;
mysql> ALTER TABLE insect
-> ADD id INT UNSIGNED NOT NULL AUTO_INCREMENT FIRST,
-> ADD PRIMARY KEY (id);
设置序列的开始值
一般情况下序列的开始值为1,但如果你需要指定一个开始值100,那我们可以通过以下语句来实现:
mysql> CREATE TABLE insect
-> (
-> id INT UNSIGNED NOT NULL AUTO_INCREMENT = 100,
-> PRIMARY KEY (id),
-> name VARCHAR(30) NOT NULL, # type of insect
-> date DATE NOT NULL, # date collected
-> origin VARCHAR(30) NOT NULL # where collected
);
或者你也可以在表创建成功后,通过以下语句来实现:
mysql> ALTER TABLE t AUTO_INCREMENT = 100;
防止数据重复
设置字段为primary key或者unique索引
INSERT IGNORE INTO当插入数据时,在设置了记录的唯一性后,如果插入重复数据,将不返回错误,只以警告形式返回。 而REPLACE INTO into如果存在primary 或 unique相同的记录,则先删除掉。再插入新记录。
添加一个UNIQUE索引,如下所示:
CREATE TABLE person_tbl
(
first_name CHAR(20) NOT NULL,
last_name CHAR(20) NOT NULL,
sex CHAR(10)
UNIQUE (last_name, first_name)
);
统计重复数据
SELECT COUNT(*) as repetitions, last_name, first_name FROM person_tbl GROUP BY last_name, first_name HAVING repetitions > 1;
过滤重复数据
mysql> SELECT DISTINCT last_name, first_name
-> FROM person_tbl
-> ORDER BY last_name;
你也可以使用 GROUP BY 来读取数据表中不重复的数据:
mysql> SELECT last_name, first_name
-> FROM person_tbl
-> GROUP BY (last_name, first_name);
删除重复数据
如果你想删除数据表中的重复数据,你可以使用以下的SQL语句:
mysql> CREATE TABLE tmp SELECT last_name, first_name, sex
-> FROM person_tbl;
-> GROUP BY (last_name, first_name);
mysql> DROP TABLE person_tbl;
mysql> ALTER TABLE tmp RENAME TO person_tbl;
当然你也可以在数据表中添加 INDEX(索引) 和 PRIMAY KEY(主键)这种简单的方法来删除表中的重复记录。方法如下:
mysql> ALTER IGNORE TABLE person_tbl
-> ADD PRIMARY KEY (last_name, first_name);
redis其他缓存比较
常量的存储 redis
读取堵塞问题
redis 与 Memcached的区别
Memcached支持的协议
Redis集群 主从快速切换
Redis bitmap
Memcached运行状态
Memcached 列出所有的key
public class Telnet {
public static void main(String args[]) {
String[] keys = allkeys("localhost", 11211).split("\n");
Arrays.sort(keys);
for(String s : keys){
System.out.println(s);
}
System.out.println(telnet("localhost", 11211, "stats"));
}
public static String allkeys(String host, int port){
StringBuffer r = new StringBuffer();
try {
Socket socket = new Socket(host, port);
PrintWriter os = new PrintWriter(socket.getOutputStream());
BufferedReader is = new BufferedReader(new InputStreamReader( socket.getInputStream()));
os.println("stats items");
os.flush();
String l ;
while (!(l = is.readLine()).equals("END")) {
r.append(l).append("\n");
}
String rr = r.toString();
Set ids = new HashSet();
if(rr.length() > 0){
r = new StringBuffer();//items
rr.replace("STAT items", "");
for(String s : rr.split("\n")){
ids.add(s.split(":")[1]);
}
if (ids.size() > 0){
r = new StringBuffer();//
for(String s : ids){
os.println("stats cachedump "+ s +" 0");
os.flush();
while (!(l = is.readLine()).equals("END")) {
r.append(l.split(" ")[1]).append("\n");
}
}
}
}
os.close();
is.close();
socket.close();
} catch (Exception e) {
System.out.println("Error" + e);
}
return r.toString();
}
public static String telnet(String host, int port, String cmd){
StringBuffer r = new StringBuffer();
try {
Socket socket = new Socket(host, port);
PrintWriter os = new PrintWriter(socket.getOutputStream());
BufferedReader is = new BufferedReader(new InputStreamReader( socket.getInputStream()));
os.println(cmd);
os.flush();
String l ;
while (!(l = is.readLine()).equals("END")) {
r.append(l).append("\n");
}
os.close();
is.close();
socket.close();
} catch (Exception e) {
System.out.println("Error" + e);
}
return r.toString();
}
}
ngnix分发原理
Ngnix分发算法
Nginx前端缓冲代理
kafak或者其他消息中间件原理,比较
卡夫卡存储结构 快的原因 与其他MQ的对比
linux select epoll
tail -f
top
常见数据结构
web service
秒杀避免商品超卖方法前端、后端各有哪些方法前端哪些措施缓解高并发后端数据库怎么处理商品超卖
PaaS模式
Rest API
什么是重量级?什么是轻量级?
SOA
分布式部署
搜索算法设计
自我介绍
涉及工作经历和关键的项目、产品经历,如果有与目标岗位或公司产品相关的经历,就重点提到。
为什么来应聘这个岗位
碰见这类问题,应该结合自己的经历、商业价值和将来定位,再加上对岗位职能的了解,将回答聚焦在个人与公司的匹配性上。
如何发起技术问题讨论和学习
七种基本技能是:数组,字符串与哈希表、正则表达式、调试、两门语言、一个开发环境、SQL 语言和编写软件的思想。效率目前最难解决的问题是贪玩!!!一天的时间倒叙复习
Netty基础
Jshell
Rational Rose与建模j2ee 原理
jquery框架
LDAP
Hadoop 解决的瓶颈
Emma原理
django
谈一谈你对脚本语言的理解 你的优点缺点
微信应用号来了,你自己的 app 该怎么办?http://card.weibo.com/article/h5/s#cid=2309353930199359112579&vid=1880591992&extparam=&from=1057195010&wm=9848_0009&ip=121.34.118.148
数据库设计 Step by Step (1)——扬帆启航http://blog.jobbole.com/99057/ ivy
Quartz
Resume
WildFly
velocity
Nutz
ExceptionInInitializerError
别了!华为8年女硕士离职感言!http://mp.weixin.qq.com/s?__biz=MjM5MjExNDIzNw==&mid=401845920&idx=1&sn=4dad0a927b7b401ea1f473acc41fca66&scene=1&srcid=0120lnfCXGjuvxFBZcVznRHo#wechat_redirect
portlet
制定逃亡计划 打败你的正是自己
高质量代码 改善java程序的151个建议
吸引力法则
传输过程中如何强行关闭输出流
前言 | Docker —— 从入门到实践 http://dockerpool.com/static/books/docker_practice/index.html
源码太枯燥,转成uml设计框架,结合设计模式挑感兴趣的学习;自己模拟一些场景应用情况,比较各种框架存在的问题