顶级架构师学习——第十五阶段:学渣最后的挣扎(ajax,listener,filter,classloader)

哎呀呀,一不小心就到基础阶段的最后一部分了呢!昨天&今天学习的主要内容是ajax,listener,filter和classloader。

目录

异步AJAX

简介

运行原理

js原生的Ajax技术(了解)

Json数据格式(重要)

Json的格式与解析

Json的转换插件

Jquery的Ajax技术(重点)

监听器Listener

什么是监听器?

监听器有哪些?

监听三大域对象的创建与销毁的监听器

监听三大域对象的属性变化的监听器

对象感知监听器

过滤器Filter

简介

快速入门

API详解

filter生命周期

API详解

Filter的配置

访问方式(了解)

Filter的作用

类加载器ClassLoader

简介

类加载器的种类

获得类加载器

注解Annotation

什么是注解

注解的作用

jdk5提供的注解

元注解

自定义注解(了解)

编写注解

使用注解

解析注解

代理Proxy

什么是代理

动态代理的API

实例


异步AJAX

简介

AJAX即“Asynchronous Javascript And XML”(异步 Javascript 和 XML)可以使网页实现异步更新就是不重新加载整个网页的情况下,对网页的某部分进行更新(局部刷新)。传统的网页(不使用AJAX)如果需要更新内容,必须重载整个网页页面。

AJAX = 异步 Javascript 和 XML,是一种新的思想,整合之前的多种技术,用于创建快速交互式网页应用的网页开发技术。

提一下同步和异步吧:

同步现象:客户端发送请求到服务器端,当服务器返回响应之前,客户端都处于等待、卡死状态

异步现象:客户端发送请求到服务器端,无论服务器是否返回响应,客户端都可以随意做其他事情,不会被卡死

 通过使用AJAX,我们可以跳过中间那段执行代码的等待时间,从而大幅度的提高工作效率。

运行原理

页面发起请求,会将请求发送给浏览器内核中的Ajax引擎,Ajax引擎会提交请求到 服务器端,在这段时间里,客户端可以任意进行任意操作,直到服务器端将数据返回 给Ajax引擎后,会触发你设置的事件,从而执行自定义的js逻辑代码完成某种页面1的功能。

具体的步骤如下:

js原生的Ajax技术(了解)

js原生的Ajax其实就是围绕浏览器内内置的Ajax引擎对象进行学习的,要使用js原生的Ajax完成异步操作,有如下几个步骤:

  1. 创建Ajax引擎对象
  2. 为Ajax引擎对象绑定监听(监听服务器已将数据响应给引擎)
  3. 绑定提交地址
  4. 发送请求
  5. 接受响应数据

对于GET请求 : 

// 1、创建引擎对象
var xmlhttp = new XMLHttpRequest();
// 2、绑定监听事件
xmlhttp.onreadystatechange = function() {
    // 5、接收响应数据
    if(xmlhttp.readyState == 4 && xmlhttp.status == 200) {
        var res = xmlhttp.responseText;
        alert(res);
    }
}
// 3、绑定跳转页面地址
xmlhttp.open("GET", "${pageContext.request.contextPath}/ajax",true);
// 4、发送请求
xmlhttp.send();

 注意:如果是post提交,需要在发送请求之前设置一个头:xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");  直接复制粘贴即可,似乎是格式emmm

XMLHttpRequest对象浏览器兼容:

function getXMLhttp() {
    var xmlhttp = null;
    // 谷歌、火狐、IE7+
    if(window.XMLHttpRequest) {// 检测浏览器是否支持XMLHttpRequset
        xmlhttp = new XMLHttpRequest();
    } else if (window.ActiveXObject) {
        // IE旧版本浏览器
        xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
    }
}

Json数据格式(重要)

json是一种与语言无关的数据交换的格式,我们使用使用ajax进行前后台数据交换或进行移动端与服务端的数据交换。

Json的格式与解析

json有两种格式

  1. 对象格式:{"key1":obj,"key2":obj,"key3":obj...}
  2. 数组/集合格式:[obj,obj,obj...]

例如:user对象用json数据格式表示

{"username":"zhangsan","age":28,"password":"123","addr":"北京"}

List<Product> 用json数据格式表示

[{"pid":"10","pname":"小米4C"},{},{}]

注意:对象格式和数组格式可以互相嵌套

注意:json的key是字符串,value是Object

json的解析

json是js的原生内容,也就意味着js可以直接取出json对象中的数据

Json的转换插件

将java的对象或集合转成json形式字符串

json的转换插件是通过java的一些工具,直接将java对象或集合转换成json字符串。

常用的json转换工具有如下几种:

  1. jsonlib
  2. Gson:google
  3. fastjson:阿里巴巴(使用最便捷)

Jquery的Ajax技术(重点)

jquery是一个优秀的js框架,自然对js原生的ajax进行了封装,封装后的ajax的操作方法更简洁,功能更强大,与ajax操作相关的jquery方法有如下几种,但开发中经常使用的是前三种:

$.ajax([options])
$.get(url, [data], [fn], [type])
$.post(url, [data], [fn], [type])
load(url, [data], [callback])
$.getJSON(url, [data], [fn])
$.getScript(url, [callback])

1.$.get(url, [data], [callback], [type])

2.$.post(url, [data], [callback], [type])

其中:

url:代表请求的服务器端地址

data:代表请求服务器端的数据(可以是key=value形式也可以是json格式)

callback:表示服务器端成功响应所触发的函数(只有正常成功返回才执行)

type:表示服务器端返回的数据类型(jquery会根据指定的类型自动类型转换)

常用的返回类型:text、json、html等

3.$.ajax( { option1:value1,option2:value2... } );

常用的option有如下:

async:是否异步,默认是true代表异步

data:发送到服务器的参数,建议使用json格式

dataType:服务器端返回的数据类型,常用text和json

success:成功响应执行的函数,对应的类型是function类型

type:请求方式,POST/GET

url:请求服务器端地址

监听器Listener

什么是监听器?

监听器就是监听某个对象的的状态变化的组件

监听器的相关概念:

事件源:被监听的对象  ----- 三个域对象 request  session  servletContext

监听器:监听事件源对象、事件源对象的状态的变化都会触发监听器 ---- 6+2

注册监听器:将监听器与事件源进行绑定

响应行为:监听器监听到事件源的状态变化时所涉及的功能代码 ---- 程序员编写代码

监听器有哪些?

第一维度:按照被监听的对象划分:ServletRequest域、HttpSession域、ServletContext域

第二维度:监听的内容分:监听域对象的创建与销毁的和监听域对象的属性变化的

监听三大域对象的创建与销毁的监听器

1、监听ServletContext域的创建与销毁的监听器ServletContextListener

1)Servlet域的生命周期

何时创建:服务器启动创建

何时销毁:服务器关闭销毁

2)监听器的编写步骤(重点):

  1. 编写一个监听器类去实现监听器接口
  2. 覆盖监听器的方法
  3. 需要在web.xml中进行配置---注册

3)监听的方法:

4)配置文件(web.xml):

5)ServletContextListener监听器的主要作用

  1. 初始化的工作:初始化对象初始化数据 ---- 加载数据库驱动、连接池的初始化
  2. 加载一些初始化的配置文件 --- spring的配置文件
  3. 任务调度----定时器----Timer/TimerTask
public class BirthdayListener implements ServletContextListener{

	@Override
	public void contextInitialized(ServletContextEvent sce) {
		//当web应用启动 开启任务调动---功能在用户的生日当前发送邮件
		//开启一个定时器
		Timer timer = new Timer();
		timer.scheduleAtFixedRate(new TimerTask() {
			
			@Override
			public void run() {
				// 为当前的生日的用户发邮件
				//1、获得今天过生日的人
				//获得今天的日期
				SimpleDateFormat format = new SimpleDateFormat("MM-dd");
				String currentDate = format.format(new Date());
				//根据当前时间从数据查询今天过生日的人
				QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
				String sql = "select * from customer where birthday like ?";
				List<Customer> customerList = null;
				try {
					customerList = runner.query(sql, new BeanListHandler<Customer>(Customer.class) ,"%"+currentDate+"%");
				} catch (SQLException e) {
					e.printStackTrace();
				} //08-18
				//2、发邮件
				if(customerList!=null&&customerList.size()>0){
					for(Customer c : customerList){
						String emailMsg = "亲爱的:"+c.getRealname()+",生日快乐!";
						try {
							MailUtils.sendMail(c.getEmail(), "生日祝福", emailMsg);
							System.out.println(c.getRealname()+"邮件发送完毕");
						} catch (MessagingException e) {
							e.printStackTrace();
						}
					}
				}
				
				
			}
		}, new Date(), 1000*10);
		//实际开发中起始时间是一个固定的时间
		//实际开发中间隔时间是1天
	}

	@Override
	public void contextDestroyed(ServletContextEvent sce) {
		
	}

}

1、监听Httpsession域的创建于销毁的监听器HttpSessionListener

1)HttpSession对象的生命周期

何时创建:第一次调用request.getSession时创建

何时销毁:服务器关闭销毁  session过期  手动销毁

2)HttpSessionListener的方法

3、监听ServletRequest域创建与销毁的监听器ServletRequestListener

1)ServletRequest的生命周期

创建:每一次请求都会创建request

销毁:请求结束

2)ServletRequestListener的方法

监听三大域对象的属性变化的监听器

1、域对象的通用的方法:

setAttribute(name,value)

 --- 触发添加属性的监听器的方法   

 --- 触发修改属性的监听器的方法

getAttribute(name)

removeAttribute(name)  

--- 触发删除属性的监听器的方法

2、ServletContextAttibuteListener监听器

 

public class MyServletContextAttributeListener implements ServletContextAttributeListener{

	@Override
	public void attributeAdded(ServletContextAttributeEvent scab) {
		//放到域中的属性
		System.out.println(scab.getName());//放到域中的name
		System.out.println(scab.getValue());//放到域中的value
	}

	@Override
	public void attributeRemoved(ServletContextAttributeEvent scab) {
		System.out.println(scab.getName());//删除的域中的name
		System.out.println(scab.getValue());//删除的域中的value
	}

	@Override
	public void attributeReplaced(ServletContextAttributeEvent scab) {
		System.out.println(scab.getName());//获得修改前的name
		System.out.println(scab.getValue());//获得修改前的value
	}

}

3、HttpSessionAttributeListener监听器(同上)

4、ServletRequestAriibuteListenr监听器(同上)

对象感知监听器

与session中的绑定的对象相关的监听器

1、即将要被绑定到session中的对象有几种状态

绑定状态:就一个对象被放到session域中

解绑状态:就是这个对象从session域中移除了

钝化状态:是将session内存中的对象持久化(序列化)到磁盘

活化状态:就是将磁盘上的对象再次恢复到session内存中

2、绑定与解绑的监听器HttpSessionBindingListener

public class Person implements HttpSessionBindingListener{

	private String id;
	private String name;
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
		
	@Override
	//绑定的方法
	public void valueBound(HttpSessionBindingEvent event) {
		System.out.println("person被绑定了");
	}
	@Override
	//解绑方法
	public void valueUnbound(HttpSessionBindingEvent event) {
		System.out.println("person被解绑了");
	}	

}

 3、钝化与活化的监听器HttpSessionActivationListener

可以通过配置文件指定对象钝化时间 --- 对象多长时间不用被钝化

在META-INF下创建一个context.xml

<Context>
 <!-- maxIdleSwap:session中的对象多长时间不使用就钝化 -->
 <!-- directory:钝化后的对象的文件写到磁盘的哪个目录下  配置钝化的对象文件在												work/catalina/localhost/钝化文件 -->
 <Manager className="org.apache.catalina.session.PersistentManager" 																				maxIdleSwap="1">
  <Store className="org.apache.catalina.session.FileStore" directory="itcast205" />
 </Manager>
</Context>

钝化和活化session对象到本地:

public class Customer implements HttpSessionActivationListener,Serializable{

	private String id;
	private String name;
	
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
		
	@Override
	//钝化
	public void sessionWillPassivate(HttpSessionEvent se) {
		System.out.println("customer被钝化了");
	}
	@Override
	//活化
	public void sessionDidActivate(HttpSessionEvent se) {
		System.out.println("customer被活化了");
	}
	
}

过滤器Filter

简介

filter是对客户端访问资源的过滤,符合条件放行,不符合条件不放行,并且可以对目标资源访问前后进行逻辑处理。

快速入门

步骤(给出自动登录的filter作为示例):

1.编写一个过滤器的类实现Filter接口

2.实现接口中尚未实现的方法(着重实现doFilter方法)

public class AutoLoginFilter implements Filter{

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		
		HttpServletRequest req = (HttpServletRequest) request;
		HttpServletResponse resp = (HttpServletResponse) response;
		HttpSession session = req.getSession();
		
		//获得cookie中用户名和密码 进行登录的操作
		//定义cookie_username
		String cookie_username = null;
		//定义cookie_password
		String cookie_password = null;
		//获得cookie
		Cookie[] cookies = req.getCookies();
		if(cookies!=null){
			for(Cookie cookie : cookies){
				//获得名字是cookie_username和cookie_password
				if("cookie_username".equals(cookie.getName())){
					cookie_username = cookie.getValue();
					//恢复中文用户名
					cookie_username = URLDecoder.decode(cookie_username, "UTF-8");
				}
				if("cookie_password".equals(cookie.getName())){
					cookie_password = cookie.getValue();
				}
			}
		}
		
		//判断username和password是否是null
		if(cookie_username!=null&&cookie_password!=null){
			//登录的代码
			UserService service = new UserService();
			User user = null;
			try {
				user = service.login(cookie_username,cookie_password);
			} catch (SQLException e) {
				e.printStackTrace();
			}
			//将登录的用户的user对象存到session中
			session.setAttribute("user", user);
		}
		
		//放行
		chain.doFilter(req, resp);		
	}	
	
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		
	}

	@Override
	public void destroy() {
		
	}	
	
}

3.在web.xml中进行配置(主要是配置要对哪些资源进行过滤)

<filter>
	<filter-name>AutoLoginFilter</filter-name>
	<filter-class>com.ithiema.web.filter.AutoLoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AutoLoginFilter</filter-name>
	<url-pattern>/*</url-pattern>
</filter-mapping>

API详解

filter生命周期

Filter接口有三个方法,并且这个三个都是与Filter的生命相关的方法

init(Filterconfig):代表filter对象初始化方法 filter对象创建时执行

doFilter(ServletRequest,ServletResponse,FilterCha):代表filter执行过滤的核心方法,如果某资源在已经被配置到这个filter进行过滤的话,那么每次访问这个资源都会执行doFilter方法

destory():代表是filter销毁方法 当filter对象销毁时执行该方法

Filter对象的生命周期:

Filter何时创建:服务器启动时就创建该filter对象

Filter何时销毁:服务器关闭时filter销毁

API详解

1.init(FilterConfig)

其中参数config代表 该Filter对象的配置信息的对象,内部封装是该filter的配置信息。

2.destory()方法

filter对象销毁时执行

3.doFilter方法

doFilter(ServletRequest,ServletResponse,FilterChain)

其中的参数:

ServletRequest/ServletResponse:每次在执行doFilter方法时 web容器负责创建一个request和一个response对象作为doFilter的参数传递进来。该request个该response就是在访问目标资源的service方法时的request和response。

FilterChain:过滤器链对象,通过该对象的doFilter方法可以放行该请求

Filter的配置

具体的配置,上面已经给过了,这里进行一下各个参数的介绍:

url-pattern配置时

1.完全匹配  /sertvle1

2.目录匹配  /aaa/bbb/* ----最多的

    /user/*:访问前台的资源进入此过滤器

    /admin/*:访问后台的资源时执行此过滤器

3.扩展名匹配  *.abc  *.jsp

注意:url-pattern可以使用servlet-name替代,也可以混用

访问方式(了解)

dispatcher有以下四个方式(值)

REQUEST:默认值,代表直接访问某个资源时执行filter

FORWARD:转发时才执行filter

INCLUDE: 包含资源时执行filter

ERROR:发生错误时 进行跳转是执行filter

Filter的作用

过滤器Filter的作用大概有以下三点:

1.公共代码的提取

2.可以对request和response中的方法进行增强(装饰者模式/动态代理)

3.进行权限控制

类加载器ClassLoader

简介

类加载器被用于加载字节码文件(.class)

类加载器的种类

类加载器有三种,不同类加载器加载不同的类。

  1. BootStrap:引导类加载器:加载都是最基础的文件
  2. ExtClassLoader:扩展类加载器:加载都是基础的文件
  3. AppClassLoader:应用类加载器:三方jar包和自己编写java文件

获得类加载器

// 获得Demo字节码文件的类加载器
Class clazz = Demo.class;// 获得Demo的字节码对象
ClassLoader classLoader = clazz.getClassLoader();// 获得类加载器
// getResource的参数路径相对classes(src)
// 获得classes(src)下的任何的资源
// jdbc.properties位于src目录下
String path = classLoader.getResource("jdbc.properties").getPath();
System.out.println(path);

注解Annotation

什么是注解

Annotation注解,是一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举在同一个层次。与注释相比较而言,注释是给开发人员阅读的,而注解是给jvm的编译提供信息的。

关于配置文件与注解开发的优缺点:

注解优点:开发效率高 成本低  

注解缺点:耦合性大 并且不利于后期维护

注解的作用

1、编译检查:通过给代码标识注解,让编译器能够实现基本的编译检查,如@Override。

2、代码分析:通过给代码标识注解,对代码进行分析,从而达到取代xml的目的。

3、编写文档:通过给代码标识注解,辅助生成帮助文档对应的内容。

jdk5提供的注解

经常使用的是以下三种:

@Override:告知编译器此方法是覆盖父类的

@Deprecated:标注过时

@SuppressWarnings:压制警告

不同的注解只能在不同的位置使用(方法上、字段上、类上),由元注解标识作用对象

元注解

元注解是指注解的注解,包括@Retention @Target @Document @Inherited四种。

1.@Retention: 定义注解的保留策略
@Retention(RetentionPolicy.SOURCE)   //注解仅存在于源码中,在class字节码文件中不包含
@Retention(RetentionPolicy.CLASS)     // 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得,
@Retention(RetentionPolicy.RUNTIME)  // 注解会在class字节码文件中存在,在运行时可以通过反射获取到
首先要明确生命周期长度 SOURCE < CLASS < RUNTIME,所以前者能作用的地方后者一定也能作用。一般如果需要在运行时去动态获取注解信息,那只能用 RUNTIME 注解;如果要在编译时进行一些预处理操作,比如生成一些辅助代码(如 ButterKnife),就用 CLASS注解;如果只是做一些检查性的操作,比如 @Override 和 @SuppressWarnings,则可选用 SOURCE 注解。

2.@Target:定义注解的作用目标
源码为:
@Documented  
@Retention(RetentionPolicy.RUNTIME)  
@Target(ElementType.ANNOTATION_TYPE)  
public @interface Target {  
    ElementType[] value();  
}  
@Target(ElementType.TYPE)   //接口、类、枚举、注解
@Target(ElementType.FIELD) //字段、枚举的常量
@Target(ElementType.METHOD) //方法
@Target(ElementType.PARAMETER) //方法参数
@Target(ElementType.CONSTRUCTOR)  //构造函数
@Target(ElementType.LOCAL_VARIABLE)//局部变量
@Target(ElementType.ANNOTATION_TYPE)//注解
@Target(ElementType.PACKAGE) ///包    

3.@Document:说明该注解将被包含在javadoc中

4.@Inherited:说明子类可以继承父类中的该注解

自定义注解(了解)

根据实际需求,编写使用并解析(通过反射机制)注解。

编写注解

关键字:@interface

注解的属性:

语法:返回值名称();

注意:如果属性的名字是value,并且注解的属性值有一个那么在使用注解时可以省略value

注解属性类型只能是以下几种

1.基本类型

2.String

3.枚举类型

4.注解类型

5.Class类型

6.以上类型的一维数组类型

使用注解

在类/方法/字段 上面是@XXX(......)

解析注解

要想解析使用了注解的类,那么该注解的Retention必须设置成Runtime

注解解析的实质:从注解中解析出属性值

字节码对象存在于获得注解相关的方法

isAnnotationPresent(Class<? extends Annotation> annotationClass):判断该字节码对象身上是否使用该注解了

getAnnotation(Class<A> annotationClass):获得该字节码对象身上的注解对象

代理Proxy

什么是代理

简单打个比方趴~

目标对象/被代理对象 ------ 房主:真正的租房的方法

代理对象 ------- 黑中介:有租房子的方法(调用房主的租房的方法)

执行代理对象方法的对象 ---- 租房的人

流程:我们要租房----->中介(租房的方法)------>房主(租房的方法)

抽象:调用对象----->代理对象------>目标对象

动态代理就是不用手动编写一个代理对象,不需要一一编写与目标对象相同的方法,这个过程,在运行时的内存中动态生成代理对象。------字节码对象级别的代理对象

动态代理的API

在jdk的API中存在一个Proxy中存在一个生成动态代理的的方法——newProxyInstance

static Object

newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) 

返回值:Object就是代理对象

参数:loader:代表与目标对象相同的类加载器-------目标对象.getClass().getClassLoader()

interfaces:代表与目标对象实现的所有的接口字节码对象数组

h:具体的代理的操作,InvocationHandler接口

注意:JDK的Proxy方式实现的动态代理,目标对象必须有接口,没有接口不能实现jdk版动态代理

实例

public interface TargetInterface {

	public void method1();
	public String method2();
	public int method3(int x);
}

 

public class Target implements TargetInterface{

	@Override
	public void method1() {
		System.out.println("method1 running...");
	}

	@Override
	public String method2() {
		System.out.println("method2 running...");
		return "method2";
	}

	@Override
	public int method3(int x) {
		return x;
	}
	
}

 

public class ProxyTest {

	@Test// JUnit测试注解
	public void test1(){
		//获得动态的代理对象----在运行时 在内存中动态的为Target创建一个虚拟的代理对象
		//objProxy是代理对象 根据参数确定到底是谁的代理对象
		TargetInterface objProxy = (TargetInterface) Proxy.newProxyInstance(
				Target.class.getClassLoader(), //与目标对象相同的类加载器
				new Class[]{TargetInterface.class}, 
				new InvocationHandler() {
					//invoke 代表的是执行代理对象的方法
					@Override
					//method:代表目标对象的方法字节码对象
					//args:代表目标对象的响应的方法的参数
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						System.out.println("目标方法前的逻辑");
						//执行目标对象的方法
						Object invoke = method.invoke(new Target(), args);
						System.out.println("目标方法后的逻辑");
						return invoke;
					}
				}
			);
		
		objProxy.method1();
		String method2 = objProxy.method2();
		System.out.println(method2);
		
	}
	
}

这个阶段的学习暂时告一段落,至于下一阶段的学习emmm

我是小昶,我们开学后见~~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值