Java基础ArrayList、Servlet与Filter

一、技术分享

迭代器(Iterator

  迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构。迭代器通常被称为轻量级对象,因为创建它的代价小。

Java中的Iterator功能比较简单,并且只能单向移动:

(1) 使用方法iterator()要求容器返回一个Iterator。第一次调用Iteratornext()方法时,它返回序列的第一个元素。注意:iterator()方法是java.lang.Iterable接口,Collection继承。

(2) 使用next()获得序列中的下一个元素。

(3) 使用hasNext()检查序列中是否还有元素。

(4) 使用remove()将迭代器新返回的元素删除。

IteratorJava迭代器最简单的实现,为List设计的ListIterator具有更多的功能,它可以从两个方向遍历List,也可以从List中插入和删除元素。

迭代器应用:
 list l = new ArrayList();
 l.add("aa");
 l.add("bb");
 l.add("cc");
 for (Iterator iter = l.iterator(); iter.hasNext();) {
  String str = (String)iter.next();
  System.out.println(str);
 }
 /*迭代器用于while循环
 Iterator iter = l.iterator();
 while(iter.hasNext()){
  String str = (String) iter.next();
  System.out.println(str);
 }
 */

 ArrayList

1、什么是ArrayList 
ArrayList就是传说中的动态数组,用MSDN中的说法,就是Array的复杂版本,它提供了如下一些好处: 
动态的增加和减少元素 
实现了ICollectionIList接口 
灵活的设置数组的大小

2、如何使用ArrayList 
最简单的例子: 
ArrayList List = new ArrayList(); 
for( int i=0;i <10;i++ ) //给数组增加10Int元素 
List.Add(i); 
//..程序做一些处理 
List.RemoveAt(5);//将第6个元素移除 
for( int i=0;i <3;i++ ) //再增加3个元素 
List.Add(i+20); 
Int32[] values = (Int32[])List.ToArray(typeof(Int32));//返回ArrayList包含的数组

这是一个简单的例子,虽然没有包含ArrayList所有的方法,但是可以反映出ArrayList最常用的用法

3ArrayList重要的方法和属性 
1)构造器 
ArrayList提供了三个构造器: 
public ArrayList(); 
默认的构造器,将会以默认(16)的大小来初始化内部的数组 
public ArrayList(ICollection); 
用一个ICollection对象来构造,并将该集合的元素添加到ArrayList 
public ArrayList(int); 
用指定的大小来初始化内部的数组

2IsSynchronized属性和ArrayList.Synchronized方法 
IsSynchronized属性指示当前的ArrayList实例是否支持线程同步,而ArrayList.Synchronized静态方法则会返回一个ArrayList的线程同步的封装。 
如果使用非线程同步的实例,那么在多线程访问的时候,需要自己手动调用lock来保持线程同步,例如: 
ArrayList list = new ArrayList(); 
//... 
lock( list.SyncRoot ) //ArrayList为非线程包装的时候,SyncRoot属性其实就是它自己,但是为了满足ICollectionSyncRoot定义,这里还是使用SyncRoot来保持源代码的规范性 

list.Add( “Add a Item” ); 
}

如果使用ArrayList.Synchronized方法返回的实例,那么就不用考虑线程同步的问题,这个实例本身就是线程安全的,实际上ArrayList内部实现了一个保证线程同步的内部类,ArrayList.Synchronized返回的就是这个类的实例,它里面的每个属性都是用了lock关键字来保证线程同步。

3Count属性和Capacity属性 
Count属性是目前ArrayList包含的元素的数量,这个属性是只读的。 
Capacity属性是目前ArrayList能够包含的最大数量,可以手动的设置这个属性,但是当设置为小于Count值的时候会引发一个异常。

4AddAddRangeRemoveRemoveAtRemoveRangeInsertInsertRange 
这几个方法比较类似 
Add方法用于添加一个元素到当前列表的末尾 
AddRange方法用于添加一批元素到当前列表的末尾 
Remove方法用于删除一个元素,通过元素本身的引用来删除 
RemoveAt方法用于删除一个元素,通过索引值来删除 
RemoveRange用于删除一批元素,通过指定开始的索引和删除的数量来删除 
Insert用于添加一个元素到指定位置,列表后面的元素依次往后移动 
InsertRange用于从指定位置开始添加一批元素,列表后面的元素依次往后移动

二、转发和重定向

if (username.equals("yangmin")&&password.equals("123456")) {

   Java基础ArrayList、Servlet与Filter

 //演示转发请求

request.getRequestDispatcher("/success.jsp").forward(request,response);

//通过请求request获取请求转发器

//在请求转发器中设置要转发的位置

//调用请求转发器的forward()方法进行转发

//转发时,把request和response传递给下一个页面(ServletJSP)

//转发 成功时,响应状态码通常是200

//转发时,浏览器不知道最终是哪个页面(地址)返回了响应

//经常表现 为浏览器的地址不变化或者与真实地址不同

}else {

//演示重定向【响应】

response.sendRedirect(request.getContextPath() +"/fail.jsp");

//通过response的sendRedirect()方法发送一个重定向响应

//sendRedirect方法会把响应状态设置为301、302

//还会添加Location头,Location头的值就是参数指定的重定向的地址

//重定向成功时,响应状态码为301(永久地移动到其他位置)、302(临时重定向到一个位置)

//浏览器的地址栏会变化,能看到最终是哪个页面(servletjsp)返回了HTML

}

三、如何附加Tomcat源代码

   方法一、

      随便找一个Servlet类,按F3找它的定义,在弹出的页面上点击“Attach Source”按钮,在弹出的按钮上选择源代码所在的位置即可(通常选择external files

 方法二、

     在项目视图java Resources里面的Libraries找到Apache Tomcat展开,找到servlet-api.jar右键properties,属性,java Source Attachment

选择源代码位置

 Java基础ArrayList、Servlet与Filter

四、Servlet 接口

   接口定义

       关键词:interface

       java中,接口是一种特殊类型

       可以在接口中声明一些属性和方法

       声明的方法可以不实现(类似于抽象方法)

  

接口的实现

      其他类可以选择实现某个接口,或者某一些接口

      格式:    implements 接口名1,接口名2,接口名3.....

      实现接口通常意味着要实现接口规定的方法和属性

接口对于程序设计的意义

    1》接口是给设计师使用的工具

    2》目的是规范程序代码,保证编码者实现统一设计意图

       (不实现接口指定的方法,或者方法签名走样就会报错)

3》接口是一个约定,方便双方或多方合作

可以使各方写的类能够相互找到并调用

比如Tomcat是一种通用的网络程序,它只能处理网络和协议的功能

    但是不懂客户的业务逻辑

    此时就需要第三方开发者实现具体的业务逻辑

    实现之后Tomcat怎么调用开发者实现的方法呢?

    解决的方法就是大家商量并定义一个接口

    开发者实现这个接口

 Tomcat调用这个接口

 

注意:继承只能写一个,因为java是单继承的,但是可以实现多个接口

 

Servlet

  1. 是一个接口

  2. 是开发者和Tomcat的约定

  3. init                  初始化Servlet

  4. getServletConfig      返回配置信息

  5. getServletInfo        返回描述 信息

  6. service                处理请求的一手方法

  7. destory                 销毁

 

 

获取协议

String protocol = req.getProtocol();

 

HttpServlet

     继承自 -->GenericServlet-->实现了Servlet, ServletConfig,java.io.Serializable接口

 

      HttpServlet是抽象类

           它实现了基本的HTTP协议

               支持GETHEADTRACEPUTPOSTOPTIONSDELETE

                GET    获取资源

                POST    新增资源

                PUT     修改资源

                DELETE   删除资源

            基本实现了对资源的增删改查操作

 

      GET请求支持If-Modified-Sence缓存检查机制(如果有缓存状态码会使304

 Java基础ArrayList、Servlet与Filter

      Head不会返回响应体

      TRACE 将请求头信息收集到响应体中返回

      OPTIONS  返回了所支持的请求方法(子类实现几个doXXX就返回几个doXXX

其他请求默认返回Not_Alloweed,所以子类实现相应方法时

       不用调用super.doXXX()

 

     service 方法会检查请求报文中的请求方法   request.getMethod()

       根据请求 方法将请求转发给doXXX方法处理

       所以service方法只是简单实现了调度作用

 

GenericServlet  几乎什么都没干

 

创建servlet时对话框

 Java基础ArrayList、Servlet与Filter

Name  --><servlet-name>

Description --> <description> Servlet 处理什么请求、特殊注意事项

Initialization Parameters  --> <init-param> 传入Servlet类的参数

URL mappings  -->  <url-pattern>  映射到Servlet类的URL可以指定多个

 

 

 

<url-pattern>的几种写法

     精确匹配    /api/user/login ,      /admin/user

     后缀名       *.jsp       *.action      *.do

     路径        /admin/*     凡是/admin/开头的都匹配

                /*     所有请求

      

     缺省     /     当其他匹配没有成功时,交给这个映射处理

      

 

注意:每一个服务都是由一个引擎和连接器组成的

 

 

应用路径

     一个应用对应一个Dynamic  Web  Project

       应用路径不是固定的

          在开发阶段,通过Eclipse可以改变它,Context root

          在生产环境,由部署位置或配置决定

所以应用路径在源代码(包括JSPServlet)中不能写死!!

 

 

如果在jsp中,优先使用<c:url value =“/login”/>

如果在java代码中(Servlet)中

    使用request.getContextPath()获取

 

 

五、Session

session的工作原理

1)当一个session第一次被启用时,一个唯一的标识被存储于本地的cookie中。

2)首先使用session_start()函数,PHPsession仓库中加载已经存储的session变量。

3)当执行PHP脚本时,通过使用session_register()函数注册session变量。

4)当PHP脚本执行结束时,未被销毁的session变量会被自动保存在本地一定路径下的session库中,这个路径可以通过php.ini文件中的session.save_path指定,下次浏览网页时可以加载使用。


Session图解

Java基础ArrayList、Servlet与Filter

Session 是一个跨页(Servletjsp)面的数据共享机制

Session默认存储在内存中。当应用分布式部署到多台服务器,首先要解决的就是Session问题

                 

Session 通过javax.servlet.http.HttpSession实现

常用的方法

     1》setAttribute(key,value)    把数据(基本类型或对象)存储到session中

   Java基础ArrayList、Servlet与Filter

    

   2》getAttribute(key) 获取session值,返回类型是Object

强制转换后才可以方便使用

   Java基础ArrayList、Servlet与Filter

3removeAttributekey)   删除指定的session

 Java基础ArrayList、Servlet与Filter

4invalidate()            清除所有的session(让所有的session值都失效)

      Java基础ArrayList、Servlet与Filter

在JSP中获取session

      方法1:使用<% session.getAttribute(key)  %>   JSP代码块

                  <%%>代码块,它可以让你把java代码和html混写在一块

                  Session内置对象,可以在页面上直接通过session对象访问session

     方法2:使用EL表达式   ${sessionScope.key}

               EL表达式是为了简化对内置对象中的数据的访问、

                JSP有九大内置对象,四大作用域

关于九大内置对象,四大作用域的详解

request           请求对象             类型javax.servlet.ServletRequest       作用域Request

response          响应对象              类型javax.servlet.SrvletResponse        作用域Page

pageContext       页面上下文对象        类型javax.servlet.jsp.PageContext      作用域Page

session           会话对象              类型javax.servlet.http.HttpSession      作用域Session

application       应用程序对象          类型javax.servlet.ServletContext        作用域Application

out               输出对象              类型javax.servlet.jsp.JspWriter        作用域Page

config            配置对象              类型javax.servlet.ServletConfig        作用域Page

page              页面对象              类型javax.lang.Object                  作用域Page

exception         例外对象              类型javax.lang.Throwable                作用域page

exception” 对象则代表了JSP文件运行时所产生的例外对象,此对象不能在一般JSP文件中直接使用,而只能在使用了“<%@ page isErrorPage="true "%>”的JSP文件中使用。

何为作用域

  先让我们看看效果:

  大概流程是这样的,我们访问index.jsp的时候,分别对pageContext, request, session,application四个作用域中的变量进行累加。(当然先判断这个变量是不是存在,如果变量不存在,则要把变量初始化成1)。计算完成后就从index.jsp执行forward跳转到test.jsp。在test.jsp里再进行一次累加,然后显示出这四个整数来。

  从显示的结果来看,我们可以直观的得出结论:

page里的变量没法从index.jsp传递到test.jsp。只要页面跳转了,它们就不见了。

request里的变量可以跨越forward前后的两页。但是只要刷新页面,它们就重新计算了。

sessionapplication里的变量一直在累加,开始还看不出区别,只要关闭浏览器,再次重启浏览器访问这页,session里的变量就重新计算了。

    application里的变量一直在累加,除非你重启tomcat,否则它会一直变大。

作用域规定的是变量的有效期限

  如果把变量放到pageContext里,就说明它的作用域是page,它的有效范围只在当前jsp页面里。

  从把变量放到pageContext开始,到jsp页面结束,你都可以使用这个变量。

  如果把变量放到request里,就说明它的作用域是request,它的有效范围是当前请求周期。

  所谓请求周期,就是指从http请求发起,到服务器处理结束,返回响应的整个过程。在这个过程中可能使用forward的方式跳转了多个jsp页面,在这些页面里你都可以使用这个变量。

  如果把变量放到session里,就说明它的作用域是session,它的有效范围是当前会话。

  所谓当前会话,就是指从用户打开浏览器开始,到用户关闭浏览器这中间的过程。这个过程可能包含多个请求响应。也就是说,只要用户不关浏览器,服务器就有办法知道这些请求是一个人发起的,整个过程被称为一个会话(session),而放到会话中的变量,就可以在当前会话的所有请求里使用。

  如果把变量放到application里,就说明它的作用域是application,它的有效范围是整个应用。

  整个应用是指从应用启动,到应用结束。我们没有说“从服务器启动,到服务器关闭”,是因为一个服务器可能部署多个应用,当然你关闭了服务器,就会把上面所有的应用都关闭了。

application作用域里的变量,它们的存活时间是最长的,如果不进行手工删除,它们就一直可以使用。

与上述三个不同的是,application里的变量可以被所有用户共用。如果用户甲的操作修改了application中的变量,用户乙访问时得到的是修改后的值。这在其他scope中都是不会发生的,page, request,session都是完全隔离的,无论如何修改都不会影响其他人的数据。

六、Sessionld

      Session.getId()   可以获取SessionId

      SessionId是一个随机字符串(随机数)

      每次会话使用一个SessionId

 Java基础ArrayList、Servlet与Filter

在用户访问服务器的过程中,服务器会在某一次响应中通过Set-Cookie头向浏览器发送一个JSESSIONID。浏览器接到这个Cookie之后,会将之存储下来。以后每一次请求服务器时,都会通过Cookie头携带这个JSESSIONID

    

     服务器通过JSESSIONID区分不同的用户

     

而且服务器端Session数据也被JSESSIONID分成不同的区域

  

通过session.setAttribute()getAttribute等方法操作Session数据时,都只会在当前JSESSIONID关联的区域内操作。即,每个用户只能操作自己的Session区域

Cookie机制

      服务器通过Set-Cookie响应头可以向浏览器设置Cookie

      浏览器会将收到的Cookie保存下来

      以后每次请求时都很通过Cookie头将Cookie发给服务器

Cookie可以设置保存时间(可以使绝对时间,也可是在浏览器关闭时清除)

Cookie可以设置域名(在本域名中有效,在其他域名中无法获取)-----Cookie不能跨域

Cookie可以设置路径(在本路径有效,在其他路径中无法获取)

Cookie可以区分协议,(可以设置Cookie只在https/http的协议中能获取)

如果浏览器不支持CookieSession难道就没法用了

浏览器不支持Cookie,或者程序员不选择通过Cookie保存JSESSIONID

可以通过URL夹带JSESSIONID


七、Filter    

Filter作用

      Filter  可以在请求处理之前以及请求处理之后对请求或响应进行限制、加工、装换

      比如:登录保护、保存日志、转换编码、业务统计、响应格式转换等.....

Filter是一个接口

     三个方法:

       1>  init        初始化

       2>  doFilter     执行过滤

       3>  destory     销毁

   

Filter Servlet组成了一个链条chain

     多个Filter时,谁的<filter-mapping>web.xml的前面谁先执行

      如果使用注解的话,按照名字的字母排序

通过Filter实现登录保护(用户身份验证)

     登录叫身份认证

      与权限相关的叫用户授权

步骤:

 创建过滤器

     在过滤器的前处理部分检查session中是否有用户数据

      没有的话就是没有登录、

        重定向到登录页

         Return   停止后续处理

        有数据就是已经登录

          调用chain.doFilter继续处理

      

       退出的实现

              创建LogoutServlet

                   doGet方法中

                       清除session数据

                       重定向的登录页