Servlet 学习笔记

时间:2022-09-20 20:10:48

Servlet 运行在服务器上的 java 类;

Servlet 容器为 javaWeb 应用提供运行时环境,负责管理 servlet 和 jsp 生命周期,以及管理他们的共享数据。

现在我们知道了 Servlet 是运行在服务器上的 Java 类,那么什么是服务器?我们平常最常用的服务器都有哪些呢?

  服务器是一种被动程序:只有当Internet上运行其他计算机中的浏览器发出的请求时,服务器才会响应;

  最常用的Web服务器是ApacheMicrosoftInternet信息服务器。

对于现在大多数 Javaweb 学习者大多数使用的是 Apache 服务器,所以我们今天也就从 Tomact 服务器开始。

  Tomact 服务器的安装和配置

  首先从官网上下载 Tomact 压缩包到本地,然后解压到你想要解压到的目录,会得到一个解压后的目录如下

    --bin 存放启动和关闭 Tomact 的脚本文件

    -- conf 存放 Tomact 服务器的各种配置文件

    -- lib 存放第三方依赖 jar 包

    -- logs 存放日志文件

    -- temp 存放 Tomact 运行时产生的临时文件

    -- webapp 发布 web 应用时,通常把 web 应用的目录和文件放到这个目录下

    -- work 存放 jsp 被翻译为 Servlet 后编译的 class 文件

  启动 Tomact 服务器

    点击 bin/startup.bat 启动服务器;如果你点击之后只是闪了一下那么你可以查看日志文件查看错误信息,或者在 cmd 命令行下切换到 Tomact/bin 目录下,输入 startup 将会显示错误信息,而不是闪一下,找到错误信息之后发现它需要我们配置 JAVA_HOME(jdk 安装根目录) 或 JRE_HOME(jre 安装根目录) 中任何一个环境变量。

    配置完成后再次点击便会成功启动服务器。

    启动后在浏览器地址栏输入 localhost:8080(Apache 默认的端口号为 8080),如果出现 Apache 页面便说明启动成功(Tomcat 服务器只可以启动一个,如果你去启动第二个便会提示你端口被占用的错误信息)

    我们如果每次启动服务器在命令行中的任意目录去启动而不需要在特定的目录该多方便?那么该如何实现呢?首先我们需要知道 PATH 环境变量,安装和配置 Java 时也会用到;

    PATH是路径的意思,PATH环境变量中存放的值,就是一连串的路径。不同的路径之间,用英文的分号(;)分隔开。系统执行用户命令时,若用户未给出绝对路径,则首先在当前目录下寻找相应的可执行文件、批处理文件(另外一种可以执行的文件)等。若找不到,再依次在PATH保存的这些路径中寻找相应的可执行的程序文件。

    如上面所述,我们把 bin 目录配置到系统环境变量 path 下,这样便不会出现错误信息(xxx 不是内部命令或外部命令,也不是可运行程序或批处理文件),但是会提示另一个错误,需要我们设置另外一个环境变量(CATALINA_HOME,Tomact 解压的根目录),同上我们去设置 CATALINA 环境变量。

    设置成功后我们可以试着在任意目录下去输入 startup 来开启 Tomact。这时便可以正常启动服务器,你还可以在命令行中输入 catalina,查看 catalina 命令帮助,其中 catalina run 可以在当前窗口开启服务器,而不像 startup 那样开启另外一个窗口。开启之后可以按下 Ctrl + C 关闭服务器。

  服务器介绍完毕,开始我们的正题 ---- Servlet。

  1. 新建 web 工程,并新建一个类继承 Servlet 接口并实现其所有方法

  2. 在 web 工程队的 web.xml 中映射 servlet 类,如下:

 <?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<servlet>
<!--Servlet 注册的名字-->
<servlet-name>helloServlet</servlet-name>
<!--Servlet 的全类名-->
<servlet-class>com.javaweb.firstServlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<!--同上一致-->
<servlet-name>helloServlet</servlet-name>
<!--映射访问的具体路径,/ 表示根目录-->
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>

  3. 我们继承 Servlet 接口的类如下,我们可以在 web 项目下的 jsp 文件中写一个超链接连接到 Servlet 的 URL,运行 web 项目执行 servlet,不断刷新页面,并在最后关闭服务器,我们可以看到控制台打印的消息,由此可知 servlet 执行顺序为(构造器-init 方法-service 方法 -----service 方法 – 关闭服务器调用 destroy 方法)

    1. 构造器(只有第一次请求 Servlet 时创建 Servlet 实例调用构造器,说明 Servlet 是单实例,所以不可以写全局变量)

    2.  init(只被调用一次,在创建好实例后立即被调用,用于初始化当前 Servlet,构造器也可以初始化,但是 init 方法传入了构造器所没有的参数,所以使用 init 初始化 Servlet)

    3. service(被调用多次,每次请求都会调用 Service 方法,被用于响应请求)

    4. destroy(只被调用一次,在当前 Servlet 所在的 WEB 应用被卸载前调用,用于释放 Servlet 所占用的资源)

 package com.javaweb.firstServlet;

 import javax.servlet.*;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration; public class HelloServlet implements Servlet{ @Override
public void init(ServletConfig servletConfig) throws ServletException { System.out.println("init");
} @Override
public ServletConfig getServletConfig() {
System.out.println("getServletConfig");
return null;
} @Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("service");
} @Override
public String getServletInfo() {
System.out.println("servletInfo");
return null;
} @Override
public void destroy() {
System.out.println("destroy");
} public HelloServlet() {
System.out.println("HelloServlet");
}
}

  4. web.xml 文件 <servlet> 节点中可以指定load-on-startup 属性,指定 servlet 被创建的时机,其值越小越先被创建,若为负数则在第一次请求时被创建,若为 0 或正数则在容器被加载的时候被创建

现在我们开始详细的讲解 servlet 类及其对象

  ServletConfig 类(封装了 Servlet 的配置信息,并且可以获取 ServletContext 对象)

  方法:   getInitParameter(String name) 获取指定参数名的初始化参数

           getInitParametersNames() 获取初始化参数组成的 Enumeration 对象

  首先我们需要会配置 servlet 初始化参数,如下

 <servlet>
<!--Servlet 注册的名字-->
<servlet-name>helloServlet</servlet-name>
<!--Servlet 的全类名-->
<servlet-class>com.javaweb.firstServlet.HelloServlet</servlet-class>
<!--配置初始化参数,必须在 load-on-startup 节点前面-->
<init-param>
<param-name>user</param-name>
<param-value>root</param-value>
</init-param>
<init-param>
<param-name>password</param-name>
<param-value>zy961029</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

  ServletContext 对象(可以认为是当前 WEB 应用的大管家 )

  定义了一组和 Servlet 容器通信的方法,每个应用程序都有一个 ServletContext(上下文),ServletContext 对象被称为application 对象,ServletContext 被包含在 ServletConfig 对象中,其拥有的方法和 servletConfig 一样,但获取的是当前 WEB 应用的初始化参数,当前 WEB 应用的初始化参数配置如下:

 ServletContext 对象的方法众多可以参考其官方 API。

 <?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<context-param>
<param-name>url</param-name>
<param-value>jdbc:mysql:///sh_db</param-value>
</context-param>
<context-param>
<param-name>driverClass</param-name>
<param-value>com.mysql.jdbc.Driver</param-value>
</context-param>
<web-app>

    当前 WEB 应用的初始化参数和 Servlet 初始化参数的区别:

      Servlet 初始化参数在当前 Servlet 中也就是 局部的,WEB 应用参数在 servlet 外边,相当于全局的,所有的 Servlet 可以获取

    下面的是 ServletConfig 对象和 ServletContext 对象的方法实现

 package com.javaweb.firstServlet;

 import javax.servlet.*;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration; /**
* Created by shkstart on 2017/11/06.
*/
public class HelloServlet implements Servlet{ @Override
public void init(ServletConfig servletConfig) throws ServletException {
// 获取当前 Servlet 的初始化参数
Enumeration<String> names = servletConfig.getInitParameterNames(); while (names.hasMoreElements()) {
String name = names.nextElement();
String value = servletConfig.getInitParameter(name);
System.out.println("name:" + name + "; value: " + value);
} // 获取当前 WEB 应用的初始化参数
ServletContext servletContext = servletConfig.getServletContext();
Enumeration<String> contextNames = servletContext.getInitParameterNames();
while (contextNames.hasMoreElements()) {
String contextName = contextNames.nextElement();
String contextValue = servletContext.getInitParameter(contextName);
System.out.println(contextName + "-->" + contextValue);
}
// 获取当前 WEB 应用的名称
String contextPath = servletContext.getContextPath();
System.out.println(contextPath + "+------+"); // 获取某一个文件对应的输入流
InputStream inputStream2 = servletContext.getResourceAsStream("/First.jsp");
System.out.println(inputStream2 + "-----+-----"); // 获取部署在服务器上的绝对路径
String realPath = servletContext.getRealPath("First.jsp");
System.out.println(realPath);
} @Override
public ServletConfig getServletConfig() {
System.out.println("getServletConfig");
return null;
} @Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("service");
} @Override
public String getServletInfo() {
System.out.println("servletInfo");
return null;
} @Override
public void destroy() {
System.out.println("destroy");
} public HelloServlet() {
System.out.println("HelloServlet");
}
}

  ServletRequest 和 ServletResponse 对象

  ServletRequest 封装了请求信息,可从中获取到任何的请求信息;ServletResponse 封装了响应信息,如果想给用户什么响应,具体可以使用该接口的方法实现 ,其常用方法有

           String getParameter(String name); 获取请求的参数值,根据所传入的参数,例如输入框;

      String[] getParameterValues() 返回参数的字符串类型的数组,例如多选框;

      getWriter() 方法返回一个 PrintWirter 对象,打印到浏览器页面其他方法可以参考官方 PAI,在这里就不再啰嗦。

    上面的方法具体如下:

 <%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<form action="loginServlet">
UserName: <input type="text" name="userName"><br>
PassWord: <input type="password" name="passWord"><br>
Interest: <input type="checkbox" name="interest" value="TV">TV
<input type="checkbox" name="interest" value="MP3">MP3
<input type="checkbox" name="interest" value="SPORT">SPORT
<button type="submit">Submit</button>
</form>
</body>
</html>

  

 package com.javaweb.firstServlet;

 import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.PrintWriter; /**
* Created by shkstart on 2017/11/06.
*/
public class LoginServlet implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException { } @Override
public ServletConfig getServletConfig() {
return null;
} @Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
String userName = servletRequest.getParameter("userName");
String passWord = servletRequest.getParameter("passWord");
// 获取上面 jsp 文件中的输入框的值
System.out.println("userName: " + userName + "; passWord: " + passWord);
// 获取上面 jsp 文件中多选框的值
String[] interests = servletRequest.getParameterValues("interest");
for (String inter : interests) {
System.out.println("INTEREST: " + inter);
} // 获取请求的 URI,获取与 HTTP 请求有关的需要使用 ServletRequest 子接口 HttpServletRequst
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
String uri = httpServletRequest.getRequestURI();
System.out.println(uri); String method = httpServletRequest.getMethod();
System.out.println(method); // 获取 Servlete 的映射路径
String servletPath = httpServletRequest.getServletPath();
System.out.println(servletPath); // 设置响应内容类型,为 word
// servletResponse.setContentType("application/msword"); PrintWriter printWriter = servletResponse.getWriter();
printWriter.print("HelloWorld");
} @Override
public String getServletInfo() {
return null;
} @Override
public void destroy() { }
}

  如果每次都要像上面这样继承 Servlet 接口,且其大多数方法并不会经常用到,如果你感到这样很烦琐就对了,因为  Servlet 接口有一个子接口 GenericServlet,GenericServlet 实现了 Servlet 和 ServletConfig 接口的所有方法的一个抽象类,其中的 serevice 方法为抽象方法,因为每次请求都要去实现 service 方法;在其中 声明了一个 servletConfig 成员变量,在 init(ServletConfig) 方法中对其进行初始化;利用 ServletConfig 成员变量的方法实现了 ServletConfig 接口的方法,还定义了一个 init() 方法,在 init(ServletConfig) 方法对其进行调用,子类可以直接覆盖 init() 在其中实现对 Servlet 的初始化,这样我们继承 GenericServlet 就可以极大简化我们的代码。

  我们如果在 service 方法中想要获取有关 URL 的相关信息,我们还必须使用 HttpServletRequest 和 HttpServletResponse,如果我们继承 GenericServlet ,那么每次还需要去强制转换,特别麻烦,和上面所述一样我们有封装好的类去专门用作开发----HttpServlet,HttpServlet 继承自 GenericServlet,针对 HTTP 协议所定制;特点是在 service 方法中直接把 ServletRequest 和 ServletResponse 转为 HttpServletRequest 和 HttpServletResponse,并调用 service(HttpServletRequest resquest, HttpServletResponse response);

  我们在平常开发中的 Servlet 便是继承自 HttpServlet,如果对上面所述的 GenericServlet 和 HttpServlet 想理解的更清楚可以去阅读源代码,看看他们的具体实现,下一篇文章将会对上面所述的四个对象的方法加以更加详细的讲解。

  以上就是本周对 Servlet 学习的知识总结,有点乱,如果有什么疑问或者错误可以提出来我会尽快回复。

Servlet 学习笔记的更多相关文章

  1. &num; jsp及servlet学习笔记

    目录 jsp及servlet学习笔记 JSP(Java Server Page Java服务端网页) 指令和动作: servlet(小服务程序) jsp及servlet学习笔记 JSP(Java Se ...

  2. Servlet学习笔记(四)

    目录 Servlet学习笔记(四) 一.会话技术Cookie.session 1. 什么是会话技术? 2. 会话技术有什么用? 3. Cookie 3.1 什么是Cookie? 3.2 使用Cooki ...

  3. Servlet学习笔记(三)

    目录 Servlet学习笔记(三) 一.HTTP协议 1.请求:客户端发送欸服务器端的数据 2.响应:服务器端发送给客户端的数据 3.响应状态码 二.Response对象 1.Response设置响应 ...

  4. Servlet学习笔记(二)

    目录 Servlet学习笔记(二) Request对象 1.request和response对象: 2.request对象继承体系结构: 3.什么是HttpServletRequest ? 4.Htt ...

  5. jsp&amp&semi;servlet学习笔记

    1.路径引用问题 一个css.jsp.html.或者javascript文件从从一个工程复制到另一工程,如果引用的时候使用的时相对路径,看似没有错误,但是却一直引用不进来,这时候要使用绝对路径,这样才 ...

  6. Servlet学习笔记&lpar;1&rpar;--第一个servlet&amp&semi;&amp&semi;三种状态对象&lpar;cookie&comma;session&comma;application&rpar;&amp&semi;&amp&semi;Servlet的生命周期

    servlet的404错误困扰了两天,各种方法都试过了,翻书逛论坛终于把问题解决了,写此博客来纪念自己的第一个servlet经历. 下面我会将自己的编写第一个servlet的详细过程提供给初学者,大神 ...

  7. Servlet学习笔记(七)—— 自己定义过滤器的编写改进:自己定义实现FilterChain

    笔记六中实现了三种过滤器:字符编码过滤.登录权限过滤.敏感词过滤,可是有个缺陷就是,限定了过滤顺序,而不能实现先进行request过滤.最后response过滤,而且中间几项过滤的顺序不能动态改变.所 ...

  8. Servlet学习笔记(八)—— 文件下载

    一.文件下载概述 比如图片或者HTML这类静态资源,仅仅要在浏览器中打开正确的网址就行下载.仅仅要资源放在应用程序文件夹或者其下的子文件夹中,但不在WEB-INF下.Servlet/JSP容器就会将资 ...

  9. JSP&amp&semi;Servlet学习笔记----第1&sol;2章

    HTML(HyperText Markup Language):超文本标记语言 HTTP(HyperText Transfer Protocol):超文本传输协议 URL(Uniform Resour ...

随机推荐

  1. iOS证书详解--再转

    一.成员介绍1.    Certification(证书)证书是对电脑开发资格的认证,每个开发者帐号有一套,分为两种:1)    Developer Certification(开发证书)安装在电脑上 ...

  2. HTML&amp&semi;CSS基础学习笔记1&period;5-添加常用标签

    代码如下: <!DOCTYPE html><html lang="en"><head>    <meta charset="UT ...

  3. UVA 12103 - Leonardo&amp&semi;&num;39&semi;s Notebook&lpar;数论置换群&rpar;

    UVA 12103 - Leonardo's Notebook 题目链接 题意:给定一个字母置换B.求是否存在A使得A^2=B 思路:随意一个长为 L 的置换的k次幂,会把自己分裂成gcd(L,k) ...

  4. Hibernate 系列教程6-双向多对多

    双向多对多inverse配置 如果关系两边都使用默认inverse=false配置,表示关系两边都可以管理中间表的数据 关系其中一边设置inverse=true配置,表示自己放弃管理中间表关系,由对方 ...

  5. 【转载】解决refreshing gradle project 和Building gradle project info 一直卡住&bsol;速度慢

    转载: http://blog.csdn.net/xx326664162/article/details/52002616 文章出自:薛瑄的博客 分析原因: 更改Gradle的版本后,或者更新AS后, ...

  6. Android OpenGL ES 开发(十)&colon; 通过GLES20与着色器交互

    1. 获取着色器程序内成员变量的id(句柄.指针) GLES20.glGetAttribLocation方法:获取着色器程序中,指定为attribute类型变量的id. GLES20.glGetUni ...

  7. Axure RP8 注册码

    升级了 8.1.0.3381版本后,需要使用下面这组注册码 License:zdfansKey:fZw2VoYzXakllUuLVdTH13QYWnjD6NZrxgubQkaRyxD5+HNMqdr+ ...

  8. Spring学习之旅(三)Spring工作原理初探

    详细的废话相信很多书籍视频资料都已经很多了,这里说几个小编个人认为对于理解Spring框架很重要的点.欢迎批评指正. 1)Spring的控制反转 先说说“依赖”,在面向对象程序设计中,类A中用到了类B ...

  9. 使用Golang&plus;Mongodb打造你的第一个站点

    很多人推荐MEAN来开发站点.MEAN就是M:mongodb,E:expressjs.A:angular最后的N:nodejs. 但是如果你亲身的体会到了js的嵌套回调的话你就会想换换别的办法了.虽然 ...

  10. Link1123&colon;转换到COFF期间失败:文件无效或损坏

        当在编译VS项目时,出现如下错误:         这个错误,表明在连接阶段出错.COFF为Common Object File Format,通用对象文件格式,它的出现为混合语言编程带来方便 ...