javaweb-3-servlet-尚硅谷

servlet技术

一、什么是servlet

  • Servlet是javaEE规范之一
    • 规范就是接口
  • servlet就是javaweb三大组件之一
    • 三大组件分别是:
    • Servlet程序
    • Filter过滤器
    • Listener监听器
  • Servlet是运行在服务器上的java小程序
    • 用来处理客户端发过来的请求并响应数据给客户端

二、Servlet程序

  • 编写一个类实现Servlet接口
  • 实现service方法,处理请求并响应数据
  • 在web.xml中配置地址
1、Servlet的生命周期
  • 执行Servlet构造器方法

  • 执行init初始化方法

    第一、二步:开启tomcat之后第一次访问,tomcat创建Servlet程序时会调用

  • 执行service方法

    第三步:开启tomcat后,每次访问都会调用

  • 执行destroy销毁方法

    第四步:在关闭tomcat时会被调用

2、请求的分发处理
  • 首先我们呢需要在webapp文件夹下创建一个test.html(访问时只需要在域名后加上test.html即可访问,不需要再web.xml中注册)

    我们主要是用这个网页来访问我们的程序,进而在我们的程序中读取到我们读取的方法是哪种的(GET还是POST)

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>test</title>
    </head>
    <body>
    <form action="http://localhost:8080/servlet03/demo1" method="get">
        <input type="submit">
    </form>
    </body>
    </html>
    
  • 了解创建为什么我们在后来的学习中继承了HttpServlet后只需要重写doGet方法和doPost方法

    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        //ServletRequest类没有getMethod方法所以我们需要向下转型为HttpServletRequest类
        HttpServletRequest req1 = (HttpServletRequest) req;
        String method = req1.getMethod();
        if (method.equals("GET")){
            doGet();
        }else{
            doPost();
        }
        System.out.println("hello servlet 被访问了");
    }
    public void doPost(){
        System.out.println("post请求");
    }
    public void doGet(){
        System.out.println("Get请求");
    }
    

    可以对比HttpServlet的类的service方法

    • 会发现HttpServlet中req调用getMethod不需要向下转型(因为该类传入的参数是HttpServletRequest req,而我们的类是ServletRequest req)
    • 那么我们是否可以也可以把ServletRequest req跟改成HttpServletRequest req呢?不能,因为我们的类是实现了Servlet,所有方法必须重写,方法的参数类型也必须和Servlet中的ServletRequest req一致,而HttpServlet类是继承GenericServlet 类,没有硬性要求必须重写,所以可以更改)
3、用IDEA直接创建Servlet程序

image-20210302123021846

  • 在servlet程序中直接配置doget方法和dopost方法
  • 在web.xml文件中配置servlet部分,但是不会配置servlet-mapping方法
4、继承HttpServlet类
  • 我们直接去实现Servlet类的话,会很麻烦
  • 实际开发中我们一般直接继承HttpServlet类
    • 这样我们只需要重写doGet和doPost方法即可
public class demo3 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("post方法");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("get方法");
    }
}

三、ServletConfig类的使用

ServletConfig类:Servlet程序的配置信息类

Servlet程序和ServletConfig对象都是由Tomcat负责创建,我们负责使用。

Servlet程序默认是第一次访问时的创建,而Servlet是每一个Servlet程序创建时就创建一个对应得ServletConfig对象

1、ServletConfig类的三大作用
  • 可以获取Servlet程序的别名servlet-name

  • 可以获取在web.xml配置的初始化参数init-param

    <servlet>
        <servlet-name>demo3</servlet-name>
        <servlet-class>com.wang.servlet.demo3</servlet-class>
        <init-param>
            <param-name>url</param-name>
            <param-value>jdbc:mysql//localhost:8080/test</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>demo3</servlet-name>
        <url-pattern>/demo3</url-pattern>
    </servlet-mapping>
    
  • 获取Servlet-Context对象

2、Servletconfig在哪使用
  • Servletconfig是每个Servlet程序都有一个独立存在的。(数据不能共同)

  • ServletConfig一般在Servlet程序的初始化方法中使用

  • 在直接实现Servlet的Servlet程序中

    @Override
    public void init(ServletConfig config) throws ServletException {
        System.out.println("初始化方法");
        //可以获取Servlet程序的别名servlet-name
        System.out.println("别名"+config.getServletName());
        // 可以获取在web.xml配置的初始化参数init-param
        System.out.println("数据库"+config.getInitParameter("url"));
        // 获取Servlet-Context对象
        System.out.println("ServiceContext"+config.getServletContext());
    }
    
  • 在继承HttpServlet程序中

    @Override
    public void init(ServletConfig config) throws ServletException {
        //注意这句一定要加,否则会空指针异常
        //因为在generalServlet中的构造方法也是init方法(里面主要是有一个保存config的操作),因为我们现在重写了这个init方法,所以generalServlet类中的构造方法就访问不到了所以我们需要用一个super.init(config)来继续调用这个init方法(空指针异常其实就是因为这个config本来会保存,可以调用到,但现在调用不到了。)
        super.init(config);
        System.out.println("初始化方法");
        System.out.println("rename"+config.getServletName());
    }
    

四、ServletContext类

  • ServletContext是一个接口,表示Servlet上下文对象
  • 一个web工程,只有一个ServletContext对象

因为GeneralServlet也实现了ServletConfig接口,所以我们写的类中也有getServletContext方法,

五、HTTP协议

1、GET请求

两部分组成:

1、请求行

2、请求头

image-20210302174134000

  • 请求行:
    • 请求的方式:GET
    • 请求的资源路径:/06_servlet/a.html
      • 一般这里的模板是:请求的资源路径[+?+请求参数]
    • 请求的协议版本号:HTTP/1.1
  • 请求头:
    • key-value: 请求是一堆键值对,每一对都代表不同的含义
    • Accept:告诉服务器,客户端可以接受的数据类型
    • Accept-Language:告诉服务器客户端的可接受语言
      • 中文:zh-cn
      • 英文:en-us
    • User-Agent:人的代理即浏览器的信息
    • Accept-Encoding:告诉服务器,客户端可以接受的数据编码(压缩)格式
    • Host:服务器ip和需要访问的端口号
    • Connection:告诉服务器请求连接怎么处理
      • Keep-Alive:告诉服务器回传数据之后一段时间不要关闭,保持一段时间的连接
      • Closed:断开连接
2、POST请求
  • 隐藏域:

    • <form action="http://localhost:8080/servlet03/demo3" method="post">
          //这两个hidden就是隐藏域,我们会在请求体中看到这两个数据
          <input type="hidden" name="action" value="login">
          <input type="hidden" name="username" value="rooot">
          
          <input type="submit">
      </form>
      
  • 先行了解:POST请求和GET请求区别主要是POST请求多了一个请求体(用来存放传递的数据)

image-20210302193948081

3、哪些时GET请求哪些时POST请求
  • 一般情况下都是GET请求
  • from标签中type=“hidden”是一种POST请求
4、响应的HTTP协议介绍

image-20210302195536048

5、常用的响应码

image-20210302195936302

6、MIME数据类型说明

image-20210302200510018

7、谷歌查看原始HTTP协议

image-20210302201151887

  • 响应体的数据谷歌会单独放在一个repose中

    image-20210302201436090

  • General部分是全局请求信息

    image-20210302201814903

六、HttpServletRequest类

image-20210302202221838

1、HttpServletRequest常用API
  • uri和url区别:
    • 都可以准确的定位一个东西,但url是uri子集
    • uri主要是用一定的规则,比如身份证号码定位一个人一样定位一个资源(可以是相对路径,因为在这个工程中这个资源的相对路径是唯一对应的)
    • url主要偏向于用绝对路径定位一个人,url=协议+主机+端口号+uri

image-20210302211648484

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //获取请求的资源路径
    System.out.println("URI-->>"+req.getRequestURI());
    //获取请求的统一资源定位符
    System.out.println("URL-->>"+req.getRequestURL());
    //获取客户端的ip地址,由于本机测试很有可能出现0:0:0:0:0:0:0:1这种IPV6的ip地址(正常)
    System.out.println("客户端IP地址-->>"+req.getRemoteHost());
    //获取请求头
    System.out.println("请求头-->>"+req.getHeader("user-agent"));
    //获取请求的参数----getParamter()方法
    //获取请求的多个参数----getParamterValues()方法
    //获取请求的方式
    System.out.println("请求方式-->>"+req.getMethod());
}


//获取请求的参数,获取请求转发对象单独重点讲解
  • 结果
URI-->>/servlet03/demo2
URL-->>http://localhost:8080/servlet03/demo2
客户端IP地址-->>0:0:0:0:0:0:0:1
请求头-->>Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko)              Chrome/88.0.4324.104 Safari/537.36
请求方式-->>GET
2、在get请求中获取请求参数
  • html界面模拟提交数据
<form action="http://localhost:8080/servlet03/demo2" method="get">get请求<br/>
    用户名:<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="js">JavaScript<br/>

    <input type="submit">
</form>
  • Servlet程序模拟接受数据
//获取请求的参数----getParamter()方法
//获取请求的多个参数----getParamterValues()方法
System.out.println("输入的用户名"+req.getParameter("username"));
System.out.println("输入的密码"+req.getParameter("password"));
//这里列表不能直接打印出来,我们需要用到工具类
System.out.println("选择的爱好"+ Arrays.asList(req.getParameterValues("hobby")));
  • 结果
输入的用户名wang
输入的密码123456
选择的爱好[cpp, java, js]
3、在post请求中获取请求参数
  • 在html中把form的method改成post即可(在HttpServlet中重写的Service方法会自动根据请求的方式调用不同的方法如doGet方法和doPost方法)

  • Servlet程序不需要改(暂时)

    • 传输数据是中文时会报错

    • req.setCharacterEncoding("UTF-8");
      //一般来说都是要统一设置字符集编码为UTF-8的
      
4、请求转发
  • 服务器收到请求之后,从一个资源跳转到另一个资源的操作叫做请求转发(注意:url不会发生改变)
image-20210303115000451
  • html部分

    <form action="http://localhost:8080/servlet04/enter">
            用户名:<input type="text" name="username" placeholder="用户名"><br/>
    
            密码:<input type="password" name="password" placeholder="密码"><br/>
    
            兴趣爱好:<input type="checkbox" name="hobby" value="cpp">C++
            <input type="checkbox" name="hobby" value="java">java
            <input type="checkbox" name="hobby" value="js">JavaScript<br/>
    
            <input type="submit">
    </form>
    
  • enter部分

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //检查参数
        String username = req.getParameter("username");
        System.out.println("enter检查参数-->>"+username);
        //在检查了参数之后就传一个已查到传到域对象处,后面的Servlet就调用这个域对象的键就可以知道这个参数是否经过了Servlet
        req.setAttribute("inspect_status","inspected");
        //开始转发
        /*
        *   这里的/代表http://ip:port/工程名
        */
        RequestDispatcher Dispatcher = req.getRequestDispatcher("/login");
        Dispatcher.forward(req,resp);
    }
    
  • login部分

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //检查参数
        String username = req.getParameter("username");
        System.out.println("login检查参数-->>"+username);
        //检查域对象
        Object respect_status = req.getAttribute("inspect_status");
        System.out.println("login检查respect_status-->>"+respect_status);
    }
    
  • 请转发的特点

    image-20210303115742699

    • 共享request域中的数据,这也是为什么我们使用ServletContext类,我们这里将数据键值对放到req域中,之后的转发中通过forword(req,resp)又把这个req当作参数传给了转发对象

    • 一般web-inf下文件时不能直接访问的,但是通过转发时可以是实现的

      RequestDispatcher requestDispatcher = req.getRequestDispatcher("/WEB-INF/hello.html");
      requestDispatcher.forward(req,resp);
      
5、base标签(html、jsp)
<!DOCTYPE html>
<html lang="zh_CN">
<head>
    <meta charset="UTF-8">
    <title>注意项界面</title>
<!--    一般来说base标签下我们只需要放置自己这个文件的访问目录即可-->
<!--    后面的资源路径可以省去,只显示一个目录路径即可-->
    <base href="http://localhost:8080/servlet04/a/b/">
</head>
<body>
a下的b下的c.html
<a href="../../index.html">首页</a>
</body>
</html>
  • 注意:a标签下的index.html路径时根据当前url来跳转的
    • url是http://localhost:8080/servlet04/a/b/c.html时,…/…/index.html相对路径会跳转到http://localhost:8080/servlet04/index.html(这个时html之间跳转)
    • url是http://localhost:8080/servlet04/demo3时,…/…/index.html相对路径会跳转到http://localhost:8080/index.html(这个是Servlet程序转发,我们会发现这个跳转肯定会发生错误,所以我们就需要base标签)
  • base标签就是为了设置一个默认的参考相对路径的url,这样html就不会根据当前url来判断跳转路径了
6、路径中斜杆的含义
  • “/“ 被浏览器解析,得到的地址是:http://ip:port
    • 一般存在于html,jsp中
  • “/” 被服务器解析,得到的地址是:http://ip:port/工程路径
    • 一般存在于Servlet程序中,其中的各种API中
  • 特殊情况:response.sentRediect("/");把斜杠发送给浏览器解析,得到http://ip:port/ (重定向)

七、HttpServletResponse类

image-20210303170724367

1、两个响应流
  • outputStream();字节流
  • getWrite();字符流
  • 两个响应流只能用一个
2、解决响应中文乱码

注意我们这里的方法都需要在获取流之前完成

  • 我们需要做的:
    • 把服务器输出格式调为UTF-8格式:resp.setCharsetEncoding(“UTF-8”)
    • 把浏览器接受格式调为UTF-8格式:resp.setHeader(“Content-type”,“text/html;Charset=UTF-8”)
  • 另一种方法:
    • resp.setContentType(“text/html;charset=UTF-8”)
    • 可以直接达到这两种代码的共同作用
3、请求重定向

image-20210303184158997

  • 两个步骤:

    • 设置状态码为302:resp.setStatus(302)
    • 设置重定向地址:resp.setHeader(“Location”,"/servlet04/demo6")
    • 注意这里的重定向地址的斜杠:这里是直接把这个相对路径直接发送给浏览器,由浏览器来解析所以斜杠的意思是http://ip:port/,所以我们还需要加上工程目录
  • 第二种方法:

    • resp.sendRedirect("/servlet04/demo6")
    • 这个方法可以直接一步到位
  • 重定向特点

)

  • 把浏览器接受格式调为UTF-8格式:resp.setHeader(“Content-type”,“text/html;Charset=UTF-8”)
  • 另一种方法:
    • resp.setContentType(“text/html;charset=UTF-8”)
    • 可以直接达到这两种代码的共同作用
3、请求重定向

[外链图片转存中…(img-HwjzyycY-1615108468040)]

  • 两个步骤:

    • 设置状态码为302:resp.setStatus(302)
    • 设置重定向地址:resp.setHeader(“Location”,"/servlet04/demo6")
    • 注意这里的重定向地址的斜杠:这里是直接把这个相对路径直接发送给浏览器,由浏览器来解析所以斜杠的意思是http://ip:port/,所以我们还需要加上工程目录
  • 第二种方法:

    • resp.sendRedirect("/servlet04/demo6")
    • 这个方法可以直接一步到位
  • 重定向特点

    image-20210303191827778

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值