JAVA Servlet

Servlet

Servlet是SUN公司提供的一门用于开发动态WEB资源的技术。

SUN公司在其API中提供了一个Servlet接口。

用户若想开发一个动态WEB资源(即开发一个Java程序向浏览器输出数据),需要完成以下2个步骤:

1、编写一个Java类,实现Servlet接口

2、把开发好的Java类部署到WEB服务器中

Servlet简单编写

一个简单的回显的Java类,这里一个HelloWorld继承了HttpServlet,而跟进去可以发现HttpServlet已经实现了Servlet的接口了,并且还封装了一些东西来让我们方便使用,比如GET POST等的方法...

public class HelloWorld extends HttpServlet {


    public void doGet(HttpServletRequest request, HttpServletResponse response)
    throws IOException, ServletException
    {
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        out.println("<html>");
        out.println("<head>");
        out.println("<title>Hello World!</title>");
        out.println("</head>");
        out.println("<body>");
        out.println("<h1>Hello World!</h1>");
        out.println("</body>");
        out.println("</html>");
    }

当写完Servlet的类之后,还需要映射到对应的web.xml中的路由,这样web容器类似tomcat来知道你请求的路径是哪个Servlet来进行处理

此时访问/adezz,则由Hello这个类来进行处理请求和回复

<servlet>
  <servlet-name>MyHello</servlet-name>
  <servlet-class>com.zpchcbd.servlet.Hello</servlet-class>
</servlet>

<servlet-mapping>
  <servlet-name>MyHello</servlet-name>
  <url-pattern>/adezz</url-pattern>
</servlet-mapping>

Servlet 工作原理

先说下Servlet接口中需要实现的如下方法:

public interface Servlet {
    void init(ServletConfig var1) throws ServletException;
    ServletConfig getServletConfig();
    void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
    String getServletInfo();
    void destroy();
}

继续看Servlet运行的如下流程图:

1、第一步客户发送http request到ServletContainer(不知道这个是什么东西)

2、然后ServletContainer接受到了

3/4、可以看到ServletContainer在接收Client请求的时候,在第三步和第四步分别创建一个HttpServletRequest实例化的对象和一个HttpServletResponse实例化的对象

5、 ServletContainer又会调用service方法

6/7、service方法就会获取HttpServletRequest,HttpServletResponse这两个实例化的对象进行处理,并且通过对应的http方法来处理HttpServletRequest实例化的对象,将结果设置给HttpServletResponse对象

总结:init()方法仅在服务器装载Servlet时才由服务器执行一次,而每次客户向服务器发请求时,服务器就会调用Service()方法。

1、init的函数:这个函数是当我们的 Servlet运行起来后,服务器会对所需要用到的java类文件进行一次编译生成.class文件,然后在之后的请求中都不会进行重新编译,这也就导致了我们此时在java类文件中怎么修改,web页面都不会出现改变,除非我们重启tomcat服务器,来对Servlet实现重新运行!

2、Service的函数:也是Servlet的核心,负责接受/响应客户的请求。Servlet默认情况下,不管是get请求还是post请求,都会经过service()方法来处理,之后在转到相应的doGet或doPost方法上,比如如下正常的GET请求:

3、 Destroy()方法:仅运行一次。在server端停止且卸载Servlet时运行该方法。

Servlet的上下文Context

什么是Context上下文?就是一个保证能程序运行所依赖的东西,也就是上下文中保存了程序需要运行的必须的东西!

在C里面的Context上下文保存的就是CPU中每个寄存器的数据,每个线程运行都需要一个CPU,那么线程怎么知道自己运行到哪里了,那么依赖的就是Context上下文这个结构体,这个结构体就能够说明当前线程跑到了哪里!

那么这里也是类似的理解,多个Servlets所依赖的上下文就是ServletContext,个人理解就是ServletContext中的一些数据能够保证Servlets稳定运行

所以ServletContext中也会存储着一些信息,比如session会话和一些配置信息,我们这里可以直接看ServletContext源码,它是一个接口

public interface ServletContext //这是一个接口

public static final String TEMPDIR = "javax.servlet.context.tempdir"; //用来存储ServletContext的属性的临时目录

public String getContextPath(); //返回当前ServletContext上下文的路径

public ServletContext getContext(String uripath); // 返回一个URL路径的Context对象,撒子玩意 不太懂

public int getMajorVersion(); //获取主要版本

public int getMinorVersion(); //获取次要版本

public Set<String> getResourcePaths(String path);// 获取所有的资源路径(返回指向资源的所有路径的类似目录的列表),并且返回的是一个String的集合

public URL getResource(String path) //获取路径的资源,不太理解

public Servlet getServlet(String name)//获取指定的Servlet程序的对象

public Enumeration<Servlet> getServlets() //获取所有的Servlet程序的对象,返回时一个Servlet类型的Enumeration

public Enumeration<String> getServletNames(); //获取所有的Servlet程序对象的名称

public Object getAttribute(String name); //获取Servlet中有指定name属性的Servlet对象

public void setAttribute(String name, Object object); //给指定的Servlet对象赋值

public void removeAttribute(String name); //移除指定属性名

public String getServletContextName(); //获取当前ServletContext的名称
....

Servlet的上下文Context的应用

应用1、共享数据

这个就不举例的,只需要知道ServletContext中有个setAttribute 和 getAttribute 就知道怎么用了

应用2、通过web.xml中配置Context-param标签,然后通过ServletContext的getInitParameter方法进行获取

比如你在web.xml中写入该标签

<context-param>
  <param-name>url</param-name>
  <param-value>jdbc:mysql://localhost:3306</param-value>
</context-param>

<servlet-mapping>
  <servlet-name>MYHELLO</servlet-name>
  <url-pattern>/myhello</url-pattern>
</servlet-mapping>

<servlet>
  <servlet-name>MYHELLO</servlet-name>
  <servlet-class>com.zpchcbd.servlet.HelloServlet</servlet-class>
</servlet>

然后在HelloServlet继承HttpServlet类中写入:

ServletContext servletContext = this.getServletContext();
String s = servletContext.getInitParameter("mysqlUrl");
resp.getWriter().print(s);

访问对应的映射路径,如下图:

应用3、请求转发

写完如下代码,再写上对应的映射路由,在访问mydis的路由

public class DispatcherServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext = this.getServletContext();
        servletContext.getRequestDispatcher("/myhello").forward(req, resp);
    }

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

<servlet-mapping>
  <servlet-name>myDis</servlet-name>
  <url-pattern>/mydis</url-pattern>
</servlet-mapping>

<servlet>
  <servlet-name>myDis</servlet-name>
  <servlet-class>com.zpchcbd.servlet.DispatcherServlet</servlet-class>
</servlet>

如下图所示,我访问了mydis路由,但是最终访问的确实myhello路径

应用3、读取资源文件

public class PropertiesServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ServletContext servletContext = this.getServletContext();
        InputStream inputStream = servletContext.getResourceAsStream("/WEB-INF/classes/db.properties");
        Properties properties = new Properties();
        properties.load(inputStream);
        String s = properties.getProperty("username");
        resp.getWriter().print(s);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}
  <servlet>
    <servlet-name>mypro</servlet-name>
    <servlet-class>com.zpchcbd.servlet.PropertiesServlet</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>mypro</servlet-name>
    <url-pattern>/mypro</url-pattern>
  </servlet-mapping>

posted @ 2020-08-13 18:01  zpchcbd  阅读(83)  评论(0编辑  收藏  举报