JavaWeb学习第六章——Servlet

目录

Servlet技术

Servlet实现

ServletConfig类

​ServletContext类

HTTP 协议

请求的HTTP协议格式

HttpServletRequest类

HttpServletResponse类


Servlet技术

1. Servlet JavaEE 规范之一。javaEE体系结构:13种核心技术规范
2.Servlet是 JavaWeb 三大组件之一,三大组件分别是: Servlet 程序、 Filter 过滤器、 Listener 监听器。
3.Servlet 是运行在服务器上的一个 java 小程序, 它可以接收客户端发送过来的请求,并响应数据给客户端。

Servlet实现

手动实现 Servlet 程序
1、编写一个类去实现Servlet 接口
2、实现 service方法 ,处理请求,并响应数据
3、到web.xml 中配置 servlet 程序的访问地址(servlet运行在服务器上,需要地址与之对应进行访问)
Servlet程序的示例代码:
public class HelloServlet implements Servlet {//实现servlet接口
    ... ...

    //service方法是专门用来处理请求和响应的
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("Hello Servlet 被访问了");
    }
}

web.xml中的配置: 


<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- servlet标签给Tomcat配置Servlet程序 -->
<servlet>
    <!--servlet-name标签给Servlet程序起一个别名(一般是类名) -->
    <servlet-name>HelloServlet</servlet-name>
    <!--servlet-class是Servlet程序的全类名-->
    <servlet-class>com.atguigu.servlet.HelloServlet</servlet-class>
</servlet>

<!--servlet-mapping标签给servlet程序配置访问地址-->
<servlet-mapping>
    <!--servlet-name标签的作用是告诉服务器,当前配置的访问地址给哪个Servlet程序使用-->
    <servlet-name>HelloServlet</servlet-name>
    <!--url-pattern标签配置访问地址
    /斜杠在服务器解析的时候,表示地址为:http://ip:port/工程路径
    /hello表示地址为:http://ip:port/工程路径/hello -->
    <url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>

 常见的错误1:url-pattern中配置的路径没有以斜杠打头。

 常见错误 2:servlet-name配置的值不存在:

常见错误 3:servlet-class 标签的全类名配置错误:

url地址到Servlet程序的访问过程

通过资源路径查找xml中对应的配置地址,通过配置地址找到对应的servlet程序,通过servlet程序名找到全类名,运行类并执行方法。

Servlet的生命周期

1、执行Servlet构造器方法
2、执行init初始化方法

第一、二步在第一次访问的时候创建Servlet程序会调用。

3、执行service方法。第三步,每次访问都会调用。

4、执行destroy销毁方法。第四步,在web工程停止的时候调用

public class HelloServlet implements Servlet {
 public HelloServlet() {
        System.out.println("1 构造器方法");
    }

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("2 init初始化方法");
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("3 service === Hello Servlet 被访问了");
    }

        @Override
    public void destroy() {
        System.out.println("4 . destroy销毁方法");
    }
}
}

GETPOST请求的分发处理

根据service方法中获取请求的方式(post/get)调用不同的功能方法。使用HttpServletRequest中的getMethod方法获取请求方式。

public class HelloServlet implements Servlet {
    //service方法是专门用来处理请求和响应的
    @Override
    //方法声明的形参类型为父类类型,可以使用子类的对象作为实参调用该方法(子类的对象传递给父类的参数)
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
    System.out.println("3 service === Hello Servlet 被访问了");
    /**
    *多态性,内存中实际加载了子类特有的属性和方法,但是由于变量声明为父类类型,导致编译时,只能调用父类中声明的属性和方法。子类特有的属性和方法不能调用。向下转型调用子类特有的属性和方法?**/
    HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
    // 获取请求的方式
    String method = httpServletRequest.getMethod();
    if ("GET".equals(method)) {
        doGet();
    } else if ("POST".equals(method)) {
        doPost();
    }
}

    //做get请求的操作
    public void doGet(){
        System.out.println("get 请求");
        System.out.println("get 请求");
    }
    //做post 请求的操作
    public void doPost(){
        System.out.println("post 请求");
        System.out.println("post 请求");
    }
}
通过继承 HttpServlet 实现 Servlet 程序
一般在实际项目开发中,很少用实现servlet接口的方式实现servlet程序。都是 使用继承HttpServlet类的方式去实现Servlet程序
1、编写一个类去继承HttpServlet
2、根据业务需要重写doGet doPost 方法
3、到web.xml 中的配置 Servlet 程序的访问地址
Servlet 类的代码:
public class HelloServlet2 extends HttpServlet {

    //doGet()在get请求的时候调用
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
IOException {
    System.out.println("HelloServlet2 的 doGet 方法");
}

    //doPost()在post请求的时候调用
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
IOException {
    System.out.println("HelloServlet2 的 doPost 方法");
    }
}
<servlet>
    <servlet-name>HelloServlet2</servlet-name>
    <servlet-class>com.atguigu.servlet.HelloServlet2</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>HelloServlet2</servlet-name>
    <url-pattern>/hello2</url-pattern>
</servlet-mapping>

使用IDEA创建Servlet程序

使用idea工具直接生成类和配置,更加便捷

菜单:new ->Servlet 程序

配置Servlet的信息:

Servlet类的继承体系

 源代码参考

servlet

public interface Servlet {
    void init(ServletConfig var1) throws ServletException;

    ServletConfig getServletConfig();

    void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;

    String getServletInfo();

    void destroy();
}

GenericServlet

public abstract class GenericServlet implements Servlet, ServletConfig, Serializable {
    private static final long serialVersionUID = 1L;
    private transient ServletConfig config;

    public GenericServlet() {
    }

    public void destroy() {
    }

    public String getInitParameter(String name) {
        return this.getServletConfig().getInitParameter(name);
    }

    public Enumeration<String> getInitParameterNames() {
        return this.getServletConfig().getInitParameterNames();
    }

    public ServletConfig getServletConfig() {
        return this.config;
    }

    public ServletContext getServletContext() {
        return this.getServletConfig().getServletContext();
    }

    public String getServletInfo() {
        return "";
    }

    public void init(ServletConfig config) throws ServletException {
        this.config = config;
        this.init();
    }

    public void init() throws ServletException {
    }

    public void log(String msg) {
        this.getServletContext().log(this.getServletName() + ": " + msg);
    }

    public void log(String message, Throwable t) {
        this.getServletContext().log(this.getServletName() + ": " + message, t);
    }

    public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;

    public String getServletName() {
        return this.config.getServletName();
    }
}

 HttpServlet

public abstract class HttpServlet extends GenericServlet {
    private static final long serialVersionUID = 1L;
    private static final String METHOD_DELETE = "DELETE";
    private static final String METHOD_HEAD = "HEAD";
    private static final String METHOD_GET = "GET";
    private static final String METHOD_OPTIONS = "OPTIONS";
    private static final String METHOD_POST = "POST";
    private static final String METHOD_PUT = "PUT";
    private static final String METHOD_TRACE = "TRACE";
    private static final String HEADER_IFMODSINCE = "If-Modified-Since";
    private static final String HEADER_LASTMOD = "Last-Modified";
    private static final String LSTRING_FILE = "javax.servlet.http.LocalStrings";
    private static final ResourceBundle lStrings = ResourceBundle.getBundle("javax.servlet.http.LocalStrings");

    public HttpServlet() {
    }

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String protocol = req.getProtocol();
        String msg = lStrings.getString("http.method_get_not_supported");
        if (protocol.endsWith("1.1")) {
            resp.sendError(405, msg);
        } else {
            resp.sendError(400, msg);
        }

    }

    protected long getLastModified(HttpServletRequest req) {
        return -1L;
    }

    protected void doHead(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        if (DispatcherType.INCLUDE.equals(req.getDispatcherType())) {
            this.doGet(req, resp);
        } else {
            NoBodyResponse response = new NoBodyResponse(resp);
            this.doGet(req, response);
            response.setContentLength();
        }

    }

    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String protocol = req.getProtocol();
        String msg = lStrings.getString("http.method_post_not_supported");
        if (protocol.endsWith("1.1")) {
            resp.sendError(405, msg);
        } else {
            resp.sendError(400, msg);
        }

    }

    protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String protocol = req.getProtocol();
        String msg = lStrings.getString("http.method_put_not_supported");
        if (protocol.endsWith("1.1")) {
            resp.sendError(405, msg);
        } else {
            resp.sendError(400, msg);
        }

    }

    protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String protocol = req.getProtocol();
        String msg = lStrings.getString("http.method_delete_not_supported");
        if (protocol.endsWith("1.1")) {
            resp.sendError(405, msg);
        } else {
            resp.sendError(400, msg);
        }

    }

    private static Method[] getAllDeclaredMethods(Class<?> c) {
        if (c.equals(HttpServlet.class)) {
            return null;
        } else {
            Method[] parentMethods = getAllDeclaredMethods(c.getSuperclass());
            Method[] thisMethods = c.getDeclaredMethods();
            if (parentMethods != null && parentMethods.length > 0) {
                Method[] allMethods = new Method[parentMethods.length + thisMethods.length];
                System.arraycopy(parentMethods, 0, allMethods, 0, parentMethods.length);
                System.arraycopy(thisMethods, 0, allMethods, parentMethods.length, thisMethods.length);
                thisMethods = allMethods;
            }

            return thisMethods;
        }
    }

    protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Method[] methods = getAllDeclaredMethods(this.getClass());
        boolean ALLOW_GET = false;
        boolean ALLOW_HEAD = false;
        boolean ALLOW_POST = false;
        boolean ALLOW_PUT = false;
        boolean ALLOW_DELETE = false;
        boolean ALLOW_TRACE = true;
        boolean ALLOW_OPTIONS = true;
        Class clazz = null;

        try {
            clazz = Class.forName("org.apache.catalina.connector.RequestFacade");
            Method getAllowTrace = clazz.getMethod("getAllowTrace", (Class[])null);
            ALLOW_TRACE = (Boolean)getAllowTrace.invoke(req, (Object[])null);
        } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | ClassNotFoundException var14) {
        }

        for(int i = 0; i < methods.length; ++i) {
            Method m = methods[i];
            if (m.getName().equals("doGet")) {
                ALLOW_GET = true;
                ALLOW_HEAD = true;
            }

            if (m.getName().equals("doPost")) {
                ALLOW_POST = true;
            }

            if (m.getName().equals("doPut")) {
                ALLOW_PUT = true;
            }

            if (m.getName().equals("doDelete")) {
                ALLOW_DELETE = true;
            }
        }

        String allow = null;
        if (ALLOW_GET) {
            allow = "GET";
        }

        if (ALLOW_HEAD) {
            if (allow == null) {
                allow = "HEAD";
            } else {
                allow = allow + ", HEAD";
            }
        }

        if (ALLOW_POST) {
            if (allow == null) {
                allow = "POST";
            } else {
                allow = allow + ", POST";
            }
        }

        if (ALLOW_PUT) {
            if (allow == null) {
                allow = "PUT";
            } else {
                allow = allow + ", PUT";
            }
        }

        if (ALLOW_DELETE) {
            if (allow == null) {
                allow = "DELETE";
            } else {
                allow = allow + ", DELETE";
            }
        }

        if (ALLOW_TRACE) {
            if (allow == null) {
                allow = "TRACE";
            } else {
                allow = allow + ", TRACE";
            }
        }

        if (ALLOW_OPTIONS) {
            if (allow == null) {
                allow = "OPTIONS";
            } else {
                allow = allow + ", OPTIONS";
            }
        }

        resp.setHeader("Allow", allow);
    }

    protected void doTrace(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String CRLF = "\r\n";
        StringBuilder buffer = (new StringBuilder("TRACE ")).append(req.getRequestURI()).append(" ").append(req.getProtocol());
        Enumeration reqHeaderEnum = req.getHeaderNames();

        while(reqHeaderEnum.hasMoreElements()) {
            String headerName = (String)reqHeaderEnum.nextElement();
            buffer.append(CRLF).append(headerName).append(": ").append(req.getHeader(headerName));
        }

        buffer.append(CRLF);
        int responseLength = buffer.length();
        resp.setContentType("message/http");
        resp.setContentLength(responseLength);
        ServletOutputStream out = resp.getOutputStream();
        out.print(buffer.toString());
        out.close();
    }

    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String method = req.getMethod();
        long lastModified;
        if (method.equals("GET")) {
            lastModified = this.getLastModified(req);
            if (lastModified == -1L) {
                this.doGet(req, resp);
            } else {
                long ifModifiedSince;
                try {
                    ifModifiedSince = req.getDateHeader("If-Modified-Since");
                } catch (IllegalArgumentException var9) {
                    ifModifiedSince = -1L;
                }

                if (ifModifiedSince < lastModified / 1000L * 1000L) {
                    this.maybeSetLastModified(resp, lastModified);
                    this.doGet(req, resp);
                } else {
                    resp.setStatus(304);
                }
            }
        } else if (method.equals("HEAD")) {
            lastModified = this.getLastModified(req);
            this.maybeSetLastModified(resp, lastModified);
            this.doHead(req, resp);
        } else if (method.equals("POST")) {
            this.doPost(req, resp);
        } else if (method.equals("PUT")) {
            this.doPut(req, resp);
        } else if (method.equals("DELETE")) {
            this.doDelete(req, resp);
        } else if (method.equals("OPTIONS")) {
            this.doOptions(req, resp);
        } else if (method.equals("TRACE")) {
            this.doTrace(req, resp);
        } else {
            String errMsg = lStrings.getString("http.method_not_implemented");
            Object[] errArgs = new Object[]{method};
            errMsg = MessageFormat.format(errMsg, errArgs);
            resp.sendError(501, errMsg);
        }

    }

    private void maybeSetLastModified(HttpServletResponse resp, long lastModified) {
        if (!resp.containsHeader("Last-Modified")) {
            if (lastModified >= 0L) {
                resp.setDateHeader("Last-Modified", lastModified);
            }

        }
    }

    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        HttpServletRequest request;
        HttpServletResponse response;
        try {
            request = (HttpServletRequest)req;
            response = (HttpServletResponse)res;
        } catch (ClassCastException var6) {
            throw new ServletException("non-HTTP request or response");
        }

        this.service(request, response);
    }
}

ServletConfig

ServletConfig类从类名上来看,就知道是Servlet程序的配置信息类。
Servlet和ServletConfig对象都是由Tomcat负责创建,我们负责使用。
Servlet默认是第一次访问的时候创建,ServletConfig是每个Servlet程序创建时,就创建一个对应的ServletConfig对象。(看运行效果需要重启tomcat服务器,init方法只在创建servlet时调用)

ServletConfig 类的三大作用
1、可以获取 Servlet 程序的别名 servlet-name 的值
2、获取初始化参数init-param
3 、获取 ServletContext 对象

web.xml 中的配置:<init-param>键值对可以配置多个

<!-- servlet标签给Tomcat配置Servlet 程序 -->
<servlet>
    <!--servlet-name 标签 Servlet 程序起一个别名(一般是类名) -->
    <servlet-name>HelloServlet</servlet-name>
    <!--servlet-class 是 Servlet 程序的全类名-->
    <servlet-class>com.atguigu.servlet.HelloServlet</servlet-class>
    <!--init-param 是初始化参数-->

    <init-param>
        <!--是参数名-->
        <param-name>username</param-name>
        <!--是参数值-->
        <param-value>root</param-value>
    </init-param>
    <!--init-param 是初始化参数-->
    <init-param>
        <!--是参数名-->
        <param-name>url</param-name>
        <!--是参数值-->
        <param-value>jdbc:mysql://localhost:3306/test</param-value>
    </init-param>

</servlet>

<!--servlet-mapping 标签给 servlet 程序配置访问地址-->
<servlet-mapping>
    <!--servlet-name 标签的作用是告诉服务器,我当前配置的地址给哪个 Servlet 程序使用-->
    <servlet-name>HelloServlet</servlet-name>
    <!--
    url-pattern 标签配置访问地址 <br/>
    / 斜杠在服务器解析的时候,表示地址为:http://ip:port/工程路径 <br/>
    /hello 表示地址为:http://ip:port/工程路径/hello <br/>
    -->
    <url-pattern>/hello</url-pattern>
</servlet-mapping>

Servlet中的代码:

@Override
public void init(ServletConfig servletConfig) throws ServletException {
    System.out.println("2 init 初始化方法");
   // 1、可以获取 Servlet 程序的别名 servlet-name 的值
    System.out.println("HelloServlet 程序的别名是:" + servletConfig.getServletName());
    // 2、获取初始化参数 init-param
    System.out.println("初始化参数 username 的值是;" +         servletConfig.getInitParameter("username"));
    System.out.println("初始化参数 url 的值是;" + servletConfig.getInitParameter("url"));
    // 3、获取 ServletContext 对象
    System.out.println(servletConfig.getServletContext());
}
注意点:

如果没有在init方法中通过使用servletConfig对象获取各配置信息,也可以在别的方法中使用getServletConfig()方法获取servletConfig对象,此方法默认调用了父类GenericServlet中的方法,如下

private transient ServletConfig config; 

public void init(ServletConfig config) throws ServletException {//默认调用
        this.config = config;//赋值保存
        this.init();
    }

 public ServletConfig getServletConfig() {
        return this.config;
 }

 如果用此方法,并在该servlet程序中重写了带参数的init方法,则在init中需要调用父类的init(ServletConfig)操作,否则默认父类空参的Init,没有为config赋值,得到null

ServletContext

1、ServletContext是一个接口,它表示Servlet上下文对象
2、一个web工程,只有一个ServletContext对象实例。
3、ServletContext对象是一个
域对象四大域对象
4、
ServletContext是在web工程部署启动的时候创建。在web工程停止的时候销毁。

域对象
域对象,是可以像 Map一样存取数据的对象(内置了map集合,都有setAttribute和getAttribute方法 )。
这里的域指的是存取数据的操作范围(整个web工程)。
                        存数据                 取数据                  删除数据                
Map                 put()                    get()                      remove()
域对象             setAttribute()       getAttribute()         removeAttribute();
ServletContext 类的四个作用
1、获取web.xml 中配置的上下文参数 context-param
2、获取当前的工程路径,格式: / 工程路径
3、获取工程部署后在服务器硬盘上的绝对路径
4、像Map 一样存取数据
ServletContext 演示代码:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throwsServletException, IOException {
    // 1 获取web.xml中配置的上下文参数context-parm
    ServletContext context = getServletConfig().getServletContext();   
    System.out.println("context-param 参数 username 的值是:" + context.getInitParameter("username"););
    System.out.println("context-param 参数 password 的值是:" +context.getInitParameter("password"));
    
    // 2: 获取当前的工程路径,格式:/工程路径
    System.out.println( "当前工程路径:" + context.getContextPath() );

    // 3获取工程部署后在服务器硬盘上的绝对路径    
    //斜杠/ 被服务器解析地址为:http://ip:port/工程名/  映射到IDEA代码的web目录                
    System.out.println("工程部署的路径是:" + context.getRealPath("/"));//D:\idea_work\JavaWeb\out\artifacts\servletPro_war_exploded

    System.out.println("工程下css目录的绝对路径是:" + context.getRealPath("/css"));
    System.out.println("工程下imgs目录 1.jpg 的绝对路径是:" + context.getRealPath("/imgs/1.jpg"))}
注意:
通过context.getRealPath("/"))我们 获取工程部署后在服务器硬盘上的绝对路径D:\idea_work\JavaWeb\out\artifacts\servletPro_war_exploded
以下路径是IDEA整合tomcat后tomcat被拷贝的一些副本
C:\Users\admin\AppData\Local\JetBrains\IntelliJIdea2020.1\tomcat\Tomcat_9_0_0_M18_JavaWeb_4。

其中Catalina文件下的配置文件内容是
<Context docBase="D:\idea_work\JavaWeb\out\artifacts\servletPro_war_exploded" path="/servletPro"/>

也就是说通过访问Catalinav文件下的servletPro.xml的配置文件,知道工程的地址(DocBase) 

http://ip:port/工程名  这个工程名对应到磁盘的D:\idea_work\JavaWeb\out\artifacts\servletPro_war_exploded绝对路径,这个绝对路径位置和idea中的web文件夹相对应。也就是映射到idea代码的web目录

 web.xml中的配置:

<!--context-param 是上下文参数(它属于整个 web 工程)-->
<context-param>
    <param-name>username</param-name>
    <param-value>context</param-value>
</context-param>

<!--context-param 是上下文参数(它属于整个 web 工程)-->
<context-param>
    <param-name>password</param-name>
    <param-value>root</param-value>
</context-param>

ServletContext像Map一样存取数据:

ContextServlet1代码:
public class ContextServlet1 extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws
ServletException, IOException {
        // 获取 ServletContext 对象
        ServletContext context = getServletContext();//有直接获取的方法
        System.out.println(context);

        System.out.println("保存之前: Context1 获取 key1 的值是:"+ context.getAttribute("key1"));//null
        context.setAttribute("key1", "value1");
        System.out.println("Context1 中获取域数据 key1 的值是:"+ context.getAttribute("key1"));//value1
    }
}

ContextServlet2代码:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
IOException {
    ServletContext context = getServletContext();
    System.out.println(context);
    System.out.println("Context2 中获取域数据 key1 的值是:"+ context.getAttribute("key1"));//value1
}

HTTP 协议

协议是指双方,或多方,相互约定好,大家都需要遵守的规则,叫协议。
所谓HTTP协议,就是指客户端和服务器之间通信时,发送的数据,需要遵守的规则,叫 HTTP 协议。
HTTP协议中的数据又叫报文

请求的HTTP协议格式

客户端给服务器发送数据叫请求。
服务器给客户端回传数据叫响应。
请求又分为GET 请求和 POST 请求两种
此处安装httpwatch软件分析 【抓包工具】HttpWatch(功能详细介绍)
GET 请求
1、请求行
        (1) 请求的方式                 GET
        (2) 请求的资源路径          [+?+请求参数]
        (3) 请求的协议的版本号   HTTP/1.1
2、请求头
        key : value         组成不同的键值对,表示不同的含义。

POST 请求

1、请求行

         (1) 请求的方式                 POST
         (2) 请求的资源路径          [+?+请求参数]
         (3) 请求的协议的版本号   HTTP/1.1

2、请求头
1) key : value                         不同的请求头,有不同的含义
空行
3、请求体 ===>>> 就是发送给服务器的数据

常用请求头的说明

Accept: 表示客户端可以接收的数据类型
Accpet-Languege: 表示客户端可以接收的语言类型
User-Agent: 表示客户端浏览器的信息
Host: 表示请求时的服务器ip 和端口号
哪些是 GET 请求,哪些是 POST 请求
GET请求有哪些:
        1、form标签默认 method=get
        2、a标签
        3、link标签引入cs
        4、Script 标签引入js文件
        5、img标签引入图片
        6、iframe引入html 页面
        7、在浏览器地址栏中输入地址后敲回车

POST 请求有哪些:
        8、form 标签 method=post

响应的HTTP协议格式

1、响应行
(1) 响应的协议和版本号
(2) 响应状态码
(3) 响应状态描述符
2、响应头
(1) key : value 不同的响应头,有其不同含义
空行
3、响应体 ---->>> 就是回传给客户端的数据

常用的响应码说明

200 表示请求成功
302 表示请求重定向
404 表示请求服务器已经收到了,但是你要的数据不存在(请求地址错误)
500 表示服务器已经收到请求,但是服务器内部错误(代码错误)
MIME 类型说明
MIME是HTTP 协议中数据类型。

MIME的英文全称是"Multipurpose Internet Mail Extensions" 多功能Internet邮件扩充服务。MIME 类型的格式是“大类型/小类型”,并与某一种文件的扩展名相对应。

常见的MIME 类型:
文件
MIME 类型
超文本标记语言文本.html , .htm         text/html
普通文本.txt         text/plain
RTF文本.rtf         application/rtf
GIF图形.gif         image/gif
JPEG图形.jpeg,.jpg         image/jpeg
au声音文件.au         audio/basic mid,
MIDI音乐文件.midi,.mid audio/midi,audio/x-midi
RealAudio音乐文件.ra, .ram         audio/x-pn-realaudio
MPEG文件.mpg,.mpeg v        ideo/mpeg
AVI文件.avi         video/x-msvideo
GZIP文件.gz         application/x-gzip
TAR文件.tar         application/x-tar

谷歌浏览器如何查看HTTP协议:f12

火狐浏览器如何查看 HTTP 协议:

HttpServletRequest

HttpServletRequest 类作用
每次只要有请求进入Tomcat 服务器, Tomcat 服务器就会把请求过来的 HTTP 协议信息解析好封装到 Request对象中。
然后传递到service方法( doGet doPost )中给我们使用。我们可以通过 HttpServletRequest 对象,获取到所有请求的信息。
HttpServletRequest 类的常用方法
getRequestURI()              获取请求的资源路径
getRequestURL()              获取请求的统一资源定位符(绝对路径)
getRemoteHost()              获取客户端的ip地址
getHeader()                  获取请求头
getParameter()               获取请求的参数
getParameterValues()         获取请求的参数(多个值的时候使用)
getMethod()                  获取请求的方式GET或POST
setAttribute(key, value);    设置域数据
getAttribute(key);           获取域数据
getRequestDispatcher()       获取请求转发对象
常用 API 示例代码:
public class RequestAPIServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException {
    // i.getRequestURI()获取请求的资源路径
    System.out.println("URI => " + req.getRequestURI());//uri->/servletPro1/request
    // ii.getRequestURL()获取请求的统一资源定位符(绝对路径)
    System.out.println("URL => " + req.getRequestURL());//url->http://localhost:8080/servletPro1/request
    // iii.getRemoteHost()获取客户端的ip地址
    /**
    *在IDEA中,使用localhost访问时,得到的客户端ip地址是 ===>>> 127.0.0.1
    *在IDEA中,使用127.0.0.1访问时,得到的客户端ip地址是 ===>>> 127.0.0.1
    *在IDEA中,使用真实ip访问时,得到的客户端ip地址是 ===>>>真实的客户端ip地址
    */
    System.out.println("客户端 ip 地址 => " + req.getRemoteHost());
    // iv.getHeader() 获取请求头
    System.out.println("请求头 User-Agent ==>> " + req.getHeader("User-Agent"));
    //vii.getMethod()获取请求的方式GET或POST
    System.out.println( "请求的方式 ==>> " + req.getMethod() );
    }
}
获取请求参数
表单:
<body>
    <form action="http://localhost:8080/07_servlet/parameterServlet" method="get">
        用户名:<input type="text" name="username"><br/>
        密码:<input type="password" name="password"><br/>
        兴趣爱好:<input type="checkbox" name="hobby" value="cpp">C++
        <input type="checkbox" name="hobby" value="java">Java//注:后台根据name属性获取value值,value不加默认是on的选中状态 
        <input type="checkbox" name="hobby" value="js">JavaScript<br/>
        <input type="submit">
    form>
body>
Java 代码:
public class ParameterServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException {
    //获取请求参数.根据html中的name属性获取
    String username = req.getParameter("username");
    String password = req.getParameter("password");
    String[] hobby = req.getParameterValues("hobby");
    System.out.println("用户名:" + username);
    System.out.println("密码:" + password);
    System.out.println("兴趣爱好:" + Arrays.asList(hobby));}
}
doGet 请求的中文乱码解决:
// 获取请求参数
String username = req.getParameter("username");
//1 先以 iso8859-1 进行编码
//2 再以 utf-8 进行解码
username = new String(username.getBytes("iso-8859-1"), "UTF-8");
POST 请求的中文乱码解决
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
IOException {
// 设置请求体的字符集为 UTF-8,从而解决 post 请求的中文乱码问题。获取请求参数调用前使用才有效
req.setCharacterEncoding("UTF-8");
System.out.println("-------------doPost------------");
// 获取请求参数
String username = req.getParameter("username");
String password = req.getParameter("password");
String[] hobby = req.getParameterValues("hobby");
System.out.println("用户名:" + username);
System.out.println("密码:" + password);
System.out.println("兴趣爱好:" + Arrays.asList(hobby));
请求转发
请求转发是指,服务器收到请求后,从一个资源跳转到另一个资源的操作叫请求转发。

Servlet1 代码:

req.getRequestDispatcher("/servlet2"); requestDispatcher.forward(req,resp);

public class Servlet1 extends HttpServlet {
    @Override    
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException {
    //获取请求的参数(办事的材料)查看
    String username = req.getParameter("username");
    System.out.println("在 Servlet1(柜台 1)中查看参数(材料):" + username);
    //给材料盖一个章,并传递到Servlet2(柜台 2)去查看
    req.setAttribute("key1","柜台 1 的章");
    // 问路:Servlet2(柜台 2)怎么走
    /**
    * 请求转发必须要以斜杠打头,/ 斜杠表示地址为:http://ip:port/工程名/ , 映射到 IDEA 代码的 web 目录
    **/
    RequestDispatcher requestDispatcher = req.getRequestDispatcher("/servlet2");
    // RequestDispatcher requestDispatcher = req.getRequestDispatcher("http://www.baidu.com");//不可以访问工程意外的资源
    // 走向Sevlet2(柜台 2)
    requestDispatcher.forward(req,resp);
    }
}
Servlet2 代码:
 
public class Servlet2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException {
    // 获取请求的参数(办事的材料)查看
    String username = req.getParameter("username");
    System.out.println("在 Servlet2(柜台 2)中查看参数(材料):" + username);
    // 查看 柜台 1 是否有盖章
    Object key1 = req.getAttribute("key1");
    System.out.println("柜台 1 是否有章:" + key1);
    // 处理自己的业务
    System.out.println("Servlet2 处理自己的业务 ");
    }
}

base标签的作用

目录结构

 在web下新建c.html和index.html,实现两个页面的跳转

 不采用请求转发的方法可以实现跳转

<body>
    这是a下的b下的c<br/>
    <a href="../../index.html">跳回首页</a>
</body>

<body>
    这是web下的index.html<br/>
    <a href="a/b/c.html">a/b/c.html</a><br/>
</body>

此处采用请求方式后无法跳回到index

<body>
    这是web下的index.html<br/>   
    <a href="http://localhost:8080/servletPro1/forward">请求转发:a/b/c.html</a>
</body>
public class ForwardC extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("经过了forwardc程序");
        req.getRequestDispatcher("/a/b/c.html").forward(req,resp);
    }
}

无法跳转的原因: 

base标签可以设置当前页面中所有相对路径工作时,参照哪个路径来进行跳转 

<html lang="zh_CN">
<head>
    <meta charset="UTF-8">
    <title>Titletitle>
    <!--base 标签设置页面相对路径工作时参照的地址
        href 属性就是参数的地址值
    -->
    <base href="http://localhost:8080/servletPro1/a/b/">a/b/     //c.html可省略c.html
<head>
<body>
    这是a下的b下的c.html 页面<br/>
    <a href="../../index.html">跳回首页a><br/>
<body>
<html>

Web中的相对路径和绝对路径

在javaWeb中,路径分为相对路径和绝对路径两种:
    相对路径是:
          .           表示当前目录
          ..           表示上一级目录
         资源名   表示当前目录/资源名

    绝对路径:
         http://ip:port/工程路径/资源路径

在实际开发中,路径都使用绝对路径,而不简单的使用相对路径。
1、绝对路径
2、base+相对

web/斜杠的不同意义

在web中 / 斜杠是一种绝对路径
/斜杠如果被浏览器解析,得到的地址是: http://ip:port/
<a href="/">斜杠a>
/斜杠如果被服务器解析,得到的地址是: http://ip:port/ 工程路径
1、<url-pattern>/servlet1url-pattern>

2、servletContext.getRealPath(“/”);

3、request.getRequestDispatcher(“/”);
特殊情况 response.sendRediect(“/”); 把斜杠发送给浏览器解析。得到 http://ip:port/

HttpServletResponse

HttpServletResponse 类的作用
HttpServletResponse类和HttpServletRequest 类一样。每次请求进来, Tomcat 服务器都会创建一个 Response 对象传递给Servlet程序去使用。HttpServletRequest 表示请求过来的信息, HttpServletResponse 表示所有响应的信息,我们如果需要设置返回给客户端的信息,都可以通过 HttpServletResponse对象来进行设置
两个输出流的说明。
        字节流 getOutputStream() ; 常用于下载(传递二进制数据)
        字符流 getWriter() ; 常用于回传字符串(常用)
两个流同时只能使用一个。
使用了字节流,就不能再使用字符流,反之亦然,否则就会报错。

往客户端回传数据

要求:往客户端回传字符串数据。
public class ResponseIOServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException {
    //要求:往客户端回传字符串数据。
    PrintWriter writer = resp.getWriter();
    writer.write("response's content!!!");
    }
}
响应的乱码解决
解决响应中文乱码方案一 (不推荐使用)
//System.out.println(resp.getCharacterEncoding()) //默认的服务器响应字符集不支持中文
// 设置服务器字符集为UTF-8
resp.setCharacterEncoding("UTF-8");
// 通过响应头,设置浏览器也使用UTF-8字符集
resp.setHeader("Content-Type", "text/html; charset=UTF-8");
解决响应中文乱码方案二 (推荐) setContentType
// 它会同时设置服务器和客户端都使用 UTF-8 字符集,还设置了响应头
// 此方法一定要在获取流对象之前调用才有效
resp.setContentType("text/html; charset=UTF-8");
请求重定向
请求重定向,是指客户端给服务器发请求,然后服务器告诉客户端说。我给你一些地址。你去新地址访问,叫请求重定向(因为之前的地址可能已经被废弃)。

对于3,每个request都是一个不同的对象,对于4,浏览器不能直接访问WEB-INF下的资源,资源是受保护的>

请求重定向的第一种方案:

public class Response1 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("曾到此一游 Response1 ");
        //不共享req中的数据
        req.setAttribute("key1", "value1");//不共享
        // 设置响应状态码302 ,表示重定向,(已搬迁)
        resp.setStatus(302);
        // 设置响应头,说明 新的地址在哪里
       resp.setHeader("Location", "http://localhost:8080/07_servlet/response2");
       //可以访问工程外的资源
        resp.setHeader("Location", "http://www.baidu.com");
    }
}

public class Response2 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println(req.getAttribute("key1"));//不能得到req中的数据
        resp.getWriter().write("response2's result!");
    }
}
请求重定向的第二种方案( 推荐使用 ):
resp.sendRedirect(""http://localhost:8080/servletPro1/response2"");

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值