Javaweb学习笔记 servlet篇

a)什么是servlet

1.servlet是javaee规范之一,规范就是接口,
2.servlet是javaee三大组件之一,三大组件分别是servlet程序,filter过滤器,listener监听器
3.servlet是运行在服务器上的一个java小程序,它可以接受客户端发送过来的请求,并响应数据给客户端,

b)手动实现servlet程序

1.编写一个类去实现servlet接口
2.实现servlet方法,处理请求,并响应数据
3.到web.xml中去配置servlet程序的访问地址

Servlet 程序的示例代码:

package com.atguigu.servlet;

import javax.servlet.*;
import java.io.IOException;

public class helloServlet implements Servlet {

    //servlet方法专门用来处理请求和响应的

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("hello servlet 被访问了");
    }

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

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {

    }

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

    @Override
    public void destroy() {

    }
}

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配置tomcart程序-->
<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>

常见的错误:

常见的错误一:
在这里插入图片描述

url-pattern中配置的路径没有以斜杠打头

Caused by: java.lang.IllegalArgumentException: Invalid hello in servlet mapping
at org.apache.catalina.core.StandardContext.addServletMappingDecoded(StandardContext.java:3195)
at org.apache.catalina.core.StandardContext.addServletMappingDecoded(StandardContext.java:3182)
at org.apache.catalina.startup.ContextConfig.configureContext(ContextConfig.java:1384)
at org.apache.catalina.startup.ContextConfig.webConfig(ContextConfig.java:1192)
at org.apache.catalina.startup.ContextConfig.configureStart(ContextConfig.java:782)
at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:307)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:95)
at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5221)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
… 43 more

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

在这里插入图片描述

Caused by: java.lang.IllegalArgumentException: Servlet mapping specifies an unknown servlet name helloServlet1
at org.apache.catalina.core.StandardContext.addServletMappingDecoded(StandardContext.java:3191)
at org.apache.catalina.core.StandardContext.addServletMappingDecoded(StandardContext.java:3182)
at org.apache.catalina.startup.ContextConfig.configureContext(ContextConfig.java:1384)
at org.apache.catalina.startup.ContextConfig.webConfig(ContextConfig.java:1192)
at org.apache.catalina.startup.ContextConfig.configureStart(ContextConfig.java:782)
at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:307)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:95)
at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5221)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
… 43 more

常见错误三:
servlet-class配置的全类名配置错误
在这里插入图片描述

javax.servlet.ServletException: Error instantiating servlet class com.atguigu.srvlet.helloServlet
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:620)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:502)
org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1132)
org.apache.coyote.AbstractProtocol A b s t r a c t C o n n e c t i o n H a n d l e r . p r o c e s s ( A b s t r a c t P r o t o c o l . j a v a : 684 ) o r g . a p a c h e . t o m c a t . u t i l . n e t . A p r E n d p o i n t AbstractConnectionHandler.process(AbstractProtocol.java:684) org.apache.tomcat.util.net.AprEndpoint AbstractConnectionHandler.process(AbstractProtocol.java:684)org.apache.tomcat.util.net.AprEndpointSocketProcessor.doRun(AprEndpoint.java:2527)
org.apache.tomcat.util.net.AprEndpoint S o c k e t P r o c e s s o r . r u n ( A p r E n d p o i n t . j a v a : 2516 ) j a v a . b a s e / j a v a . u t i l . c o n c u r r e n t . T h r e a d P o o l E x e c u t o r . r u n W o r k e r ( T h r e a d P o o l E x e c u t o r . j a v a : 1130 ) j a v a . b a s e / j a v a . u t i l . c o n c u r r e n t . T h r e a d P o o l E x e c u t o r SocketProcessor.run(AprEndpoint.java:2516) java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130) java.base/java.util.concurrent.ThreadPoolExecutor SocketProcessor.run(AprEndpoint.java:2516)java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)java.base/java.util.concurrent.ThreadPoolExecutorWorker.run(ThreadPoolExecutor.java:630)
org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
java.base/java.lang.Thread.run(Thread.java:832)

c)url地址到servlet程序的访问

在这里插入图片描述

客户端(浏览器)
http://localhost:8080/test_war_exploded/hello
http://表示http协议
localhost是服务器ip
:8080是服务器的端口号
/test_war_exploded 是工程路径
/hello 是资源路径

通过ip地址定位到服务器
通过端口号定位tomcat
通过工程路径知道要访问哪个工程

 public class helloServlet{
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("hello servlet 被访问了");
    }
}

web.xml配置文件
服务器 硬件 电脑 ip地址(唯一)
8080端口 tomcat服务器
里面有:
/test_war_exploded工程
/abc 工程
/book 工程……

<servlet>
    <!--servlet-name 标签servlet程序起一个别名(一般是类名)-->
    <servlet-name>helloServlet</servlet-name>
    <!--servlet-class是servlet程序的全类名-->
    <servlet-class>com.atguigu.servlet.helloServlet</servlet-class>
</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>

d)servlet的生命周期

1.执行servlet构造器的方法
2.执行init初始化方法
第一第二步是在创建servlet程序会使用
3.执行service方法
第三步 每次访问都会被调用
4.执行destroy销毁方法
第四步在web停止的时候被调用

e)get和post的分发处理

package com.atguigu.servlet;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

public class helloServlet implements Servlet {
    public helloServlet() {
        System.out.println("1 构造器方法");
    }
//servlet方法专门用来处理请求和响应的

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

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

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("3 service()方法");
        //类型转换 (因为它有getMethod() 方法)

        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        String method = httpServletRequest.getMethod();
        if("GET".equals(method)){
          doGet();
        }else if("POST".equals(method)){
            doPost();
        }
    }
public void doGet(){
    System.out.println("get请求");
}
    public void doPost(){
        System.out.println("post请求");
    }


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

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

f)通过继承httpservlet实现servlet程序

一般在实际项目开发中,都是使用继承httpServlet类的方式去实现servlet程序
1.编写一个类去继承hpptservlet类
2.根据业务需要重写doGet或doPost方法
3.到web.xml中配置Servlet程序的访问地址

package com.atguigu.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

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方法");
    }
}

g)使用idea创建servlet程序

菜单→new→servlet程序
在这里插入图片描述
配置servlet的信息
在这里插入图片描述

h)servlet的继承体系

1.继承树

interface servlet :只是负责定义servlet程序的访问规范
↑ 实现接口
class GenericServlet :实现了servlet接口,做了很多空实现,并持有一个servletconfig类的引用,并对servletconfig的使用做一些方法
↑ 继承
class HttpServlet : HttpServlet抽象实现了service()方法,并且实现了请求的分类处理
↑ 继承 String method = req.getmethod()
自定义的servlet程序 GET POST
doGet() doPost() 负责抛异常,说不支持get和post请求
我们只需要根据自己的任务需要去重写doGet和doPost方法即可
在这里插入图片描述

2.servletConfig类

servletConfig类 从类名上来看,就知道是servlet程序的配置信息类

a)servletconfig类的三大作用

1.可以获取servlet程序的别名servlet-name的值
2.获取初始化参数init-param
3.获取servletContext的对象

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

在别的地方使用servletconfig对象

	package com.atguigu.servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class helloServlet2 extends HttpServlet {

    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        System.out.println("重写了init初始化方法,做了一些工作");
    }


    //doGet()在get请求的时候调用
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("helloservlet2的doGet方法");
        //也可以使用
        ServletConfig servletConfig = getServletConfig();
        System.out.println(servletConfig);
        System.out.println(servletConfig.getInitParameter("username"));
    }
    //doPost()在post请求时调用

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("helloservlet2的doPost方法");
    }
}
<?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配置tomcart程序-->
<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>
</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>
    
    <servlet>
        <servlet-name>helloServlet2</servlet-name>
        <servlet-class>com.atguigu.servlet.helloServlet2</servlet-class>
<init-param>
    <param-name>username</param-name>
    <param-value>root2</param-value>
</init-param>
    </servlet>
    <servlet>
        <servlet-name>helloServlet3</servlet-name>
        <servlet-class>com.atguigu.servlet.helloServlet3</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>helloServlet3</servlet-name>
        <url-pattern>/hello3</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>helloServlet2</servlet-name>
        <url-pattern>/hello2</url-pattern>
    </servlet-mapping>
</web-app>

注意 重写会覆盖掉父类方法 所以要使用super关键字调用父类方法

@Override
public void init(ServletConfig config) throws ServletException {
    super.init(config); 注意这里
    System.out.println("重写了init初始化方法,做了一些工作");
}

3.servletContext类

a)什么是servletContext

1.servletcontext是一个接口,他表示servlet上下文对象
2.一个web工程,只有一个servletContext对象实例
3.servletcontext是一个域对象,
4.4.servletcontext是在web工程中部署的时候启动创建,在web工程停止的时候销毁它

什么是域对象?

域对象,是和map一样可以存储数据的对象,叫域对象
这里的域指的存储数据的操作范围,这里的操作范围为web项目**

存数据取数据删除数据
mapput()get()remove()
servletContextputAttribute()getAttribute()removeAttribute()

b)ServletContext类的四个作用

1.获取web.xml中配置的上下文参数context-param
2.获取当前的工程路径,格式:/工程路径
3.获取工程部署后在服务器在磁盘上的绝对路径
4.像map一样存储数据
功能测试:

package com.atguigu.servlet;

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;

public class ContextServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
       // 1.获取web.xml中配置的上下文参数context-param
        ServletContext servletContext = getServletConfig().getServletContext();
        System.out.println("context-param参数username的值是"+servletContext.getInitParameter("username"));
        System.out.println("context-param参数password的值是"+servletContext.getInitParameter("password"));
        // 2.获取当前的工程路径,格式:/工程路径
        System.out.println("当前工程路径为:"+getServletConfig().getServletContext().getContextPath());
        // 3.获取工程部署后在服务器在磁盘上的绝对路径
        //  /  斜杠被服务器解析为http://ip:port/工程名/
        // 映射到idea代码的web目录
        System.out.println("工程部署的路径是"+getServletConfig().getServletContext().getRealPath("/"));
        System.out.println("工程下的css目录"+getServletConfig().getServletContext().getRealPath("/css"));
        System.out.println("工程下的image下的1.jpg的路径是"+getServletConfig().getServletContext().getRealPath("/image/1.jpg"));
    }
// 以下地址是idea整合tomcat之后,tomcat被拷贝的一些副本内容
//Using CATALINA_BASE:   "C:\Users\26523\AppData\Local\JetBrains\IntelliJIdea2021.1\tomcat\009e2895-4f0a-4989-aadc-b4300d96c7c5"

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }
}

输出结果:
context-param参数username的值是context
context-param参数password的值是root
当前工程路径为:/test_war_exploded
工程部署的路径是C:\Users\26523\IdeaProjects\test\target\test-1.0-SNAPSHOT
工程下的css目录C:\Users\26523\IdeaProjects\test\target\test-1.0-SNAPSHOT\css
工程下的image下的1.jpg的路径是C:\Users\26523\IdeaProjects\test\target\test-1.0-SNAPSHOT\image\1.jpg

4.http协议

a)什么是http协议

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

b)请求的http协议格式

客户端给服务器发送数据叫做请求
服务器给服务器回传数据叫响应
请求又分为get请求和post请求两种

i.GET请求

1.请求行
(1)请求的方式 GET
(2)请求的资源路径[+?+请求参数]
(3)请求的协议的版本号 HTTP/1.1
2.请求头
key:value 组成 不同的储值对,表示不同的含义
请求行:
1.请求的方式: GET
2.请求的资源路径 /test_war_explored/a.html
3.请求到协议的版本号 HTTP/1.1

Accept:告诉服务器可以接收到的数据类型
Accept—language:告诉服务器客户端可以接收的语言类型
zh_CN 中文中国
en_US 英文美国
User-Agent: 就是浏览器的信息
Accept-Encoding: 告诉服务器,客户端可以接收的数据编码(压缩)格式
Host:表示请求的服务器ip和端口号
Connection:告诉服务器请求连接如何处理
keep-alive 告诉服务器回传数据不要马上关闭,保持一小段时间的连接
closed 马上关闭

在这里插入图片描述

ii post请求

1.请求行
1.请求的方式: POST
2.请求的资源路径 /test_war_explored/a.html
3.请求到协议的版本号 HTTP/1.1

2.请求头
1)key:value 不同的请求头有不同的含义
空行

3.请求体 ======= 就是发送给服务器的数据

以下是post请求的http协议内容
请求行
POST /test_war_exploded/hello HTTP/1.1
1.请求的方式 post
2.请求的资源路径 /test_war_exploded/hello
3.请求的协议和版本号 HTTP/1.1

请求头:
Host: localhost:8080
Connection: keep-alive
Content-Length: 26
Cache-Control: max-age=0
sec-ch-ua: “Google Chrome”;v=“93”, " Not;A Brand";v=“99”, “Chromium”;v=“93”
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: “Windows”
Upgrade-Insecure-Requests: 1
Origin: http://localhost:8080
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://localhost:8080/test_war_exploded/a.html
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: JSESSIONID=3586F254239F3856FE08F9A589AB0F0A; Idea-c372728b=41df1464-46ec-4bba-b8c1-d85a2c936a1f
空行

accept:表示可以接收到的数据类型
accept-language 表示客户端可以接受的语言类型
referer: 表示请求发起时,浏览器地址栏中的地址(从哪来)
user-agent:表示浏览器的信息
content-type表示发送的数据的类型
application/x-www-form-urlencoded 表示提交的数据格式类型是:name=value&&name=value 然后对其进行url编码
url编码是把非英文内容转换为:%xx%xx的形式
multipart/form-data 表示以多段的形式提交给服务器(以流的形式提交,用于上传)
content-length:表示发送的数据的长度
cache-control:表示如何控制缓存 no—cache不缓存

请求体:发送给服务器的数据
username=root&action=login
在这里插入图片描述

iii 常用请求头的说明

accept:表示客户端可以接受的数据类型
accept-language:表示客户端可以接受的语言类型
user-agent:表示客户端浏览器的信息
host: 表示请求时的服务器ip和端口号

iv:哪些是get请求,哪些是post请求
get请求有哪些

1.form标签 method = get
2.a标签
3.link标签引入css
4.script标签引入js文件
5.img标签引入图片
6.iframe引入html页面
7.在浏览器地址栏中输入地址后敲回车

post请求有哪些

1.form标签 method = post

c)响应的http协议格式

1.响应行
(1)响应的协议和版本号 http:/1.1
(2) 响应状态码 200
(3) 响应状态描述符 ok

2.响应头
(1)key:value 不同的响应头有不同的含义
空行

3.响应体 ---- 就是回传给客户端的数据

以下的内容就是响应的http协议实例:

响应行:
1.响应的协议 http
2.响应状态码 200
3.响应状态描述符 ok
响应头:
server:表示服务器的信息
Content-type:表示响应体的数据类型
content-length:响应体的数据长度
date:请求响应的时间(格林时间)

响应行
HTTP/1.1 200 OK
响应头
Server: Apache-Coyote/1.1
Content-Length: 0
Date: Wed, 08 Sep 2021 10:33:59 GMT
空行

响应体

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="http://localhost:8080/test_war_exploded/hello2" method="get">
    <input type="submit" value="提交"/>
</form>
</body>
</html>

在这里插入图片描述

d)常用的响应码说明

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

e)MIME类型说明

mime是http协议中数据类型
mime的英文全称是"multipurpose Internet Mail Extensions"多功能internet邮件扩充服务,mime类型的格式是“大类型/小类型”,并与某一种文件的扩展名相对应

常见的mme类型

文本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
MIDI声音文件.midi,.mid audio/midi audio/x-midi
RealAudio声音文件.ram,.ra audio/x-pn-realaudio
mpeg文件.mpeg/.mpg video/x-msvideo
AVI文件.avi video/x-msvideo
GZIP文件.gz application/x-gzip
TAR文件.tar application/x-tar

如何用谷歌浏览器查看HTTP协议内容在这里插入图片描述
如何用火狐浏览器查看http协议内容
在这里插入图片描述

5.httpServletRequest类

a)httpServletRequest类的作用

每次只要有请求进入tomcat服务器就会把请求过来的http协议解析好封装到request对象中
然后传递到service方法里(doget和dopost)中给我们使用,我们可以通过httpServletRequest对象,获取到所有的信息,

b)httpservletrequest类的常用方法

i. getRequestURI() 获取请求的资源路径
ii. getRequestURL() 获取请求的统一的资源定位符(绝对路径)
iii. getRemoteHost() 获取客户端的ip地址
iv. getHeader() 获取请求头
vii. getMethod() 获取请求的方式GET或POST
viii. setAttribute(key, value); 设置域数据
ix. getAttribute(key); 获取域数据
x. getRequestDispatcher() 获取请求转发对象

package com.atguigu.Servlet;

import com.example.demo.HelloServlet;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class RequestApiServlet extends HelloServlet {
    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        //    i. getRequestURI() 获取请求的资源路径 uri:/demo_war_exploded/hello
        System.out.println("uri:"+request.getRequestURI());
        //ii. getRequestURL() 获取请求的统一的资源定位符(绝对路径) url:http://localhost:8080/demo_war_exploded/hello
        System.out.println("url:"+request.getRequestURL());
        //iii. getRemoteHost()  获取客户端的ip地址 客户端ip地址:127.0.0.1
        /*
        * 在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地址:"+request.getRemoteHost());
        //iv. getHeader()      获取请求头 请求头:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36 Edg/93.0.961.38
        System.out.println("请求头:"+ request.getHeader("User-Agent"));

        // vii. getMethod()             获取请求的方式GET或POST
        System.out.println("请求的方式:"+request.getMethod());}

c)如何获取请求参数

v. getParameter() 获取请求的参数
vi. getParameterValues() 获取请求的参数(多个值的时候使用)

Servlet程序代码:

package com.atguigu.Servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;

public class ParameterServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //v. getParameter()     获取请求的参数
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        //vi. getParameterValues()  获取请求的参数(多个值的时候使用)
        String[] hobby = req.getParameterValues("hobby");

        System.out.println("用户名:"+username);
        System.out.println("密码:"+password);
        System.out.println("爱好:"+ Arrays.asList(hobby));
    }

    @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));
    }
}

前端代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="http://localhost:8080/demo_war_exploded/hello2" method="post">
    用户名:<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
    <input type="checkbox" name="hobby" value="javascript"/>javascript
    <br/>
    <input type="submit" value="提交"/>

</form>
</body>
</html>

解决doget请求的中文乱码解决

//获取请求参数
        String username1 = req.getParameter("username");
        //1.先以iso8859-1进行编码
        //2.再以utf-8进行编码
        new String(username1.getBytes("iso8859-1"),"UTF-8");

d) dopost请求的中文乱码的解决:

 @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));
    }
}

e)请求的转发

什么是请求的转发?
请求转发是指,服务器收到请求后,从一次资源跳转到另一个资源的操作,叫请求转发
在这里插入图片描述

web配置文件

<?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>
        <servlet-name>RequestApiServlet</servlet-name>
        <servlet-class>com.atguigu.Servlet.RequestApiServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>RequestApiServlet</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
<servlet>
    <servlet-name>Servlet1</servlet-name>
    <servlet-class>com.atguigu.Servlet.Servlet1</servlet-class>
</servlet>
    <servlet-mapping>
        <servlet-name>Servlet1</servlet-name>
        <url-pattern>/servlet1</url-pattern>
    </servlet-mapping>
    <servlet>
        <servlet-name>servlet2</servlet-name>
        <servlet-class>com.atguigu.Servlet.Servlet2</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>servlet2</servlet-name>
        <url-pattern>/servlet2</url-pattern>
    </servlet-mapping>
</web-app>

servlet1

package com.atguigu.Servlet;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;


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");

    //走向Servlet2(柜台)
          requestDispatcher.forward(req,resp);
    }
}

servlet2

package com.atguigu.Servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

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("柜台一是否有章?"+key1);

        //开始处理自己的业务
        System.out.println("servlet2 开始处理自己的业务");
    }
}

f)base标签的使用

当我们点击a标签进行跳转的时候,浏览器的地址是http://localhost:8080/demo_war_exploded/a/b/c.html
跳转回去的a标签的路径是:…/…/index.html
所有相对路径在工作时候都会参照当前浏览器地址栏中的地址进行跳转,
那么参照后的地址是:http://localhost:8080/demo_war_exploded/index.html
正确的跳转路径

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

当我们使用请求转发跳转的地址是http://localhost:8080/demo_war_exploded/ForwardC
跳转回去的a标签的路径是:…/…/index.html
所有相对路径在工作时候都会参照当前浏览器地址栏中的地址进行跳转,
那么参照后的地址是:http://localhost:8080/index.html

实例:
a/b/c.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>test</title>
    <!--base标签设置页面相对路径工作时参照的路径、
         href属性就是参数的地址值 -->
    <base href="http://localhost:8080/demo_war_exploded/a/b/c.html">
</head>
<body>
这是a下的b的c.html界面<br/>
<a href = "../../index.html">返回主页  ../../index.html</a>
</body>
</html>

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
这个是web下的index.html <br/>
<a href="a/b/c.html">a/b/c.html</a><br/>
<a href = "http://localhost:8080/demo_war_exploded/ForwardC" >请求转发:a/b/c.html</a>
</body>
</html>

ForwardC.java

package com.atguigu.Servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

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);
    }
}

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>
        <servlet-name>RequestApiServlet</servlet-name>
        <servlet-class>com.atguigu.Servlet.RequestApiServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>RequestApiServlet</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
<servlet>
    <servlet-name>Servlet1</servlet-name>
    <servlet-class>com.atguigu.Servlet.Servlet1</servlet-class>
</servlet>
    <servlet-mapping>
        <servlet-name>Servlet1</servlet-name>
        <url-pattern>/servlet1</url-pattern>
    </servlet-mapping>
    <servlet>
        <servlet-name>servlet2</servlet-name>
        <servlet-class>com.atguigu.Servlet.Servlet2</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>servlet2</servlet-name>
        <url-pattern>/servlet2</url-pattern>
    </servlet-mapping>
    <servlet>
        <servlet-name>ForwardC</servlet-name>
        <servlet-class>com.atguigu.Servlet.ForwardC</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>ForwardC</servlet-name>
        <url-pattern>/ForwardC</url-pattern>
    </servlet-mapping>
</web-app>

g) web中的相对路径和绝对路径

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

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

h)web中 / 斜杠的不同意义

在web中 / 斜杠是一种绝对路径,
/ 斜杠如果被浏览器解析 得到的地址是:http://ip:port/

/ 斜杠如果被服务器解析,得到的地址是http://ip:port/工程路径
1. /servlet1
2. servletContext.getRealPath("/");
3.request.getRequestDispatcher("/");

特殊情况:
response.sendRediect("/"); 把斜杠发送给浏览器解析,得到的http://ip:port/

6.HttpServletResponse类

a)HttpServletResponse类的作用

httpServletResponse类和httpServletRequest类一样,每次请求进来,tomcat服务器都会创建一个response对象传递给servlet程序去使用HttpServletRequest表示请求过来的信息,HttpServletResponse表示所有相应的信息,
我们如果需要设置返回给客户端的数据,都可以通过httpServletResponse对象来进行设置

b)两个输出流的说明

字节流 getOutputStream() 常用于下载(传递二进制数据)

字符流 getWriter() 常用于回传字符串(常用)

两个流只能使用一个,
使用了字节流,就不能再使用字符流,反之亦然,否则就会报错
在这里插入图片描述

c) 如何往客户端回传数据

要求 : 往客户端回传 字符串 数据。

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!!!");
}
}

d)相应的乱码解决

解决响应中文乱码问题方案一(不推荐使用!)

package com.atguigu.Servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class ResponseIOServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println(resp.getCharacterEncoding()); //默认ISO-8859-1
        // 设置服务器字符集为UTF-8
        resp.setCharacterEncoding("UTF-8");
        //通过响应头,设置浏览器也使用utf-8字符集
        resp.setHeader("Content-Type","text/html;charset=UTF-8");
        //要求: 往客户端回传字符串数据
        PrintWriter writer = resp.getWriter();
        writer.write("阿凡达色为世人的  ");
    }

}

解决响应中文乱码问题方案二 (推荐使用)

  //它对同时设置服务器和客户端都是用utf-8字符集,还设置了响应头
  //此方法一定要在获取数据流对象前使用才有效
 resp.setContentType("text/html;charset=UTF-8");

e)请求重定向

请求重定向 是指客户端给服务器发请求,然后,服务器告诉客户端,我给你可以新的地址,你去新的地址访问,叫做请求重定向
(因为可能之前的地址可能被废弃)
在这里插入图片描述

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>
        <servlet-name>RequestApiServlet</servlet-name>
        <servlet-class>com.atguigu.Servlet.RequestApiServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>RequestApiServlet</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
<servlet>
    <servlet-name>Servlet1</servlet-name>
    <servlet-class>com.atguigu.Servlet.Servlet1</servlet-class>
</servlet>
    <servlet-mapping>
        <servlet-name>Servlet1</servlet-name>
        <url-pattern>/servlet1</url-pattern>
    </servlet-mapping>
    <servlet>
        <servlet-name>servlet2</servlet-name>
        <servlet-class>com.atguigu.Servlet.Servlet2</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>servlet2</servlet-name>
        <url-pattern>/servlet2</url-pattern>
    </servlet-mapping>
    <servlet>
        <servlet-name>ForwardC</servlet-name>
        <servlet-class>com.atguigu.Servlet.ForwardC</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>ForwardC</servlet-name>
        <url-pattern>/ForwardC</url-pattern>
    </servlet-mapping>
    <servlet>
        <servlet-name>ResponseIOServlet</servlet-name>
        <servlet-class>com.atguigu.Servlet.ResponseIOServlet</servlet-class>
    </servlet>
       <servlet-mapping>
           <servlet-name>ResponseIOServlet</servlet-name>
           <url-pattern>/ResponseIOServlet</url-pattern>
       </servlet-mapping>

    <servlet>
        <servlet-name>response1</servlet-name>
        <servlet-class>com.atguigu.Servlet.response1</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>response1</servlet-name>
        <url-pattern>/response1</url-pattern>
    </servlet-mapping>
  <servlet>
      <servlet-name>response2</servlet-name>
      <servlet-class>com.atguigu.Servlet.response2</servlet-class>
  </servlet>
    <servlet-mapping>
        <servlet-name>response2</servlet-name>
        <url-pattern>/response2</url-pattern>
    </servlet-mapping>
</web-app>

response1.java

package com.atguigu.Servlet;


import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class response1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("曾到此一游 response1");
        //设置响应状态码302,表示重定向,(已搬迁)
        resp.setStatus(302);

        resp.setHeader("location","http://localhost:8080/demo_war_exploded/response2");
    }
}

response2.java

package com.atguigu.Servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class response2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=UTF-8");
        PrintWriter writer = resp.getWriter();
        writer.write("啊哈的时刻实打实");
    }
}

请求重定向的另一种方法(推荐)

 resp.sendRedirect("http://localhost:8080/demo_war_exploded/response2");
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值