servlet详解

Servlet

servlet有初始化、服务、销毁等方法,可以表示一个servlet的生命周期

Init         初始化
Service      服务
Destory      销毁

一个生命周期的方法

public class ServletLife implements Servlet {

    @Override
    public void init(ServletConfig config) throws ServletException {
        System.out.println("init()方法执行了,servlet对象开始初始化...");

    }

    @Override
    public void service(ServletRequest req, ServletResponse res)
            throws ServletException, IOException {
        System.out.println("service()方法执行了,servlet对象开始运行...");

    }
    @Override
    public void destroy() {
        System.out.println("destroy()方法执行了,servlet对象销毁...");

    }

    @Override
    public ServletConfig getServletConfig() {
        System.out.println("getServletConfig()方法执行了,获取servlet配置对象...");
        return null;
    }

    @Override
    public String getServletInfo() {
        System.out.println("getServletInfo()方法执行了,获取servlet信息...");
        return null;
    }
}

在web.xml里的配置

servlet>
    <description></description>
    <display-name>AServlet</display-name>
    <servlet-name>AServlet</servlet-name>
    <servlet-class>com.qun.ecoding.AServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>AServlet</servlet-name>
    <url-pattern>/AServlet</url-pattern>//浏览器访问路径
  </servlet-mapping>

总结
servlet的生命周期:

  1. 生命周期所有三个方法init、service、destory;

  2. 请求第一次访问时被创建并初始化(init方法执行,初始化),只执行一次

  3. 每次处理请求service就会被执行一次

  4. 销毁方法在销毁Servlet之前执行;只执行一次;

特点:

  1. Servlet是单例模的,(但是我可以写AServlet、BServlet、CServlet都可以创建对象)
    一个对象同时应对多个请求时,就会出现线程安全问题,所以servlet线程不安全;

  2. Servlet有我们来写,但是对象由服务器创建,并且由服务器调用相关的方法;

**先记住,Servlet(默认)是第一次访问的时候实例化、然后初始化、service、destroy..
但是Servlet是在第一次访问被实例化的说法不准确**

ServletConfig

Servletconfig 是一个servlet对象的配置对象,servletConfig对象中封装了一个servlet对象的配置信息。
Servlet对象的配置信息在web.xml中。

一个servlet对象对应一个servletconfig,100个servlet对象对应100个servletconfig对象

Servlet有个 getServletConfig() 返回值是ServletConfig,可以通过API查看得到;

public class ServletConfig extends GenericServlet{

    @Override
    public void service(ServletRequest req, ServletResponse res)
            throws ServletException, IOException {

        //获取配置对象
        javax.servlet.ServletConfig config = getServletConfig();

        //获取web.xml中servlet-name
        String name = config.getServletName();
        System.out.println("servlet名称为:"+name);

        //获取web.xml中<Parameter-value>的值
        String value = config.getInitParameter("用户名");
        System.out.println("初始化参数的值为:"+value);

        Enumeration<String> names = config.getInitParameterNames();
        while (names.hasMoreElements()) {
            String initName = (String) names.nextElement();
            System.out.println(initName);

            //通过名称获取value值
            String initvalue = config.getInitParameter(initName);
            System.out.println(initvalue);
        }

        //通过servletConfig对象获取servletContext对象
        ServletContext context = config.getServletContext();
        System.out.println(context);
    }
}

ServletContext

1.ServletContext概述

服务器会为每个应用创建一个ServletContext对象:

  • ServletContext对象的创建是在服务器启动时完成的;
  • ServletContext对象的销毁是在服务器关闭时完成的。

ServletContext对象的作用是在整个Web应用的动态资源之间共享数据!

例如,在AServlet中向ServletContext对象中保存一个值,然后在BServlet中就可以获取这个值,这就是共享数据了。
一个项目只有一个ServletContext对象!通常给他的对象名取为application。

2.获取ServletContext对象

public class Servlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) {
ServletContext context = this.getServletContext();}}

为什么能使用this,因为是Servlet的对象来调用这个方法,Bservlet继承自HttpServlet,所以可以使用this.getServletContext()。

3.ServletContext的使用

jsp四大作用域

PageContext     page          在当前页面那种有效       抽象类
ServletRequest  request       在当前请求中有效         接口
HttpSession     session       当前会话中有效           接口
ServletContext  application   在所有应用程序中有效      接口

所有域对象都有存取数据的功能,因为域对象内部有一个Map,用来存储数据,下面是ServletContext对象用来操作数据的方法:

  • void setAttribute(String name, Object value):用来存储一个对象,也可以称之为存储一个域属性,例如:servletContext.setAttribute(“xxx”, “XXX”),在ServletContext中保存了一个域属性,域属性名称为xxx,域属性的值为XXX。请注意,如果多次调用该方法,并且使用相同的name,那么会覆盖上一次的值,这一特性与Map相同;

  • Object getAttribute(String name):用来获取ServletContext中的数据,当前在获取之前需要先去存储才行,例如:String value = (String)servletContext.getAttribute(“xxx”);,获取名为xxx的域属性;

  • void removeAttribute(String name):用来移除ServletContext中的域属性,如果参数name指定的域属性不存在,那么本方法什么都不做;

  • Enumeration getAttributeNames():获取所有域属性的名称;

    public class BServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取servletContext域对象
        ServletContext context = getServletContext();
        //通过context取出域中的数据
        String attr = (String) context.getAttribute("姓名");
        System.out.println(attr);
    }
    

    }

4.ServletContext获取公共的初始化参数

public class CServlet extends HttpServlet {

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

        //获取servletContent对象
        ServletContext application = getServletContext();
        //获取web.xml的初始化参数
        String val = application.getInitParameter("姓名");
        System.out.println(val);


        Enumeration<String> names = application.getInitParameterNames();
        while (names.hasMoreElements()) {
            //获取单个参数名称
            String name = (String) names.nextElement();
            System.out.println(name);
            //获取单个参数值
            String value = application.getInitParameter(name);
            System.out.println(value);
        }
    }
}

xml中的内容

<context-param>
        <param-name>工程师</param-name>
        <param-value>张三</param-value>
    </context-param>
    <context-param>
        <param-name>总经理</param-name>
        <param-value>李四</param-value>
    </context-param>
    <context-param>
        <param-name>总裁</param-name>
        <param-value>王五</param-value>
    </context-param>

5.ServletContext获取资源相关方法

public class DServlet extends HttpServlet {

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

        //获取context对象
        ServletContext application = getServletContext();
        //获取login.html的本地磁盘真是路径
        String realPath = application.getRealPath("login.html");
        System.out.println(realPath);

        //获取test.text文件的真实路径
        String realPath2 = application.getRealPath("/WEB-INF/test.txt");
        System.out.println("txt文件的路径为"+realPath2);

        //以流的形式获取资源
        InputStream stream = application.getResourceAsStream("/WEB-INF/test.txt");
        System.out.println(stream);
    }
}

Response

1.Response概述

sponse是Servlet.service方法的一个参数,类型为javax.servlet.http.HttpServletResponse。在客户端发出每个请求时,服务器都会创建一个response对象,并传入给Servlet.service()方法。response对象是用来对客户端进行响应的,这说明在service()方法中使用response对象可以完成对客户端的响应工作。

response对象的功能分为以下四种:

  • 设置响应头信息;

  • 发送状态码;

  • 设置响应正文;

  • 重定向;(Servlet===》Servlet;Servlet===》a.html)

2.Response对象发送状态码

常见状态码:

200 成功、

302 重定向、

404 路径错误(可能是资源不存在导致的)

405:提交方式不支持(如果你是get提交,但是只有doPost方法);

500 服务器内部错误(有可能代码写错了)

sendError(int sc);            发状态码
sendError(int sc,String msg)  发送状态码同时发送消息
setStatus(int sc);            设置状态码

3.响应头完成重定向

setHeader(String name,String value);适用单个响应头

addHeader(String name,String value);适用多个响应头

重定向状态码是302; 响应头对象的是Location:url

public class EServlet extends HttpServlet {

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

        System.out.println("我要重定向。。。");
        //通过相应头重定向到FServlet
        resp.setHeader("Location", "/servlet02/FServlet");
        resp.setStatus(302);

    }
}

//重定向到FServlet
public class FServlet extends HttpServlet {

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

        System.out.println("重定向到了FServlet");
    }
}

4.响应头完成定时刷新

public class DServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //在页面输出一句话,使用汉语会乱码以后再讲
        PrintWriter writer = response.getWriter();
        writer.print("3秒以后跳转到另外一个页面");
        response.setHeader("Refresh", "3;url=/servelt/EServlet");
    }
}
public class EServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        response.getWriter().println("看我乱码依旧!");
    }
}

5.响应头完成普通字符数据和图片字符数据

public class GServlet extends HttpServlet {

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

        resp.getWriter().print("汉字乱码");

        //1.通过response对象给浏览器响应字符数据
        String string = "loveDOUDOU";
        //响应字符时需要将字符转化为字符数组
        byte[] bytes = string.getBytes();
        //通过输出流输出到浏览器
        resp.getOutputStream().write(bytes);

        //2.通过response对象给浏览器响应字节数据(图片)
        String path = "D:\\123.jpg";
        //将图片转化为流输入到内存
        FileInputStream fileInputStream = new FileInputStream(path);
        //将输入流转化为数组
        byte[] byteArray = IOUtils.toByteArray(fileInputStream);
        //通过输出流输出
        resp.getOutputStream().write(byteArray);
    }
}

响应头快捷重定义方法

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

        //1.重新定向本地路径
        resp.sendRedirect("/servlet02/FServlet");

        //2.重新定向到网络资源
        resp.sendRedirect("http://www.baidu.com");
    }
}

Resquest

1.Resquest的概述

request是Servlet.service()方法的一个参数,类型为javax.servlet.http.HttpServletRequest。在客户端发出每个请求时,服务器都会创建一个request对象,并把请求数据封装到request中,然后在调用Servlet.service()方法时传递给service()方法,这说明在service()方法中可以通过request对象来获取请求数据。

request的功能可以分为以下几种:(重点)

  • 封装了请求头数据;

  • 封装了请求正文数据,如果是GET请求,那么就没有正文;

  • request是一个域对象,可以把它当成Map来添加获取数据;

request提供了请求转发和请求包含功能

一个web应用只有一个ServletContext即application,所以在一个Servlet的app里存值,在另外一个Servlet的app里可以取到值;但是,一个web应用对应多个reqeust,在request1里存值,在reqeust2里取不到值;

 request的常用方法
    System.out.println(req.getRemoteAddr());
    System.out.println(req.getMethod());
    req.setCharacterEncoding("utf-8");
    System.out.println(req.getCharacterEncoding());
    System.out.println("serverName:"+req.getServerName());
    System.out.println(req.getServerPort());

2.获取请求路径的方法

public class AServlet extends HttpServlet {

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

        // 获取请求路径的常用方法

        //servlet02/AServlet
        System.out.println("URL"+req.getRequestURL());

        //http://localhost:8080/servlet03/AServlet返回请求的URL路径
        System.out.println("URL:"+req.getRequestURL());

        //项目名/servlet03(重要)获取项目名
        System.out.println(req.getContextPath());

        //获取servlet路径/IServlet(重要)获取路径
        System.out.println(req.getServletPath());


    }d
}

3.请求转发和请求包含

请求转发(forward:转发)

请求转发:由下一个Servlet完成响应体!当前Servlet可以设置响应头!不能设置响应体,非得设置响应体可能会出现异常;(BServlet留头不留体,)BServlet完成不了去找CServlet完成;CSservlet能设置响应头;

public class BServlet extends HttpServlet {

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

        resp.setHeader("bb", "BBB");
        //不具备表现能力
        resp.getWriter().print("BServlet");
        //获取转发对象并转发
        req.getRequestDispatcher("/CServlet").forward(req, resp);
    }
}


public class CServlet extends HttpServlet {

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

        resp.setHeader("cc", "CCCC");
        resp.getWriter().print("CServlet");
    }
}

请求包含(include:包含)

请求包含:将两个资源的输出进行合并后输出由两个Servlet共同来完成响应体!(DServlet留头也留体)两个Servlet共同完成,被包含的不能设置响应头;

public class DServlet extends HttpServlet {

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

        resp.setHeader("ddd", "DDD");
        //具备显示能力
        resp.getWriter().print("DServlet");
        //获取转发器并包含
        req.getRequestDispatcher("/EServlet").include(req, resp);
    }
}

public class EServlet extends HttpServlet {

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

        resp.setHeader("ee", "EEEG");
        resp.getWriter().print("EServlet...");
    }
}

4.Request获取请求参数

最为常见的客户端传递参数方式有两种:

  • 浏览器地址栏直接输入:一定是GET请求;
    http://lcoalhost:8080/项目名称/AServlet?username=zhangsan&password=123456;
  • 超链接:一定是GET请求;
  • 表单:可以是GET,也可以是POST,这取决与的method属性值;

注意:表单提交过来的值都是字符串类型;

GET请求和POST请求的区别:

  • GET请求:

    1. 请求参数会在浏览器的地址栏中显示,所以不安全;

    2. 请求参数长度限制长度在1K之内;

    3. GET请求没有请求体,无法通过request.setCharacterEncoding()来设置参数的编码;

  • POST请求:

    1. 请求参数不会显示浏览器的地址栏,相对安全;

    2. 请求参数长度没有限制;

  • 下面是使用request获取请求参数的API:

    1. String getParameter(String name):通过指定名称获取参数值;

    2. String[] getParameterValues(String name):当多个参数名称相同时,可以使用方法来获取;

    3. Enumeration getParameterNames() 获取所有参数的名字;

    4. Map

5.request域

 Servlet中三大域对象:request、session、application(ServletContext的对象),都有如下三个方法:

void setAttribute(String name, Object value)

Object getAttribute(String name)

void removeAttribute(String name)

同一请求范围内使用request.setAttribute()、request.getAttribute()来传值!

前一个Servlet调用setAttribute()保存值,后一个Servlet调用getAttribute()获取值。(生命周期长,第二个servlet调用第一个servlet保存的值)

区别

parameter用来设置和获取表单给我们传递的值;

Attribute用来传递和获取servlet内部的数据;和域紧密联系到一起;

public class HServlet extends HttpServlet {

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

        //创建student对象
        Stuent stuent = new Stuent();
        //给student赋值
        stuent.setUserName("张三");
        stuent.setUserName("123");
        //向请求域中保存数据
        req.setAttribute("oo", stuent);

        //从请求域中取出数据
        Object object = req.getAttribute("oo");
        //输出到浏览器
        resp.getWriter().print(object);

        //请求转发和重定向的区别

        //转发
        //转发是一次请求,在同一个request作用有中,所以可以共享数据
        req.getRequestDispatcher("/IServlet").forward(req, resp);

        //重定向到IServlet
        //重定向是两次请求,而request作用域只作用于一次请求,不在同一个request作用域中,
        //所以不能共享数据
        resp.sendRedirect("/servlet03-request/IServlet");//null
    }
}

public class IServlet extends HttpServlet {

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

        //从请求域中取出数据
        Object object = req.getAttribute("oo");
        //输出到浏览器
        resp.getWriter().print(object);

    }
}

6.转发和重定向的区别

请求转发和重定向的区别

  • 请求转发是一个请求一次响应,而重定向是两次请求两次响应
  • 请求转发地址栏不变化,而重定向会显示后一个请求的地址
  • 请求转发只能转发到本项目其他Servlet(是Servlet在转发),而重定向不只能重定向到本项目的其他Servlet,还能定向到其他项目(其实是浏览器在重定向)
  • 请求转发是服务器端行为,只需给出转发的Servlet路径,而重定向需要给出 requestURI,即包含项目名!
  • 请求转发和重定向效率是转发高!因为是一个请求!

    <> 需要地址栏发生变化,那么必须使用重定向!

    <> 需要在下一个Servlet中获取request域中的数据,必须要使用转发!

    <> 假如我要跳到百度去,这时候也只能用重定向;

乱码的解决

1.响应乱码的解决

  • 当使用response.getWriter()来向客户端发送字符数据时,如果在之前没有设置编码,那么默认使用iso,因为iso不支持中文,一定乱码
  • 在使用response.getWriter()之前可以使用response.setCharaceterEncoding()来设置字符流的编码为gbk或utf-8,当然我们通常会选择utf-8。这样使用response.getWriter()发送的字符就是使用utf-8编码的。但还是会出现乱码!因为浏览器并不知道服务器发送过来的是什么编码的数据!这时浏览器会使用gbk来解码,所以乱码!
  • 在使用response.getWriter()之前可以使用response.setHeader(“Content-type”,”text/html;charset=utf-8”)来设置响应头,通知浏览器服务器这边使用的是utf-8编码,而且在调用setHeader()后,还会自动执行setCharacterEncding()方法。这样浏览器会使用utf-8解码,所以就不会乱码了!

    public class AServlet extends HttpServlet{

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
        //在服务器响应之前设置编码
        resp.setContentType("text/html;charset=utf-8");
        //向浏览器输出
        resp.getWriter().print("你好");
    }
    

    }

2.get提交方式乱码的解决

public class BServlet extends HttpServlet {

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

        //获取表单数据
        String name = req.getParameter("userName");
        //反编译
        byte[] bytes = name.getBytes("iso-8859-1");
        //重新设置编码格式为utf-8
        String string = new String(bytes,"utf-8");
        System.out.println(string);
    }
}

3.post提交方式乱码的解决

public class CServlet extends HttpServlet {

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

        //在接收数据之前设置编码格式
        request.setCharacterEncoding("UTF-8");
        //获取表单数据
        String name = request.getParameter("userName");
        System.out.println(name);

        //在响应之前设置编码
        response.setContentType("text/html;charset=utf-8");
        //响应给浏览器
        response.getWriter().print(name);
    }
}
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值