回 帖 发 新 帖 刷新版面

主题:[讨论]JAVA学习日记

本人在北京传智播客进行精英班的培训,在课余时间整理了下JAVA日记!发到这里!与大家分享!!希望可以帮助些什么!!

1. 同学的一个问题
他用javac(1.4)编译,用java(1.6)运行,出现不支持的类版本错误。我们用javac -version和java -version各看了一下版本,就发现了这个问题。然后查看path环境变量,发现他计算机上安装了oracle,oracle/bin排在了整个path的前面,调整path,让jdk1.6/bin排在最前面即可。
2. 由内存中一切皆二进制引出字符编码的讲解
大陆写的“中”到台湾显示不正常的原理分析,翻译软件的翻译原理,GBK-->“中”-->BIG5。讲解UTF-8编码和unicode编码,ASCII与Unicode码的转换规则,演示记事本显示字符时的趣味问题,分析乱码原因,GB2312码中也包含英文字符,如何识别GB2312码中的英文与汉字。最后课结束时讲了GB18030,如何支持?
3. xml文档中设置encoding属性的重要性
xml文档保存的编码类型和encoding指定的编码方式是两码事,前者表示xml文档内容的编码方式而后者是告诉解析器以什么编码方式来解析xml文档。二者必须一致,否则在浏览器中打开xml文档就会出现问题。默认情况下encoding属性的值是UTF-8。
沈继龙:以为指定了encoding="GBK",那文件就用GBK保存了,这正好理解反了。我是张,我戴顶帽子说明我是张,以便解析软件知道我是谁,如果我戴顶李的帽子,解析软件就认为我是李,显然就出了问题。
4. CDATA区
要小心的是XML文档是通过一个程序生成出来的,如下所示的一个jsp程序,对于用变量生成的信息,
要特别注意加上CDATA区。
<%@page pageEncoding="GBK"%>
<%@page contentType="text/xml;charset=UTF-8"%>
<?xml version="1.0" encoding="UTF-8"?>
<country>
        <name>中国</name>
        <info><![CDATA[${param.info}]]></info>
</country>
这个JSP文件涉及了两个编码:源文件是用什么码写的,程序执行后以什么码输出结果。
为了加深理解处理软件必须文件中的字符编码的情况,又演示了javac编译utf-8源文件的问题。
与CDATA区类似的一个小技巧:
        <%@page pageEncoding="GBK"%>
        <form>
            <input type="hidden" name="email" value="${param.email}"/>
            请输入用户名:<input type="text" name="name" />
        </form>
如果给隐藏字段传递的参数是“zxx" a="b”,那么也会出问题,对于程序生成值时,一定要考虑值的特殊情况。
5. 编码转换
编码转换程序:
        char [] codes = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
        byte b = (byte)Integer.parseInt(args[0]);
        System.out.print(codes[((b>>4) & 0x0f)]);
        System.out.println(codes[(b & 0x0f)]);    
得到字符的big5码
<%@page pageEncoding="GBK"%>
<%@page contentType="text/html;charset=GBK"%>//修改contentType="audio/x-mp3"说明头的作用
<%
    String china="中一二";
    for(int i=0;i<china.length();i++)
    {
        out.println(Integer.toHexString((int)china.charAt(i)));
    }
    System.out.println();
    byte[] bufGBK = china.getBytes("GBK");
    for(int i=0;i<bufGBK.length;i++)
    {
        out.println(Integer.toHexString(bufGBK [i]));
    }
    byte[] buf = china.getBytes("Big5");
    for(int i=0;i<buf.length;i++)
    {
        out.println(Integer.toHexString(buf[i]));
    }
    byte [] buf ={0xa4, 0xa4,0xa4,0x40,0xa4,0x47}
%>
输出big5码给浏览器:
<%
    byte [] buf ={(byte)0xa4, (byte)0xa4,(byte)0xa4,(byte)0x40,(byte)0xa4,(byte)0x47};
    response.getOutputStream().write(buf);
%>
6. 区分中文英文的程序代码
buf[] = new byte[1024];
int len = System.in.read(buf);
boolean halfChinese = false;
for(int i=0;i<len;i++)
{
    if(halfChinese)
    {
        //buf[i-1] + buf[i]合并
        System.out.write('[');
        Systen.out.write(buf[i-1]);
        Systen.out.write(buf[i]);
        System.out.write(']');
        halfChinese = false;
        continue;
    }
    if((buf[i] & 0x80) == 0)
    {
        //为什么必须用write???
        System.out.write('[');
        Systen.out.write(buf[i]);
        System.out.write(']');
    }
    else
    {
        halfChinese = true;
        //等下一个,暂时不处理
        /*
        System.out.write('[');
        Systen.out.write(buf[i++]);
        Systen.out.write(buf[i]);
        System.out.write(']');
        */
    }
}
System.out.write();方法要用flush();刷新缓存,才能正常显示。
我写的代码,但还有地方没弄明白:为什么去掉了if()判断是否有'\r','\n'后,显示的结果不正常。
import java.io.*;
class TestInputChinese {
    public static void main(String[] args) {
        byte[] buf = new byte[1024];
        int len = 0;
        try {
            len = System.in.read(buf);
        }catch(IOException e) {
            e.printStackTrace();
        }
        change(buf, len);
    }
    public static void change(byte[] b, int len) {
        for( int i=0; i<len; i++ ) {
            if(b[i] == '\r' || b[i] == '\n' ) {
                continue;
            }
            if((b[i] & 0x80) == 0 ) {
                System.out.write('[');
                System.out.write(b[i]);
                System.out.write(']');
            } else {
                System.out.write('[');
                System.out.write(b[i++]);
                System.out.write(b[i]);
                System.out.write(']');
            }
        }
        System.out.flush();
    }
}

回复列表 (共23个回复)

11 楼

1. Servlet的注册和运行
在web.xml里面,添加
 <servlet>
        <servlet-name>wzh</servlet-name>
        <servlet-class>MyFirst</servlet-class>
 </servlet>   
 <servlet-mapping>
        <servlet-name>wzh</servlet-name>
        <url-pattern>/first/a.html</url-pattern>
  </servlet-mapping>
<servlet-name>可以随便填写<servlet-class>要与classes文件夹内的.class内的文件同名.在写<url-pattern>的时候要注意目录结构.。里面的/first/a.html是接在当前目录(应用程序的根目录)下的。所以在地址栏中访问时,一定要加上放在webapps里那个目录的名字.如http://localhost:8080/xml/first/a.html
还可以在<servlet>中设置<load-on-startup>元素,该元素的作用是指在web应用启动的时候指定了servlet被加载的顺序,它的值必须是一个整数。如果它的值是一个负整数或是这个元素不存在,那么容器会在该servlet被调用的时候,加载这个servlet 。如果值是正整数或零,容器在配置的时候就加载并初始化这个servlet,容器必须保证值小的先被加载。如果值相等,容器可以自动选择先加载谁。
2. 类装载
如果要想让一个sevlet被多个程序装载,可以把这个servlet放在common里,把原来.class文件打成jar放在lib,原来的.class放在class目录下。因为程序起来后,会自动找上面的类装载器,如果找到,那么就可以使用。所以放在common里就可以实现。程序就算自己有也会向上找,上面的找到了就不会返回来,所以这时如果用程序获得类装载器的名字,那得到的是上面的类装载器的名字。(这和sun公司在servlet规范中的建议是不一样的,Sun建议,如果下面的可以找到servlet则不用再向上找)
3. 模版方法设计模式
下面是一个模板方法设计模式的伪代码
Class abstract BaseServlet
{
service() throws IOException,ServletException
{
    try
    {
        doService()
    }
    catch(SqlException e)
    {
        throw new IOException(e);
    }
}
    public abstract void doSevice();
}
YourServlet extends BaseServlet
{
    public doService()
    {
        ....
    }
}
小知识:
response.getWriter().println();输出流默认是ISO8859-1,如果想输出中文,则必须要显示调用response.setCharacterEncoding("gb2312");

12 楼

1. tomcat类加载器
.class文件中并不是字节码,是类装载器在加载到内存中时将.class文件中的内容转换为字节码。
Class clazz = Class.forName("Student");
//创建出一份Student类的字节码对象
Student st = clazz.new Instance();
//用这份字节码创建出这个对象
System.class和对象.getClass()这两个方法也可以获得一个类字节码,都是由ClassLoader来做的。
tomcat5.5有很多加载器:
server/lib或classes目录,为服务器启动时要加载类的类加载器,这个目录下有Servlet API定义的接口的实现类。
common目录是通用类加载器,应用程序和容器要使用的jar往往都放在该目录下,如果要多个应用程序都能装载某个Servlet,应把Servlet的字节码放到common目录中,但多个应用程序会创建多个此Servlet的对象。
各个web应用程序下的WEB-INF下的classes或lib目录下的是针对单个应用程序的类加载器。
2. JAVA类加载器
根加载器是BootStrap 是由C语言写的,他加载其他加载器
AppClassLoader加载classpath目录存放的类
jdk/jre/lib/ext  java虚拟机的ExtClassLoader类加载器找这个目录
(1)得到类加载器
通过this.getClass().getClassLoader().getClass().getName()就可以得到一个类加载器。
(2)加载一个类的过程
getClass()方法获取一个类的字节码,这个类字节码也是CLASS类的一个对象,类加载器ClassLoader用于将类的字节码加载到内存中,然后再由这个类的字节码来创建这个类的实例。getClassLoader用于返回加载这个类的类加载器。

13 楼

1. tomcat类加载器
.class文件中并不是字节码,是类装载器在加载到内存中时将.class文件中的内容转换为字节码。
Class clazz = Class.forName("Student");
//创建出一份Student类的字节码对象
Student st = clazz.new Instance();
//用这份字节码创建出这个对象
System.class和对象.getClass()这两个方法也可以获得一个类字节码,都是由ClassLoader来做的。
tomcat5.5有很多加载器:
server/lib或classes目录,为服务器启动时要加载类的类加载器,这个目录下有Servlet API定义的接口的实现类。
common目录是通用类加载器,应用程序和容器要使用的jar往往都放在该目录下,如果要多个应用程序都能装载某个Servlet,应把Servlet的字节码放到common目录中,但多个应用程序会创建多个此Servlet的对象。
各个web应用程序下的WEB-INF下的classes或lib目录下的是针对单个应用程序的类加载器。
2. JAVA类加载器
根加载器是BootStrap 是由C语言写的,他加载其他加载器
AppClassLoader加载classpath目录存放的类
jdk/jre/lib/ext  java虚拟机的ExtClassLoader类加载器找这个目录
(1)得到类加载器
通过this.getClass().getClassLoader().getClass().getName()就可以得到一个类加载器。
(2)加载一个类的过程
getClass()方法获取一个类的字节码,这个类字节码也是CLASS类的一个对象,类加载器ClassLoader用于将类的字节码加载到内存中,然后再由这个类的字节码来创建这个类的实例。getClassLoader用于返回加载这个类的类加载器


1. <load-on-startup>元素
<load-on-startup>元素在web应用启动的时候指定了servlet被加载的顺序,它的值必须是一个整数。如果它的值是一个负整数或是这个元素不存在,那么容器会在该servlet被调用的时候,加载这个servlet 。如果值是正整数或零,容器在配置的时候就加载并初始化这个servlet,容器必须保证值小的先被加载。如果值相等,容器可以自动选择先加载谁。
2. ServletContext和ServletConfig的应用
通过ServletConfig获得servlet的名称和配置参数,通过ServletContext获得web服务器程序的名称。Servlet运行于Web应用程序中,而每一个web应用程序对应一个context元素,所以就把servlet运行于的web应用程序称之为ServletContext,这从个名字上就可以知道其作用。
3. 模版方法设计模式的伪代码:
class BaseServlet
{
service() throws IOException,ServletException
{
    try
    {
        doService()
    }
    catch(SqlException e)
    {
        throw new IOException(e);
    }
}
    public abstract void doSevice();
}
YourServlet extends BaseServlet()
{
    public doService()
    {
        ....
    }
}

14 楼


1. tomcat类加载器
.class文件中并不是字节码,是类装载器在加载到内存中时将.class文件中的内容转换为字节码。
Class clazz = Class.forName("Student");
//创建出一份Student类的字节码对象
Student st = clazz.new Instance();
//用这份字节码创建出这个对象
System.class和对象.getClass()这两个方法也可以获得一个类字节码,都是由ClassLoader来做的。
tomcat5.5有很多加载器:
server/lib或classes目录,为服务器启动时要加载类的类加载器,这个目录下有Servlet API定义的接口的实现类。
common目录是通用类加载器,应用程序和容器要使用的jar往往都放在该目录下,如果要多个应用程序都能装载某个Servlet,应把Servlet的字节码放到common目录中,但多个应用程序会创建多个此Servlet的对象。
各个web应用程序下的WEB-INF下的classes或lib目录下的是针对单个应用程序的类加载器。
2. JAVA类加载器
根加载器是BootStrap 是由C语言写的,他加载其他加载器
AppClassLoader加载classpath目录存放的类
jdk/jre/lib/ext  java虚拟机的ExtClassLoader类加载器找这个目录
(1)得到类加载器
通过this.getClass().getClassLoader().getClass().getName()就可以得到一个类加载器。
(2)加载一个类的过程
getClass()方法获取一个类的字节码,这个类字节码也是CLASS类的一个对象,类加载器ClassLoader用于将类的字节码加载到内存中,然后再由这个类的字节码来创建这个类的实例。getClassLoader用于返回加载这个类的类加载器

1.<load-on-startup>元素
<load-on-startup>元素在web应用启动的时候指定了servlet被加载的顺序,它的值必须是一个整数。如果它的值是一个负整数或是这个元素不存在,那么容器会在该servlet被调用的时候,加载这个servlet 。如果值是正整数或零,容器在配置的时候就加载并初始化这个servlet,容器必须保证值小的先被加载。如果值相等,容器可以自动选择先加载谁。
2. ServletContext和ServletConfig的应用
通过ServletConfig获得servlet的名称和配置参数,通过ServletContext获得web服务器程序的名称。Servlet运行于Web应用程序中,而每一个web应用程序对应一个context元素,所以就把servlet运行于的web应用程序称之为ServletContext,这从个名字上就可以知道其作用。
3. 模版方法设计模式的伪代码:
class BaseServlet
{
service() throws IOException,ServletException
{
    try
    {
        doService()
    }
    catch(SqlException e)
    {
        throw new IOException(e);
    }
}
    public abstract void doSevice();
}
YourServlet extends BaseServlet()
{
    public doService()
    {
        ....
    }
}

15 楼


[em11]顶
[em11]顶
[em11]顶
[fly]辛苦![/fly]

16 楼

1. 学习了HTTP信息头,知道了很多文件的类型是如何被服务器识别,并做出相应的反应的。
HTTP消息头
①    通用信息头
即能用于请求消息中,也能用于响应信息中,但与被传输的实体内容没有关系的信息头,如Data,Pragma
主要: Cache-Control , Connection , Data , Pragma , Trailer , Transfer-Encoding , Upgrade
②    请求头
用于在请求消息中向服务器传递附加信息,主要包括客户机可以接受的数据类型,压缩方法,语言,以及客户计算机上保留的Cookie信息和发出该请求的超链接源地址等.
主要: Accept , Accept-Encoding , Accept-Language , Host , 
③    响应头
用于在响应消息中向客户端传递附加信息,包括服务程序的名称,要求客户端进行认证的方式,请求的资源已移动到新地址等.
主要: Location , Server , WWW-Authenticate(认证头)
④  实体头
用做实体内容的元信息,描述了实体内容的属性,包括实体信息的类型,长度,压缩方法,最后一次修改的时间和数据的有效期等.
主要: Content-Encoding , Content-Language , Content-Length , Content-Location , Content-Type
2.Content-Type的作用
服务器告诉浏览器它发送的数据属于什么文件类型,文件类型的定义在web.xml文件中的MIME标签。
并借助text/html和text/plain的对比实验加深印象,前者会让浏览器把接收到的实体内容以HTML格式解析,后者会让浏览器以普通文本解析.
要实现文件下载,我们只需要设置两个特殊的相应头,它们是什么头?
----Content-Type:application/octet-stream 
----Content-Disposition:attachment;filename=aaa.zip
3.Content-Disposition 的作用
当Content-Type 的类型为要下载的类型时 , 这个信息头会告诉浏览器这个文件的名字和类型。
在讲解这个内容时,张老师同时讲出了解决中文文件名乱码的解决方法,能用的是使用getBytes() , 实际上应使用email的附件名编码方法对文件名进行编码,但IE支持这种作法(其它浏览器支持) , 使用javax.mail.internet.*包的MimeUtility.encodeWord("中文.txt")的方法进行编码。
带中文名称的附件文件名到底该如何编写,参看邮件中的中文附件名的形式。
用MimeUtility.decodeText编码中文文件名后,IE浏览器显示不正常,而FireFox中没有问题。
解决中文文件名乱码的几种方式的内部原理:
    //response.setHeader("Content-Type","application/octet-stream");
    //response.setHeader("Content-Disposition","attachment;filename=\"=?gb2312?B?SmF2YcXg0bUudHh0?=\"");
    //response.setHeader("Content-Disposition","attachment;filename="+ MimeUtility.encodeWord("中文.txt"));
        response.setHeader("Content-Disposition",
        new String("attachment;filename=中文.txt".getBytes("GB2312"),"iso8859-1")    
    );
setContentType("text/html;charset=gbk")只对response.getWriter().println输出的实体内容起作用,不对response.setHeader方法输出的内容起作用,response.setHeader方法总是按iso8859-1输出。
4. 由一个具有多个图的网页的访问过程讲解了http 1.0的缺点,讲解了Http 1.1的优点。
    HTTP1.1 支持持久连接
5. tomcat5.5首页已经使用了xhtml,特别如下一段内容:
<style type="text/css">
       /*<![CDATA[*/
        body {
            }
      /*]]>*/
    </style>
首先由xml解析器解析出每个元素的信息,然后由下游程序对每个元素进行处理。重点分析了其中的/*<![CDATA[*/的问题。
6. POST请求方式:
POST /servlets-examples/servlet/RequestParamExample HTTP/1.1
Host:
Content-Type: application/x-www-form-urlencoded
Content-Length: 28
firstname=zxx&lastname=abc
7. 怎么把MimeUtility所属的jar文件安装到当前Web应用程序中
    将JAR文件放在当前WEB应用程序的WEB-INF\lib目录下
8. 下面的代码说明jsp翻译成class时的编码问题。
<%=
    "a中文".length()
%>
为什么上面的输出值为5?改成下面的则输出3
<%@ page pageEncoding="gbk"%>
<%=
    "a中文".length()
%>
---------归根到底是编码的问题 , 上面的代码,因为没有添加该文件的编码说明 , WEB应用程序在将jsp翻译成class文件时 , 把该字符串的内容默认当成了UTF-8翻译,因为一个汉字在UTF-8中占两个字节,长度就变成了5 , 而下面的一个因为加了编码说明 , Tomcat 就把一个汉字当成一个字符来计算,得到结果为3。

17 楼

1. 浏览器会在web.xml中查找<mime-mapping>中<extension>中定义的要浏览的扩展名,再根据<mime-type>中指定的类型打开。
<mime-mapping>
        <extension>abs</extension>
        <mime-type>audio/x-mpeg</mime-type>
</mime-mapping>
2. 用JSP做了几个例子,说明请求头、响应头的作用
(1)Authorization头的例子
 Authorization的作用是当客户端访问受口令保护时,服务器端会发送401状态码和WWW-Authenticate响应头,要求客户机使用Authorization来应答。
<%@ page  pageEncoding="GBK" contentType="text/html;charset=utf-8" import="java.util.*,java.text.*" %>
<%=DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, Locale.CHINA).format(new Date())
%>
<%
    response.setStatus(401);
    response.setHeader("WWW-Authenticate", "Basic realm=\"Tomcat Manager Application\"");
%>
(2)Content-Disposition扩展头的例子
加上Content-Type头就可以实现文件下载。
<%@ page pageEncoding="GBK" contentType="text/html;charset=utf-8" import="java.util.*,java.text.*" %>
<%=DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, Locale.CHINA).format(new Date())
%>
<%
    response.setHeader("Content-Type","video/x-msvideo");
    response.setHeader("Content-Disposition", "attachment;filename=aaa.doc");
%>
Content-Type中指定的类型是当点击保存后,文件的保存类型。
Content-Disposition中指定的类型是文件的扩展名,并且弹出的下载对话框中的文件类型图片是按照文件的扩展名显示的,点保存后,文件以filename的值命名,保存类型以Content中设置的为准。
(4)下载的文件名为中文时乱码的解决办法
如果下载的文件名中有中文那么要怎么修改?
<%@ page pageEncoding="GBK" contentType="text/html;charset=utf-8" import="java.util.*,java.text.*" %>
<%=DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, Locale.CHINA).format(new Date())
%>
<%
    response.setHeader("Content-Type","application/x-cpio");
    //response.setHeader("Content-Disposition", "attchment;filename=\"=?gb2312?B?0MK9qCDOxLG+zsS1tS50eHQ=?=\"");
    response.setHeader("Content-Disposition", new String("attachment;filename=中文.txt".getBytes("gb2312"),"ISO8859-1"));
    //response.setHeader("Content-Disposition","attachment;filename="+ MimeUtility.encodeWord("中文.txt"));
%>
这个是比较流行的方法,但比较正统的是用outlook新建一个带有中文附件的邮件,然后看这个邮件的源代码,找到:
Content-Disposition: attachment;
filename="=?gb2312?B?0MK9qCDOxLG+zsS1tS50eHQ=?="
用这个filename原理上就可以显示中文名附件,但是现在IE并不支持,如果换成FIREFOX就可以正常显示。
filename后面的内容可以用javax.mail.internet*包中有方法可以实现:MimeUtility.encodeWord()
如filename="+ MimeUtility.encodeWord("中文.txt"));
(5)jsp翻译成class时的编码问题
<%=
    "a中文".length()
%>
为什么上面的输出值为5?改成下面的则输出3
<%@ page pageEncoding="gbk"%>
<%=
    "a中文".length()
%>
原因:
因为上面的代码没有添加该文件的编码说明 , WEB应用程序在将jsp翻译成class文件时 , 把该字符串的内容按默认的保存方式指定的编码ASCII码来算的,在UTF-8中,原ASCII字符占一个字节,汉字占两个字节,对应两个字符,长度就变成了5 , 而下面的是GBK编码, 一个汉字和一个英文都对应一个字符,得到结果就为3。
(6)小知识点
referer头是可以让服务器了解和追踪发出本次请求的起源的URL地址。request.getHeader("referer")
xml默认是utf-8编码,JSP默认是ISO8859-1编码。
ContentType中的charset=gbk对头中内容不起作用。它只对response.getwriter().println输出的实体内容起作用。

18 楼

培训日记(缓存问题)

一、servlet的service()方法
回顾Servlet的生命周期,通过查看源代码了解init()及service()方法的设计思想;
问:
(1)我们在编写Servlet类时,为什么不覆盖它的service()方法,通常覆盖doGet()之类的方法?
如果用覆盖servlet的service()方法,那么servlet在处理表单提交时,就会去调用父类的service方法,父类的service方法会根据提交的方式做出判断,然后调用对应的doXX()方法。如果是覆盖doGet()之类的方法,servlet就会根据提交的方式直接调用相应的doXX()方法。
(2)如果要覆盖service()方法,通常会覆盖下列方法中的哪一个方法?
service(HttpServletRequest req, HttpServletResponse resp)
service(ServletRequest req, ServletResponse res)

二、浏览器缓存内幕及解决方案
在下面三种不同的情况下,浏览器的缓存情况不同:
1).Servlet没有覆盖getLastModified方法,响应消息中无LastModified头字段,在浏览器缓存的文档无“上次修改时间”.    
2).有getLastModified方法,响应消息中有LastModified头字段,但返回时间晚于缓存文档“上次修改时间”     
3).有getLastModified方法,响应消息中有LastModified头字段,但返回时间早于等于缓存文档“上次修改时间”    
  后退、前进、转到(手工输入后按回车)    通过超链接访问      刷新
     1)不发请求,直接使用缓存              发出请求           发出请求
     2)不发请求,直接使用缓存              不发请求           发出请求,返回200
     3)不发请求,直接使用缓存               不发请求           发出请求,返回304
2、如何禁止Servlet的缓存?(张老师JavaWeb书第236页)
response.setDateHeader("Expires", 0);
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-cache");
3、如何禁止JSP页面的缓存?
response.setDateHeader("Expires", 0);
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-cache");

<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">

4、如何禁止静态页面的缓存?(张老师JavaWeb书第238页)
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
静态页面被禁止后,刷新浏览器返回304
JSP页面被禁止后,刷新浏览器返回200
三、初始化参数
1、相对于单个Servlet:P178
在web.xml文件中配置
  <servlet>
    <servlet-name>ReadInitParam</servlet-name>
    <servlet-class>servlet.ReadInitParam</servlet-class>
    <init-param>
        <param-name>dbname</param-name>
        <param-value>mysql</param-value>
    </init-param>
  </servlet>
访问方法为:
getServletConfig().getInitParameter("keyname")
2、相对于整个Web应用程序:P201
在web.xml文件中配置
<context-param>
    <param-name>company</param-name>
    <param-value>itcast.cn</param-value>
</context-param>
访问方法为:
getServletContext().getInitParameter("keyname")

四、资源文件(.properties)的访问
1、使用Properties类来访问:
Properties prop = new Properties();

//方法一
//InputStream is = new FileInputStream("db.properties");
//db.properties要放在启动tomcat的bin目录中

//方法二
//InputStream is = new FileInputStream(this.getServletContext().getRealPath("/") + "WEB-INF/classes/config/db.properties");
//db.properties可以放在web工程的任意目录

//方法三
//InputStream is = this.getServletContext().getResourceAsStream("WEB-INF/classes/config/db.properties");
//db.properties可以放在web工程的任意目录,相对于工程的上下文路径

//方法四
//InputStream is = this.getClass().getClassLoader().getResourceAsStream("/config/db.properties");
InputStream is = ReadProp.class.getClassLoader().getResourceAsStream("/config/db.properties");
//db.properties只能放在类路径即classes目录中
prop.load(is);
is.close();
//读取key对应的value
prop.getProperty("keyname")

2、使用ResourceBundle类来访问:
//也只能放在类路径下
ResourceBundle rb = ResourceBundle.getBundle("config/db");
//读取key对应的value
rb.getString("keyname")

[url=http://www.itcast.cn]北京传智播客[/url]

[img]http://photo.store.qq.com/http_imgload.cgi?/rurl2=46675a41541a870fd43f9162c4246b274fdf458903f9caf21ebc557faadcb82617c5b5924664592bce2e9d6b8eabb4e8f5d9e897ff8518650e54ef9f12b7611fec615ad9aca101a872a2adc08ca488405690f9dd[/img]

19 楼

培训日记(路径问题)
一、迭代一个Properties类型对象的几种方法
第一种:
import java.io.*;
import java.util.Enumeration;
import java.util.Properties;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ReadProp extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
    InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
        Properties p = new Properties();
        p.load(is);
        is.close();
        Enumeration e = p.elements();
        while(e.hasMoreElements()) {
            String key = (String)e.nextElement();
            out.println(key + "<br>");
        }
        out.flush();
        out.close();
    }
}
第二种:
Enumeration e1 = p.propertyNames();
        while(e1.hasMoreElements()) {
            String key = (String)e1.nextElement();
            out.println(key + ":" + p.getProperty(key) + "<br>");
        }
第三种:
Enumeration e = p.keys();
        while(e.hasMoreElements()) {
            String key = (String)e.nextElement();
            out.println(key + ":" + p.getProperty(key) + "<br>");
        }
第四种:
Set set = p.keySet();
        Iterator it = set.iterator();
        while(it.hasNext()) {
            String key = (String)it.next();
            out.println(key + "=======" + p.getProperty(key) + "<br>");
        }

第五种
Set set = p.entrySet();
        Iterator it = set.iterator();
        while(it.hasNext()) {
            Map.Entry entry = (Entry) it.next();
            out.println(entry.getKey() + ":::::" + entry.getValue() + "<br>");
        }

二、一个显示所有访问者的IP及访问次数的Servlet
运用的知识点如下:
1、存储IP使用什么类型比较好?这个变量定义在哪里比较好?
2、复习了HashMap的迭代知识
代码如下:
用HashMap统计IP的访问次数
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class IpList extends HttpServlet {
    private Map map = new HashMap();
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        String ip = request.getRemoteAddr();
        int time = 0;
        if(map.containsKey(ip)) {
            time = Integer.parseInt((String) map.get(ip));
        }
        time++;
        map.put(ip, Integer.valueOf(time).toString());
        Set ipset = map.keySet();
        Iterator iter = ipset.iterator();
        while(iter.hasNext()) {
            String ip1 = (String)iter.next();
            out.println(ip1 + ":" + map.get(ip1) + "<br>");
        }
        out.flush();
        out.close();
    }
}
三、servlet的线程安全问题
servlet是多线程的,所以有多个线程访问同一个对象时要考虑线程安全。
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ServletThread extends HttpServlet {
    private int count = 0;
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        synchronized (this) {
            count++;
            try {
                Thread.sleep(500);
            } catch (Exception e) {
                // TODO: handle exception
            }
            System.out.println(count + "访问" + Thread.currentThread());
        }
    }
}
[url=http://www.itcast.cn]北京传智播客JAVA培训[/url]

[img]http://photo.store.qq.com/http_imgload.cgi?/rurl2=46675a41541a870fd43f9162c4246b274fdf458903f9caf21ebc557faadcb82617c5b5924664592bce2e9d6b8eabb4e8f5d9e897ff8518650e54ef9f12b7611fec615ad9aca101a872a2adc08ca488405690f9dd[/img]

20 楼

收藏了

我来回复

您尚未登录,请登录后再回复。点此登录或注册