在这篇文章里将会谈到“Servlet 发送压缩的 web 页面”和“限制对指定的 web 页面的访问”的设计,如果已经掌握了,可以略过,谢谢。

一、Servlet 发送压缩的 web 页面

    关于压缩的用意,就不去详细阐述了,用一个简单的例子:对于一个28.8kb 的调制解频率的连接,压缩平均用时不到5秒,可不压缩的则需要50秒。

   在java 里实现压缩是一件比较简单的事情,因为所有的逻辑都封装到 java.util.zip 里面的类了。发送压缩的 web 页面过程大致如下:首先,首先 servlet 会检查头字段 Accept-Encoding,判断其实是否包含 gzip 的入口。如果有,则制定 gzip 为 Accept-Encoding 的值,接着使用 GZIPOutputStream 来输出页面(需要记住的是,完成输出后要关闭GZIPOutputStream )。如果没有,则使用常规的 PrintWriter 来输出页面。为了其考虑的完整性,还需要考虑到一个头字段Accept-Encoding,这个头字段可以限制内容的编码。

    现在给出其具体代码的设计:

@WebServlet("/EncodePage")
public class EncodePage extends HttpServlet {
    private static final long serialVersionUID = 1L;
 
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html");
        String encodings = request.getHeader("Accept-Encoding");
        String encodeFlag = request.getParameter("encoding");
        
        String title;
        PrintWriter out;
        
        if (encodings != null && (encodings.indexOf("gzip") != -1) 
                && !"none".equals(encodeFlag)) {
            title = "Page encoded with Gzip";
            OutputStream outTmp = response.getOutputStream();
            out = new PrintWriter(new GZIPOutputStream(outTmp), false);
            response.setHeader("Content-Encoding", "gzip");
        } else {
            title = "Unencoded Page";
            out = response.getWriter();
        }
        out.println("

" + title + "

"
);
        String message = "I am a student from scnu, and I love programmimg"
                + ",and what about you??";
        for(int i = 0; i < 1000;i++){
            out.println(message + "
"
);
        }
        out.println("");
        out.close();
    }
}

二、限制对指定的 web 页面的访问。

   首先说明一下, 这个小东西纯粹是为了娱乐,绝不说明实际情况小会喜用这种机制来控制对指定页面的访问。使用servlet 控制表单的访问,需要程序员稍稍再付出一些,另外在一些简单的应用程序里,http 授权机制的已足矣。接着给出这个 http 授权的基本步骤:

   (1)检查是否存在头字段 Authorization。如果不存在,转到第(2)步。如果存在,则跳过字段“basic”,用base64 编码的剩下的内容。这样会得到一个用户输入的 username:password的字符串,接着检出这个字符串能否与保存的数据匹配,如果匹配,转到指定 web 页面,不匹配,则转到第(2)步。

    (2)返回 401(不授权)响应代码和一个如下格式的头字段:WWW-Authenticate: BASIC realm="some-name"。这个响应命令会让浏览器弹出一个对话框,让用户输入指定的账号和密码,接着就是重新连接。

    先给出运行的效果图:

 Servlet 笔记(二)_第1张图片  Servlet 笔记(二)_第2张图片

    代码设计如下:

@WebServlet(urlPatterns = { "/ProtectedPage" }, 
    initParams = { @WebInitParam(name = "passwordFile", value = "C:\\passwords.properties") })
public class ProtectedPage extends HttpServlet {
    private Properties passwords;
    private String passwordFile;
 
    /**
     * 读取配置文件,初始化passwords
     */
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        try {
            passwordFile = config.getInitParameter("passwordFile");
            passwords = new Properties();
            passwords.load(new FileInputStream(passwordFile));
        } catch (IOException ioe) {
        }
    }
 
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        String authorization = request.getHeader("Authorization");
        if (authorization == null) {
            askForPassword(response);
        } else {
            String userInfo = authorization.substring(6).trim();
            BASE64Decoder decoder = new BASE64Decoder();
            String nameAndPassword = new String(decoder.decodeBuffer(userInfo));
            int index = nameAndPassword.indexOf(":");
            String user = nameAndPassword.substring(0, index);
            String password = nameAndPassword.substring(index + 1);
            String realPassword = passwords.getProperty(user);
            if ((realPassword != null) && (realPassword.equals(password))) {
                String title = "Welcome to the Protected Page";
                out.println("" + "

" + title + "

\n"
                        + "congratulations. you have accessed a\n" + "highly proprietary company document.\n"
                        + "shred or eat all hardcopies before\n" + "going to bed tonight.\n" + "");
            } else {
                askForPassword(response);
            }
        }
    }
 
    // 不存在字段 Authorization 时
    private void askForPassword(HttpServletResponse response) {
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.setHeader("WWW-Authenticate", "basic realm=\"privileged-few\"");
    }
}

    在这个程序里,需要读取C:\\passwords.property文件,如果没有,可以通过如下PasswordBuilder来创建。

public class PasswordBuilder {
    public static void main(String[] args) throws Exception {
        Properties passwords = new Properties();
        passwords.put("admin", "admin");
        passwords.put("user", "123456");
 
        String passwordFile = "C:\\passwords.properties";
        FileOutputStream out = new FileOutputStream(passwordFile);
        passwords.store(out, "Passwords");
    }
}