Servlet初学

一、概念

1.1  servlet概念:

Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,用Java编写的服务器端程序,具有独立于平台和协议的特性,主要功能在于交互式地浏览和生成数据,生成动态Web内容。 简单来说,Servlet是服务器端的一段程序(代码、功能实现),可交互式的处理客户端发送到服务器的请求,并完成操作响应。并支持动态网页技术。JavaWeb程序开发的基础,JavaEE规范(一套接口)的一个组成部分。它是由服务器厂商实现的。
 

1.2 Servlet的核心作用

       1. 接收客服端请,完成操作任务

       2. 动态生成网页,网页数据可以改变

       3.  将包含操作结果的动态网页响应给客服端

1.3 Servlet的核心目录结构

web :存放需要部署的网站项目

——WEB-INF :核心内容,分别是以下内容

——classes :存放.class文件(XxxServlet.class)

———lib :储存所需jar包

———web.xml :web配置文件

——index.html/index.jsp.index.css/images

见idea目录结构如下图: (因为idea会自动处理部署的文件并打包成war包的形式储存在out文件中,所以我们在使用IDEA时不用自己创建classes文件)

1.4 IDEA工具内创建核心目录结构

因为我们使用的是idea,如果去项目目录创建该Servlet目录结构过于繁琐,所以我们可以使用idea在工具内创建目录结构(可以在配置tomact时提前创建好都是OK的!)

1.5 Servlet的开发步骤

 1.5.1  开发环境   

1、搭建开发环境,并创建Servlet核心目录结构
2、实现javax.serlvet.Servlet接口,覆盖5个方法

3、在核心的servlet()方法中书写输出语句,验证访问结果/

4、将编译后的.class文件放置在WEB-INF/classes中
5、web.xml文件中添加配置信息
 

二、实现Servlet

2.1  创建servlet的三种方法

1.实现servlet接口,重写和接口中的init(),service(),destory()等方法

2.继承GenericServlet,重写父类中的service()方法

3.继承HTTPServlet,重写父类中的doGET()doPost()方法    ->目前用的方法

GenericServlet 是一个抽象类,实现了 servlet 接口
HttpServlet 是一个普通类,继承自 GenericServlet
为什么会有三种方式?
因为 Servlet 技术是不断发展的,先有 Servlet ,再有 GenericServlet ,最后
才有的 HttpServlet HttpServlet 封装了更多的内容,实现了更强大的功
能,所以在接下来的学习中我们都使用 HttpServlet 来实现。

2.2 doGET与doPost()方法的区别

doGet是处理客户端发来的Get请求,doPost是处理客户端发来的Post请求,它们的区别可以从以下几个方面来说明:

1、客户端(一般指浏览器)生成的方式

get:form中method属性为get时;或者直接在URL地址栏中输入URL,需要传递参数时,直接在URL后面拼接?name=张三&age=18这样的查询参数字符串;

post:form中method属性为post。

2、客户端数据传送方式

get:表单数据存放在URL地址后面。所有get方式提交时HTTP中没有消息体;

post:表单数据存放在HTTP协议的消息体中以实体的方式传送到服务器。

3、服务器获取数据方式

get:服务器采用Servlet中的doGet来获取变量的值;

post:服务器采用Servlet中的doPost来获取数据。

4、传输的数据量

get:数据量长度有限制,一般不超过2kb。因为是参数传递,且在地址栏中,故数据量有限制;

post:适合大规模的数据传送。因为是以实体的方式传送的。

5、安全性

get:安全性差。因为是直接将数据显示在地址栏中,浏览器有缓冲,可记录用户信息。所以安全性低;

post:安全性高。因为post方式提交数据时是采用的HTTP post机制,是将表单中的字段与值放置在HTTP HEADER内一起传送到ACTION所指的URL中,用户是看不见的。

6、传输速度上的差别

doget传输速度高于dopost传输速度。

2.3 继承HTTPServlet

HttpServlet抽象类的内部继承了GenericServlet抽象类(证明HttpServlet有了上面我们说到的那四个方法),并扩展提供了适用于Web站点的HTTP协议的几个方法,也就是说HttpServlet的子类至少必须重写一个方法,该方法通常是如下这几个方法:

doGet,如果 servlet 支持 HTTP GET 请求   ---->用于查找
doPost,用于 HTTP POST 请求     ----->增加
doPut,用于 HTTP PUT 请求 
 ----->修改                     -----------restful风格
doDelete,用于 HTTP DELETE 请求   ---->删除
init 和 destroy,用于管理 servlet 的生命周期内保存的资源
getServletInfo,servlet 使用它提供有关其自身的信息
注意:因为我们是继承了GenericServlet抽象类,所以没有理由再去重写 service 方法。service 通过将标准 HTTP 请求分发给每个 HTTP 请求类型的处理程序方法(上面列出的 doXXX 方法)来处理它们。(只需要使用扩展的Http的所需方法即可)

java代码:

public class ServletResourceCode extends HttpServlet {

    @Override
    public void doGet(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse){
        /*
        * 获取前端request传进来的参数
        * */
        System.out.println("接收到通过GET方式传输的参数,用户名:"+
                httpServletRequest.getParameter("username")+
                "密码:"+
                httpServletRequest.getParameter("password"));

    }

    public void doPost(HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse){
        System.out.println("接收到通过POST方式传输的参数,用户名:"+
                httpServletRequest.getParameter("username")+
                "密码:"+
                httpServletRequest.getParameter("password"));
    }
}

index,jsp配置表单

 web.xml配置

2.4 HttpServletRequest对象详解

我们在创建 Servlet 时会覆盖 service() 方法,或 doGet()/doPost(), 这些方法都有两个 参数,一个为代表请求的request 和代表响应 response service ()方法中写了根 据请求方式的不同调用doget() dopost().。 service方法中的request的类型是ServletRequest doGet/doPost方法的request 类型HttpServletRequestHttpServletRequestServletRequest的子接口,功能和 方法更加强大

2.4.1   1 HttpServletRequest常用方法

2.4.1 获得客户机信息:

getRequestURL() 返回客户端发出请求时的完整 URL
getRequestURI() 返回请求行中的参数部分。
getQueryString () 方法返回请求行中的参数部分(参数名 + 值)
getRemoteHost() 返回发出请求的客户机的完整主机名。
getRemoteAddr() 返回发出请求的客户机的 IP 地址。
getPathInfo() 返回请求 URL 中的额外路径信息。额外路径信息是请求 URL
的位于 Servlet 的路径之后和查询参数之前的内容,它以 "/" 开头。

2.4.2 获得客户机请求头

getHeader(string name) String 的形式返回指定请求头的值。
getHeaders(String name) String 对象的 Enumeration 的形式返回指定请求 头的所有值

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

String getParameter(String name) :通过指定名称获取参数值;
String[] getParameterValues(String name) :通过指定名称获取参数值数组, 有可能一个名字对应多个值,例如表单中的多个复选框使用相同的name 时;
Enumeration getParameterNames():获取所有参数的名字;
Map getParameterMap() :获取所有参数对应的 Map ,其中 key 为参数名, value为参数值。
package com.request_reponse;

/**
 * @author zyh
 * @version 1.0
 * @items
 * @Date:on 2021/8/10 at 19:59
 */

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;
import java.util.Map;

/**
 * 1.HttpServletRequest:是servlet中操作请求和响应报文,只不过操作报文的形式是通过这个对象来修改的
 */
public class Request extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        /*
         * 因为servlet容器调用这个servlet的时候会将request这个对象传进来,所以我们直接用这个对象就可以了
         * 为什么servlet的doGet方法或者service()方法不需要返回值?
         *   因为servlet容器会去实例化这一个HttpServletRequest对象,当servlet容器调用这个doGet()方法的时候,传的形参是这个对象的地址,
         *   在doGet()中对这个对象做的修改会实际修改到内存中,所以在doGet()调用完成以后,servlet容器拿到的这个对象就已经是修改好了的了
         *    说白了就是引用类型传参
         *
         * */

        /**
         * 设置请求的编码格式为:UTF-8
         */
        req.setCharacterEncoding("UTF-8");

        /**
         *获取请求的URL和URI  ,URI是servlet在项目中的映射地址 URL是http请求的完整地址
         */
        System.out.println("请求的URL是+"+req.getRequestURL());
        System.out.println("请求的URI是+"+req.getRequestURI());

        //把参数列表打印出来
        System.out.println("请求参数是:"+req.getQueryString());

        /**
         * 浏览器的一些信息
         */
        System.out.println("请求的主机明是:"+req.getRemoteHost());
        System.out.println("请求的主机IP是:"+req.getRemoteAddr());
        System.out.println("请求端口号是:"+req.getRemotePort());


        /**
         * getHead可以根据请求头部的键俩获取相应的值
         */
        System.out.println(req.getHeader("user-agent"));

        /**
         * 获取客服端的请求参数:
         *  1.request.getParameter() -> 原生的servlet用的最多的方法
         *  2.request.getParameterValues() -> 当同一个键有多个值的时候用这个方法
         *  3.request.getParameterName() -> 获取所用的参数名,返回值是一个枚举类
         *  4.request.getParameterMap() -> 以Map的形式获取参数,获得所有的参数键值对
         */

        System.out.println("客服端参数:"+req.getParameter("localhost"));

        Map<String, String[]> map = req.getParameterMap();
        System.out.println(Arrays.toString(map.get("a")));
        System.out.println(Arrays.toString(map.get("b")));

    }
}

2.4.4  请求时中文产生乱码解决思路

直接使用request.setCharacterEncoding("UTF-8")来处理即可

2.5 HttpServletResponse对象详解

HttpServletResponse 对象代表服务器的响应。这个对象中封装了向客户端发送数 据、发送响应头,发送响应状态码的方法。查看HttpServletResponse API ,可以 看到这些相关的方法

2.5.1 负责向客户端(浏览器)发送数据的相关方法:

2.5.2  负责向客户端(浏览器)发送响应头的相关方法

2.5.3 负责向客户端(浏览器)发送响应状态码的相关方法

2.5.4  设置http响应头控制浏览器定时刷新网页(refresh)

package com.request_reponse;

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

/**
 * @author zyh
 * @version 1.0
 * @items
 * @Date:on 2021/8/10 at 21:37
 */

public class Response extends HttpServlet {
    /**
     * 发送数据的方式:
     * 1.response.getOutStream() -->可以向浏览器返回一个二进制文件
     * 2.response.getWriter()  -->这个方PrintWriter对象,可以向浏览器写入HTML文件,
     * 也可以写JSON等其他文件,print和write都能向前端返回数据,但是print的功能要多一点
     *
     */
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        /**
         * 一般来说,我们去写servlet的时候,为了避免乱起,我们都会在前面写上:
         * 1.request.setCharacterEncoding("UTF-8")
         * 2.response.setContentType("MIME类型;charset=utf-8")
         */
        req.setCharacterEncoding("UTF-8");
        /**
         * 设置了返回资源的MIME类型,并且设置了资源的编码为UTF-8
         */
        resp.setContentType("text/html;charset=utf-8");

        /**
         * 设置相应的状态码
         * 可以做一些异常处理的时候,设置响应码
         */
        resp.setStatus(404);

        /**
         * 设置响应头来控制浏览器的行为:
         * response.setHeader();
         * 1.控制浏览器刷新的页面
         * 2.控制浏览器重定向  -->重定向后 Http状态码会修改为302
         */
        //resp.setHeader("Refresh","5;url=/request");
        resp.sendRedirect("/request");

    }
}

三、 重定向和转发

3.1 转发

案例

需求

​ 实现从OneServlet中转发到TwoServlet

步骤

  1. OneServlet向请求域中添加了一个键和值,转发给TwoServlet
  2. TwoServlet就从请求域中取出键和值,打印到浏览器上。

效果

在这里插入图片描述

代码:

oneservlet

package com.itheima.servlet;

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

/**
 与请求域相关的方法
 */
@WebServlet(name = "Demo6OneServlet", urlPatterns = "/one")
public class Demo6OneServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.print("这是One<br/>");
        //向请求域中添加键和值
        request.setAttribute("name","Jack");
        request.setAttribute("age", 20);  //整数类型
        String name = (String) request.getAttribute("name");
        int age = (int) request.getAttribute("age");
        //从请求域中取出值
        out.print("名字:" + name + "<br/>");
        out.print("年龄:" +  age );
        out.print("<hr/>");
        //删除其中一个
        request.removeAttribute("age");

        //从请求域中取出值,直接输出Object对象
        out.print("名字:" + request.getAttribute("name") + "<br/>");
        out.print("年龄:" +  request.getAttribute("age") );

        System.out.println("这是one");
        //开始转发,参数是:要跳转到的地址
        request.getRequestDispatcher("/two").forward(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

TowServlet

package com.itheima.servlet;

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

//从请求域中取出值
@WebServlet(name = "Demo7TwoServlet", urlPatterns = "/two")
public class Demo7TwoServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.print("这是Two,从请求域中取出one中的值:" + request.getAttribute("name"));
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

转发的特点
地址栏不发生变化,显示的是上一个页面的地址
请求次数:只有1次请求
根目录:http://localhost:8080/项目地址/,包含了项目的访问地址
请求域中数据不会丢失
转发使用哪个方法?

request.getRequestDispatcher("/地址").forward(request, response);
 

3.1  请求重定向指:

一个 web 资源收到客户端请求后,通知客户端去访问另外一个 web 资源,这称之为请求重定向。

重定向案例

需求

从OneServlet重定向到TwoServlet

步骤

  1. 在OneServlet中向请求域中添加键和值
  2. 使用重定向到TwoServlet,在TwoServlet中看能否取出请求域的值

代码:

oneservlet

package com.itheima.servlet;

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

/**
 与请求域相关的方法
 */
@WebServlet(name = "Demo6OneServlet", urlPatterns = "/one")
public class Demo6OneServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.print("这是One<br/>");
        //向请求域中添加键和值
        request.setAttribute("name","Jack");
        request.setAttribute("age", 20);  //整数类型
        String name = (String) request.getAttribute("name");
        int age = (int) request.getAttribute("age");
        //从请求域中取出值
        out.print("名字:" + name + "<br/>");
        out.print("年龄:" +  age );
        out.print("<hr/>");
        //删除其中一个
        request.removeAttribute("age");

        //从请求域中取出值,直接输出Object对象
        out.print("名字:" + request.getAttribute("name") + "<br/>");
        out.print("年龄:" +  request.getAttribute("age") );

        System.out.println("这是one");
        //开始转发,参数是:要跳转到的地址
        //request.getRequestDispatcher("/two").forward(request, response);

        //使用重定向
        response.sendRedirect("two");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

twoservlet

package com.itheima.servlet;

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

//从请求域中取出值
@WebServlet(name = "Demo7TwoServlet", urlPatterns = "/two")
public class Demo7TwoServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.print("这是Two,从请求域中取出one中的值:" + request.getAttribute("name"));
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

重定向的特点
地址栏:显示新的地址
请求次数:2次
根目录:http://localhost:8080/ 没有项目的名字
请求域中的数据会丢失,因为是2次请求
疑问  问:什么时候使用转发,什么时候使用重定向?

如果要保留请求域中的数据,使用转发,否则使用重定向。

以后访问数据库,增删改使用重定向,查询使用转发。

问:转发或重定向后续的代码是否还会运行?

无论转发或重定向后续的代码都会执行

小结:重定向和转发的区别

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值