JSP———数据交互【2】

内置对象application

实现用户之间的数据共享

session 对象不同的是,所有客户的 application 对象是相同的一个,即所有的客户共享这个内置的 application 对象

常用方法:

public Enumeration getAttributeNames() 该方法产生一个枚举对象,该枚举对象使用 nextElemets()遍历application 对象所含有的全部对象

public void removeAttribue(String key)从当前 application 对象中删除关键字是 key 的对象。

public String getServletInfo()获取 Servlet 编译器的当前版本的信息。

pageContext    内置对象    代表了JSP页面编译后的内容它封装了对其他8大内置对象的引用!,也就是说,通过pageContext可以获取到其他的8个内置对象

<%
    
        System.out.println(pageContext.getSession());
        System.out.println(pageContext.getRequest());
        System.out.println(pageContext.getResponse());
    
        System.out.println(pageContext.getException());
    
        System.out.println(pageContext.getPage());
        System.out.println(pageContext.getServletConfig());
        System.out.println(pageContext.getServletContext());
        System.out.println(pageContext.getOut());
    
    %>

pageContext是    域对象    ,它代表着当前JSP页面(也就是page!也就是说:pageContext域对象只在page范围内有效,超出了page范围就无效了

三个方法:

  • § setAttribute(String name,Objcet o)
  • § getAttribute(String name)
  • § removeAttribute(String name)
<% pageContext.setAttribute("name", "zhangsan"); %>
<%
   String value = (String) pageContext.getAttribute("name");
     System.out.println(value);
%>

注意pageContext域对象是可以访问requestsessionapplicationpage这几个域对象设置的值的

上面的pageContext默认是page范围的,但pageContext对象重载了set、get、removeAttribute这三个方法

  • getAttribute(String name,int scope)
  • setAttribute(String name,Object value,int scope)
  • removeAttribute(String name,int scope)
  • 多了一个设置域范围的一个参数,如果不指定默认就是page。当然了,pageContext把request、session、application、page这几个域对象封装着了静态变量供我们使用
    • PageContext.APPLICATION_SCOPE
    • PageContext.SESSION_SCOPE
    • PageContext.REQUEST_SCOPE
    • PageContext.PAGE_SCOPE
    • 刚才我们没有使用重载方法的时候,使用pageContext无法获取到request域对象设置的属性现在我们使用重载后的方法就能获取得到
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
      <body>
      <%
        //使用重载的方法获取request域对象的属性
String value = (String) pageContext.getAttribute("name",pageContext.REQUEST_SCOPE);
        System.out.println(value);
    %>
    
    </body>
    </html>

pageContext还有这么一个方法:findAttribute(String name)

该方法会查找各个域的属性,从小到大开始寻找!也就是page—>request->session->application。

<%
    //使用findAttribute查找2.jsp中request域对象的属性
   String value = (String) pageContext.findAttribute("name");
     System.out.println(value);
    %>

 对象的作用域

 

page作用域:

只在本JSP页面范围有效

pageContext.setAttribute(键,值)

pageContext.getAttribute(键)

request作用域内的对象则是与客户端的请求绑定在一起

<%
    String name = "request";
    request.setAttribute("name",name);
    request.getRequestDispatcher("testTwo.jsp").
        forward(request, response);
%>

session作用域:一次会话

 application作用域:整个web应用程序

 

cookie

cookie是Web服务器保存在客户端的一系列文本信息

cookie的

  • 对特定对象的追踪
  • 实现各种个性化服务
  • 简化登录
  • 但安全性能————容易泄露信息

使用:

 常用方法

 

cookie与session的对比

 

 JSP访问数据库

分层实现

数据访问层(DAO)

表示层(JSP) ————非空验证 提示错误信息并保留用户所填写的信息

JavaBean

一辆货车,在java端和web页面进行数据传递的载体

优势

  • 解决代码重复编写,减少代码冗余
  • 功能区分明确 提高了代码的维护性

分类

功能上可以分为 封装数据 封装业务

JSP 页面应当将数据的处理过程指派给一个或几个 beans 来完成,我们只需在 JSP 页面中调用这个 beans即可。不提倡大量的数据处理都用 java 程序片来完成。在 JSP 页面中调用 beans,可有效的分离的静态工作部分和动态工作部分编写 javabeans 就是编写一个 java 的类

工作过程:

当服务器上某个含有 useBean 标签的 JSP 页面被加载执行时,JSP 引擎将首先根 id 的名字,查找 JSP 引擎内置 pageContent 对象中是否含有名字 id和作用域 scope 的对象,如果这个对象存在,JSP 引擎就分配一个这样的对象给客户,这样,客户就获得了一个作用域是 scope、名字是 id beans。如果在 pageContent 中没有查找到指定作用域、名字是 id 的对象,就根据 class 指定的类创建一个名字是 id 对象,即创建了一个名字是 id beans,并添加到 pageContent 内置对象中,并指定该 beans 的作用域是 scope,同时 JSP 引擎分配给客户一个作用域是 scope、名字是 id beans

² scope 取值 page

beans 的有效范围是当前页面,当客户离开这个页面时,JSP 引擎取消分配给该客户的 beans

² scope 取值 session

beans 的有效范围是客户的会话期间,也就是说,如果客户在多个页面中相互连接,每个页面都含有一个 useBeans 标签,这些 useBean 标签中 id 的值相同,并且 scope 的值都是 session,那么,该客户在这些页面得到的 beans 是相同的一个。如果客户在某个页面更改了这个 beans 的属性,其它页面的这个 beans 的属性也将发生同样的变化。当客户关闭浏览器时,JSP 引擎取消分配给客户的 beans

 

² scope 取值 request

beans 的有效范围是 request 期间。客户在网站的 访问期间可能请求过 多个页 面,如果这些页面含有 socope 取值是request useBeans 标签,那么 pageCotent 对象在每个页面分配给客户的 beans 也是互不相同的。JSP 引擎对请求作出响应之后,取消分配给客户的这个 beans

 

² scope 取值 application

所有客户共享这个 beans,如果一个客户改变这个 beans 的某个属性的值,那么所有客户的这个 beans 的属性值都发生了变化。这个 beans 直到服务器关闭才被取消。

注意事项

当使用作用域是 session beans 时,要保证客户端支持 Cooker.

为了使服务器的所有 web 服务目录下的 JSP 页面文件都能使用我们的 beans(假如是Circle.java),我们必须将上面编译通过生成的字节码类文件:Circle.class 拷贝到 JSP 引擎的 classes 文件夹下,即tomcatclasses 下。另外,在使用 beans JSP 页面中,必须有如下的 import 指令:

<@page import= Circle>

特定的写法:

  • 无参的构造函数
  • 成员属性私有化
  • 封装的属性如果需要被外所操作,必须编写public类型的settergetter方法

三个对javabean操作的标签:

(1) jsp:useBean【在JSP页面中查找javaBean对象或者实例化javaBean对象

(2) jsp:setProperty【设置javaBean的属性】

(3) jsp:getProperty【获取javaBean的属性】

<jsp:useBean>标签用于在指定的域范围内查找指定名称的JavaBean对象

1)存在则直接返回该JavaBean对象的引用

2)不存在则实例化一个新的JavaBean对象并将它以指定的名称存储到指定的域范围中

语法:

<jsp:useBean id="实例化对象的名称" class="类的全名" scope="bean 有效范围"/>

或者

<jsp:useBean id="实例化对象的名称" class="类的全名" scope="bean 有效范围">

</jsp:useBean>

举例:

  <body>
    <jsp:useBean id="tom" class="Person" scope="page"/>
    <%
        tom.setName("tom");
        System.out.println(tom.getName());
    %>   
 </body>

person类必须存在一个           空参构造         才能使用<jsp:useBean>标签不然不行

上例等价于:

<body>
     <%
        //new出对象
        Person tom = new Person();
        tom.setName("tom");
        System.out.println(tom.getName());
    %>
</body>

jsp:setProperty  该标签可以设置 beans 的属性值

setProperty标签可以通过 3 种方式设置 beans的属性值

1)将 beans的属性值置为一个表达式的值或字符串

beans 的属性值设置为一个表达式的值:

<jsp:setProperty name= beans的名字property= beans 的属性名 ” value=<%=expression%>/>

beans 的属性值设置为一个字符串:

<jsp:setProperty name= beans 的名字” property= beans 的属性名” value= 字符串/>

(2)通过form表单的参数的值来设置 beans 的相应属性的值,要求表单参数名字必须与 beans 属性的名字相同JSP

引擎会自动将表单中的数据(字符串)转换为 beans 属性的类型。

<jsp:setProperty name= "beans 的名字" property="*" />

该标签不用再具体指定 beans 的属性的值对应的是表单中的哪个参数的值,系统会自动

根据名字进行匹配

(3)通过 request 的参数的值来设置 beans 的相应属性的值,要求 request 参数名字必须与 beans 属性的名字相同

<jsp:setProperty name= "beans的名字" property="属性名" param= “参数名”/>

注:不能在<jsp:setProperty> 中同时使用 value param

jsp:getProperty

该标签可以获得 beans 的属性值,并将这个值用串的形式显示给客户.

语法格式:

<jsp:getProperty name= “beans 的名字” property= “beans 的属性” /><jsp:getProperty name= “beans 的名字” property= “beans 的属性” />

</jsp:getProperty>

举例:

<jsp:getProperty name="person" property="username"/>
    <jsp:getProperty name="person" property="age"/>

序列化

序列化:对象的寿命通常随着生成该对象的程序的终止而终止,有时候需要把在内存中的各种对象的状态(也就是实例变量,不是方法)保存下来,并且可以在需要时再将对象恢复。

总结:

Java 序列化技术可以使你将一个对象的状态写入一个Byte 流里(序列化),并且可以从其它地方把该Byte 流里的数据读出来(反序列化)

用途:

  • 想把的内存中的对象状态保存到一个文件中或者数据库中时候
  • 想把对象通过网络进行传播的时候

如何序列化:

只要一个类实现Serializable接口,那么这个类就可以序列化了

 

例如,有一个 Person类,实现了Serializable接口,那么这个类就可以被序列化了。

class Person implements Serializable{   
    private static final long serialVersionUID = 1L; //下面解释这个是做什么的
    String name;
    int age;
    public Person(String name,int age){
        this.name = name;
        this.age = age;
    }   
    public String toString(){
        return "name:"+name+"	age:"+age;
    }
}

通过ObjectOutputStream writeObject()方法把这个类的对象到一个地方(文件),再通过ObjectInputStream readObject()方法把这个对象出来

 File file = new File("file"+File.separator+"out.txt");
    
    FileOutputStream fos = null;
    try {
        fos = new FileOutputStream(file);
        ObjectOutputStream oos = null;
        try {
            oos = new ObjectOutputStream(fos);
            Person person = new Person("tom", 22);
            System.out.println(person);
            oos.writeObject(person);            //写入对象
            oos.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                oos.close();
            } catch (IOException e) {
                System.out.println("oos关闭失败:"+e.getMessage());
            }
        }
    } catch (FileNotFoundException e) {
        System.out.println("找不到文件:"+e.getMessage());
    } finally{
        try {
            fos.close();
        } catch (IOException e) {
            System.out.println("fos关闭失败:"+e.getMessage());
        }
    }
                            
    FileInputStream fis = null;
    try {
        fis = new FileInputStream(file);
        ObjectInputStream ois = null;
        try {
            ois = new ObjectInputStream(fis);
            try {
                Person person = (Person)ois.readObject();   //读出对象
                System.out.println(person);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } 
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                ois.close();
            } catch (IOException e) {
                System.out.println("ois关闭失败:"+e.getMessage());
            }
        }
    } catch (FileNotFoundException e) {
        System.out.println("找不到文件:"+e.getMessage());
    } finally{
        try {
            fis.close();
        } catch (IOException e) {
            System.out.println("fis关闭失败:"+e.getMessage());
        }
}

输出结果为:

name:tom    age:22

name:tom    age:22

serialVersionUID ,实现了Serializable接口之后,Eclipse就会提示你增加一个 serialVersionUID,虽然不加的话上述程序依然能够正常运行。

序列化 ID 在 Eclipse 下提供了两种生成策略

  • 一个是固定的 1L
  • 一个是随机生成一个不重复的 long 类型数据(实际上是使用 JDK 工具,根据类名、接口名、成员方法及属性等来生成)

上面程序中,输出对象和读入对象使用的是同一个Person类。

如果是通过网络传输的话,如果Person类的serialVersionUID不一致,那么反序列化就不能正常进行。例如在客户端A中Person类的serialVersionUID=1L,而在客户端B中Person类的serialVersionUID=2L 那么就不能重构这个Person对象。

 

如果没有特殊需求的话,使用用默认的 1L 就可以,这样可以确保代码一致时反序列化成功。那么随机生成的序列化 ID 有什么作用呢,有些时候,通过改变序列化 ID 可以用来限制某些用户的使用。

原文地址:https://www.cnblogs.com/expedition/p/11202702.html