Servlet, HTTP与JSP相关整理

2019-08-04  本文已影响0人  Roct

Servlet

Servlet的执行过程

浏览器访问路径全流程

Servlet的生命周期

/**
 * creater ruirui.ding
 *
 * @Date: 2019/8/4 11:58
 **/
public class HelloServlet implements Servlet {
    // 出生: (实例化) 第一次访问Servlet会调用构造方法
    public HelloServlet() {
        System.out.println("Hello Servlet");
    }
    // 出生: (实例化) 第一次访问会调用Servlet初始化
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("hello world");
    }
    // 销毁: 程序停止了才会调用
    @Override
    public void destroy() {

    }
    // 服务: 作出相应, 每次访问都会调用Service
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        servletResponse.getWriter().write("hello Servlet");
    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }
    @Override
    public String getServletInfo() {
        return null;
    }

}

Servlet的创建时机

Servlet实现的三种方式

Servlet的继承结构

Servlet的继承结构

Servlet映射细节

规则 意义
url-pattern: *.do 以*.字符串为结尾的请求都可以访问 注:不要加/
url-pattern: /* 任意字符串都可以访问
url-pattern /action/*/action开头的请求都可以访问

多种匹配规则同时存在, 匹配的优先级为

绝对匹配-->  /开头匹配 --> 扩展名方式匹配

ServletContext

Context:上下文
ServletContext: 代表的是整个应用。一个应用只有一个ServletContext对象。是单例对象

作用:

域对象:在一定范围内(当前应用),使多个Servlet共享数据。

常用方法

API 注解
void setAttribute(String name,object value); ServletContext对象的map中添加数据
Object getAttribute(String name); ServletContext对象的map中取数据
void rmoveAttribute(String name); 根据name去移除数据

常用方法示例

@WebServlet("/HelloServlet1")
public class HelloServlet1 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        super.doGet(req, resp);
        // 获取一个应用的servlet上下文
        ServletContext context = this.getServletContext();
        System.out.println("*************:" + context);
        // 往上下文存入数据
        context.setAttribute("name", ".ding");
        // 在上下文取出数据
        String name = (String)context.getAttribute("name");
        System.out.println("name::" + name);
        // 移除name
        context.removeAttribute("name");
        System.out.println("name2" + (String)context.getAttribute("name"));
    }
}

设置/读取ServletContext配置信息

先在web.xml设置ServletContext里设置全局配置

<context-param>
        <param-name>encoding</param-name>
        <param-value>utf8</param-value>
</context-param>
@WebServlet("/HelloServlet1")
public class HelloServlet1 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        // 获取一个应用的servlet上下文
        ServletContext context = this.getServletContext();
        System.out.println("*************:" + context.getInitParameter("encoding")); 
    }
}

获取资源路径

String getRealPath(String path);

相关代码实现

@WebServlet("/HelloServlet1")
public class HelloServlet1 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        // 在Servlet中读取info.properties数据
        String path = this.getServletContext().getRealPath("WEB-INF/" +
                "classes/com/rui/servlet/info.properties");
        System.out.println(path);
        // 创建属性对象
        Properties pro = new Properties();
        // 加载路径下的资源
        pro.load(new FileInputStream(path));
        System.out.println(pro.getProperty("username"));

        //解决乱码
        resp.setHeader("Content-Type", "text/html;charset=utf-8");

        resp.getWriter().write(path);
        resp.getWriter().write("-----");
        resp.getWriter().write(pro.getProperty("username"));
    }
}

在IDEA下如何查看本地资源的路径

本地相对资源的路径

Servlet的转发

将来自HelloServlet1的请求转发到HelloServlet2

@WebServlet("/HelloServlet1")
public class HelloServlet1 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        resp.setHeader("Content-Type", "text/html;charset=utf-8");
        RequestDispatcher rd = req.getRequestDispatcher("/HelloServlet2");
        rd.forward(req, resp);
    }
}
@WebServlet("/HelloServlet2")
public class HelloServlet2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
              throws ServletException, IOException {
        resp.getWriter().write("来自HelloServlet2");
    }
}

HTTP

简介

HTTP协议(HyperText Transfer Protocol,超文本传输协议)是用于从WWW服务器传输超文本到本地浏览器的传输协议。它可以使浏览器更加高效,使网络传输减少。它不仅保证计算机正确快速地传输超文本文档,还确定传输文档中的哪一部分,以及哪部分内容首先显示(如文本先于图形)等。

HTTP请求流程

HTTP请求流程

HTTP的常见请求头

请求头 意义
Accept 浏览器可接受的MIME类型。
Accept-Charset 浏览器可接受的字符集。
Accept-Encoding 浏览器能够进行解码的数据编码方式,比如gzipServlet能够向支持gzip的浏览器返回经gzip编码的HTML页面。许多情形下这可以减少5到10倍的下载时间。
Accept-Language 浏览器所希望的语言种类,当服务器能够提供一种以上的语言版本时要用到。
Authorization 授权信息,通常出现在对服务器发送的WWW-Authenticate头的应答中。
Connection 表示是否需要持久连接。如果Servlet看到这里的值为Keep-Alive或者看到请求使用的是HTTP 1.1HTTP 1.1默认进行持久连接),它就可以利用持久连接的优点,当页面包含多个元素时(例如Applet,图片),显著地减少下载所需要的时间。要实现这一点,Servlet需要在应答中发送一个Content-Length头,最简单的实现方法是:先把内容写入ByteArrayOutputStream,然后在正式写出内容之前计算它的大小。
Content-Length 表示请求消息正文的长度。
Cookie 这是最重要的请求头信息之一
From 请求发送者的email地址,由一些特殊的Web客户程序使用,浏览器不会用到它。
Host 初始URL中的主机和端口。
If-Modified-Since 只有当所请求的内容在指定的日期之后又经过修改才返回它,否则返回304“Not Modified”应答。
Pragma 指定“no-cache”值表示服务器必须返回一个刷新后的文档,即使它是代理服务器而且已经有了页面的本地拷贝。
Referer 包含一个URL,用户从该URL代表的页面出发访问当前请求的页面。
User-Agent 浏览器类型,如果Servlet返回的内容与浏览器类型有关则该值非常有用。

HTTP常见的响应头

Allow 服务器支持哪些请求方法(如GETPOST等)。
Content-Encoding 文档的编码(Encode)方法。只有在解码之后才可以得到Content-Type头指定的内容类型。利用gzip压缩文档能够显著地减少HTML文档的下载时间。JavaGZIPOutputStream可以很方便地进行gzip压缩,但只有Unix上的NetscapeWindows上的IE 4、IE 5才支持它。因此,Servlet应该通过查看Accept-Encoding头(即request.getHeader("Accept-Encoding"))检查浏览器是否支持gzip,为支持gzip的浏览器返回经gzip压缩的HTML页面,为其他浏览器返回普通页面。
Content-Length 表示内容长度。只有当浏览器使用持久HTTP连接时才需要这个数据。如果你想要利用持久连接的优势,可以把输出文档写入 ByteArrayOutputStream,完成后查看其大小,然后把该值放入Content-Length头,最后通过byteArrayStream.writeTo(response.getOutputStream()发送内容。
Content-Type 表示后面的文档属于什么MIME类型。Servlet默认为text/plain,但通常需要显式地指定为text/html。由于经常要设置Content-Type,因此HttpServletResponse提供了一个专用的方法setContentType
Date 当前的GMT时间。你可以用setDateHeader来设置这个头以避免转换时间格式的麻烦。
Expires 应该在什么时候认为文档已经过期,从而不再缓存它?
Last-Modified 文档的最后改动时间。客户可以通过If-Modified-Since请求头提供一个日期,该请求将被视为一个条件GET,只有改动时间迟于指定时间的文档才会返回,否则返回一个304(Not Modified)状态。Last-Modified也可用setDateHeader方法来设置。
Location 表示客户应当到哪里去提取文档。Location通常不是直接设置的,而是通过HttpServletResponse的sendRedirect方法,该方法同时设置状态代码为302
Refresh 表示浏览器应该在多少时间之后刷新文档,以秒计。除了刷新当前文档之外,你还可以通过setHeader("Refresh", "5; URL=http://host/path")让浏览器读取指定的页面。
Server服务器名字 Servlet一般不设置这个值,而是由Web服务器自己设置。
Set-Cookie 设置和页面关联的CookieServlet不应使用response.setHeader("Set-Cookie", ...),而是应使用HttpServletResponse提供的专用方法addCookie
WWW-Authenticate 客户应该在Authorization头中提供什么类型的授权信息?在包含401(Unauthorized)状态行的应答中这个头是必需的。例如,response.setHeader("WWW-Authenticate", "BASIC realm=\"executives\"")

HttpServletResponse

手动实现文件下载

@WebServlet("/HelloServlet1")
public class HelloServlet1 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        String fileName = "六年级上册数学课件-第四单元《比》(回顾整理)|青岛版(2014秋)  " +
                "(共9张PPT).ppt";
        // 下载文件
        String path = "C:/Users/rui/Desktop/" +
                fileName;
        // 获取文件输入流
        FileInputStream fis = new FileInputStream(path);
        // 对文件名进行encode编码
        fileName = URLEncoder.encode(fileName, "UTF-8");
        // 设置文件下载请求头
        resp.setHeader("Content-disposition", "attachment;filename="
                + fileName);
        // 将文件转成二进制数据
        byte [] bs = new byte[1024];
        // 获取输出流
        ServletOutputStream sos = resp.getOutputStream();
        int len = 0;
        while ((len = fis.read(bs)) != -1) {
            sos.write(bs, 0, len);
        }
        // 关闭资源
        fis.close();
    }
}

设置客户端不需要缓存【pass】

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse response) 
            throws ServletException, IOException {
        //浏览器刷新时就不会有缓存
        response.addHeader("Pragma", "no-cache"); 
        response.setHeader("Cache-Control", "no-cache"); 
        response.setHeader("Expires", "0");
        ValidateCode code = new ValidateCode(WIDTH, HEIGHT, 4, 6);
        
        code.write(response.getOutputStream());
}

自动刷新功能

protected void doGet(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        // TODO Auto-generated method stub
        response.setContentType("text/html;charset=UTF-8");
        //response.setHeader("Refresh", "1");//每隔一秒刷新一次
        
        response.setHeader("Refresh", "5;URL=index.html");//5秒后转到另一页面
        response.getWriter().write("注册成功!5秒后会自动跳转到index.html页面");
}

请求重定向

response.sendRedirect()

转发特点:地址栏不会变,客户端发送一次请求

重定向实现

@WebServlet("/HelloServlet1")
public class HelloServlet1 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        resp.sendRedirect("HelloServlet2");
    }
}
@WebServlet("/HelloServlet2")
public class HelloServlet2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        resp.getWriter().write("HelloServlet2" );
    }
}

HttpServletResponse总结

HttpServletRequest

简介

HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,开发人员通过这个对象的方法,可以获得客户这些信息。

获得客户端信息

API 作用
getRequestURL 返回客户端发出请求时的完整URL。
getRequestURI方法 返回请求行中的资源名部分。
getQueryString 方法 返回请求行中的参数部分。
getRemoteAddr方法 返回发出请求的客户机的IP地址
getRemoteHost方法 返回发出请求的客户机的完整主机名
getRemotePort方法 返回客户机所使用的网络端口号
getLocalAddr方法 返回WEB服务器的IP地址。
getLocalName方法 返回WEB服务器的主机名
getMethod 得到客户机请求方式

获得客户端请求头

@WebServlet("/HelloServlet1")
public class HelloServlet1 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        System.out.println(req.getHeader("User-Agent"));
        System.out.println(req.getHeader("Accept"));
    }
}
@WebServlet("/HelloServlet1")
public class HelloServlet1 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        Enumeration<String> e = req.getHeaderNames();
        while(e.hasMoreElements()) {
            String name = e.nextElement();
            System.out.println(name + ":" + req.getHeader(name));
        }
    }
}

OutPut

host:localhost:8080
connection:keep-alive
upgrade-insecure-requests:1
user-agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36
accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
accept-encoding:gzip, deflate, br
accept-language:zh-CN,zh;q=0.9
cookie:JSESSIONID=7BCC931187E41F2598EBE975DDC50F80

获得客户端请求参数(客户端提交的数据)

API 作用
getParameter(name) 获取一个参数的值
getParameterValues(String name) 获取一个参数对应的多个值, 返回一个数组
getParameterNames() 一次性获取所有参数的名字, 返回一个Enumeration
getParameterMap 返回一个Map<String, String[]> , 前面为参数, 后面为参数对应的值, 存在一个数组中.
getInputStream 以字节读取请求参数

HttpRequestServlet应用

@WebServlet("/HelloServlet1")
public class HelloServlet1 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        String userName = req.getParameter("username");
        String password = req.getParameter("password");
        System.out.println(userName + ";" + password);
    }
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/HelloServlet1">
    用户名: <input type="text" name="username"><br>
    密码: <input type="password" name="password"><br>
    <input type="submit" value="登录"></input>
</form>
</body>
</html>

实现请求转发

@WebServlet("/HelloServlet1")
public class HelloServlet1 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {

        req.getRequestDispatcher("/egg.jsp").forward(req,resp);
    }
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<div>hahahhahahahah</div>
</body>
</html>

那么访问HelloServlet1, 就自动转到egg.jsp

重定向机制的运作流程
1、用户在浏览器端输入特定URL,请求访问服务器端的某个组件
2、服务器端的组件返回一个状态码为302的响应结果。
3、当浏览器端接收到这种响应结果后,再立即自动请求访问另一个web组件
4、浏览器端接收到来自另一个web组件的响应结果。

HttpServeltResponse的sendRedirect(String location)用于重定向

转发和重定向的区别

include(), forward(), sendRedirect()的区别

JSP

1. JSP概述

上一篇 下一篇

猜你喜欢

热点阅读