作为servlet

作为servlet

本篇对应《head first servlet and jsp》的第四章。该章节通过servlet为引子,讲解了请求和响应。从这一章中应该更加清楚的认识到servletMVC中应该扮演的是controller的角色。

因为该章大部分的篇幅在API的介绍上,这些部分就请读者自行翻阅吧。

当然也意味着,我的这篇博客变短了 இ௰இ

servlet的一生

servlet的证明周期很简单,当然这些都是由容器来管理的,我们并不是非常需要关注他们的。这里的例子沿用上一篇博客的servletStudy

Web容器servlet类servlet对象
加载类servletStudy.class还不存在呢
实例化servlet(构造函数运行中)没你事了😫对象初现👶
初始化函数init()😫初始化👦
service()😫处理客户请求💪
destroy()😫生命结束了👴

以上方法都继承自Servlet接口,不过你自己写servlet的时候继承的是HttpServlet,然后HttpServlet又继承自GenericServlet,最后是GenericServlet实现了Servlet接口并覆盖了init方法。关系还是蛮复杂的嘛(◎﹏◎)

之前说到容器会为每个servlet创建一个独立的线程,那么在这个线程里去处理客户的请求吗(◎﹏◎)?

servlet的线程

我们的servlet实例永远只会起一个线程(我说的当然是一个servlet类只会起一个线程)(●ˇ∀ˇ●)那么当用户A发起一个请求1后,容器为其创建一个线程A之后。在那之后用户B发起一个请求1

疑问1

那么用户B是进入到线程A来吗?

回答是❌,实际上每一个请求都在一个单独的线程中运行!容器会为用户B创建一个线程B来处理这个请求1

疑问2

这时或许会有一个疑问,如果用户A又发起了一个请求2,那么这个请求2是进入到线程A里面吗?

很可惜回答又是❌,我们仔细的看看这句话。

实际上每一个请求都在一个单独的线程中运行!

我想你的心中已经有了答案💡吧?

虽然请求2用户A发出的,但是这跟他是用户A还是用户B发出的没有任何关系哦,所以事实上容器会创建线程C来处理请求2

疑问3

这时又有人提出了一个问题,如果容器使用了集群,这个应用分在了很多JVM上,那么情况是怎么样的呢?

这个问题的答案非常的简单,每个JVM做的事情都跟上面说的一样,使用了集群不过是 J V M ∗ N JVM*N JVMN罢了。

也就说如果上面的情况不论出现在了JVM1或在JVM2或者是JVMn处理方式都是一样的。

每个特定servlet在这个每个JVM中都有且仅有一个实例,并且JVM会为该servlet的请求创建独立的线程。

ServletConfig和ServletContext

详细的将会在下一章介绍

ServletConfig

  • 每个servlet有一个ServletConfig对象
  • 用于向servlet传递部署时信息
  • 用于访问ServletContext
  • 参数在部署描述文件中配置

ServletConfig是一个接口由GenericServlet实现并作为其成员。但是我们先把目光放到ServletConfig接口吧。
我们进入ServletConfig再看看。记住这些方法名,可以看到这些方法都在GenericServlet中得到了实现。

package javax.servlet;

import java.util.Enumeration;

public interface ServletConfig {
    String getServletName();

    ServletContext getServletContext();

    String getInitParameter(String var1);

    Enumeration getInitParameterNames();
}

我们来看看GenericServlet,我摘取了需要讲解的部分,这并不是GenericServlet的全部哦`(>﹏<)′

public abstract class GenericServlet implements Servlet, ServletConfig, Serializable {
    private static final String LSTRING_FILE = "javax.servlet.LocalStrings";
    private static ResourceBundle lStrings = ResourceBundle.getBundle("javax.servlet.LocalStrings");
    private transient ServletConfig config;
    
    public void init(ServletConfig config) throws ServletException {
        //每个servlet有一个ServletConfig对象
        this.config = config;
        this.init();
    }
    
    public ServletConfig getServletConfig() {
        return this.config;
    }
    
    public String getServletName() {
        ServletConfig sc = this.getServletConfig();
        if (sc == null) {
            throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));
        } else {
            return sc.getServletName();
        }
    }
    //用于访问ServletContext
    public ServletContext getServletContext() {
        ServletConfig sc = this.getServletConfig();
        if (sc == null) {
            throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));
        } else {
            return sc.getServletContext();
        }
    }
    
    public Enumeration getInitParameterNames() {
        ServletConfig sc = this.getServletConfig();
        if (sc == null) {
            throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));
        } else {
            return sc.getInitParameterNames();
        }
    }
    
    public Enumeration getInitParameterNames() {
        ServletConfig sc = this.getServletConfig();
        if (sc == null) {
            throw new IllegalStateException(lStrings.getString("err.servlet_config_not_initialized"));
        } else {
            return sc.getInitParameterNames();
        }
    }
}

ServletContext

  • 每个应用有一个ServletContext

  • 用于访问Web应用参数

  • 相当于应用中的一个公告栏,可以在这里放消息(称之为属性),应用的其他部分可以访问这些消息

  • 用于得到服务器信息,包括容器的名字和版本以及所支持的API版本等

我们把目光放回到ServletConfig这个接口

package javax.servlet;

import java.util.Enumeration;

public interface ServletConfig {
    String getServletName();

    ServletContext getServletContext();

    String getInitParameter(String var1);

    Enumeration getInitParameterNames();
}

看到第2个方法了吗?获取ServletContext就是从这里,那么ServletContext干了什么呢?就自己去看源码吧,下一章会讲的(*^_^*)

OK 话题好像扯远了呢?┗|`O′|┛ 嗷~~ 虽然好像我们一直在说的都是servlet。但是从这里开始《head first servlet and jsp》说的都是关于请求和响应了,请求就是GETPOST这些,而这些并不是我这篇博客想要说的东西,想要了解的话就去阅读该书📕的第4章剩余部分吧。接下来的内容只是一些记录的笔记而已了。

也就是说从这里开始,你已经可以点❌离开这篇博客了,下面是我的个人时间🕐

曾经遇到的一个问题

在某个视频中学重定向的时候,对于URL路径的设定出了点问题导致出现了404,在阅读到这里后找到了答案💡,果然看书📕还是很棒的

在使用sendRedirect方法时使用相对路径有2种

  • 前面有斜线👉👉👉/
  • 前面没有斜线

以我的博客地址为例吧https://highway2020.life(疯狂明示😋😋😋)

我们现在进入将一个请求发送至一个叫hello.doservlet

https://highway2020.life/hello/hello.do

我们在这个servlet里发现无法处理这个请求,需要重定向到另外一个页面

sendRedirect("help/help.html");

容器会相对于原先的URL请求建立完整的URL ,用通俗的话来说就是会在拼接到原请求URL的后面,重定向的URL是这样的

https://highway2020.life/hello/help/help.html

但是如果我们是用斜线开头的呢?

sendRedirect("/help/help.html");

容器会相对于Web应用本身建立完整的URL ,用通俗的话来说就是会在拼接到Web应用URL的后面,重定向的URL是这样的

https://highway2020.life/help/help.html

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值