JavaWeb开发 Servlet技术详解(二)

简介: JavaWeb开发 Servlet技术详解(二)

四、Servlet

4.1 Servlet简介

Servlet是Server Applet的简称,称为服务端小程序,是JavaEE平台下的技术标准,基于Java语言编写的服务端程序。 Web 容器或应用服务器实现了Servlet标准所以Servlet需要运行在Web容器或应用服务器中。Servlet主要功能在于能够在服务器中执行并生成数据。

4.1.1 Servlet技术特点

4.1.2 Servlet在应用程序中的位置

4.2 编写第一个Servlet

package it.com.servlet;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class HelloWorld extends HttpServlet{
    public void doGet(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
        PrintWriter pw = response.getWriter();
        pw.println("<!DOCTYPE html>");
        pw.println("<html lang=en>");
        pw.println("<head>");
        pw.println("<meta charset=UTF-8>");
        pw.println("<title>Document</title>");
        pw.println("</head>");
        pw.println("<body>");
    pw.println("<font color=blue>HelloWorld</font>");
        pw.println("</body>");
        pw.println("</html>");
        pw.flush();
        pw.close();
    }
}

4.3编译servlet

Java中需要将源文件(.java)通过Javac编译为.class的字节文件才能运行。

D:\>javac oneServlet.java

出错的原因是servlet是JavaEE实现的规范不是JavaSE实现的,在servlet包中的类全部在Tomcat中有实现。因此servlet程序要放在Tomcat中运行。因此需要指定这些对象的位置(也就是tomcat中servlet包的位置)

D:\>javac -classpath "D:\Java\apache-tomcat-9.0.75\lib\servlet-api.jar" HelloWorld.java

执行后D盘产生字节文件Hello World.class

4.4 创建web.xml

什么是web.xml

Web项目的部署描述文件,是JavaWeb工程的配置文件,通过web.xml文件可以配置servlet、filter等技术。Tomcat启动时会先解析该配置文件获取项目的配置信息。

web.xml文件中的头信息

<?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_4_0.xsd"
     version="4.0">
</web-app>

在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_4_0.xsd"
     version="4.0">
         <!-- 给定servlet的全名,tomcat会根据全名实例化servlet,从而使用servlet对象的方法 -->
         <servlet>
            <servlet-name>HelloWorld</servlet-name>
            <servlet-class>it.com.servlet.HelloWorld</servlet-class>
         </servlet>
         <!-- servlet资源映射,访问/helloworld.do即可访问到servlet资源 -->
         <servlet-mapping>
            <servlet-name>HelloWorld</servlet-name>
            <url-pattern>/helloworld.do</url-pattern>
         </servlet-mapping>
</web-app>

注意路径必须加 /

4.5 部署运行Servlet

Web工程目录结构

访问Servlet

http://localhost:8888/servletdemo/helloworld.do

注意:没有在host下配置context时资源名默认为项目名。

4.6 Tomcat处理请求过程

  1. 用户访问localhost:8888/test/helloword.do,请求被发送到Tomcat,被监听8888端口并处理 HTTP/1.1 协议的Connector获得。
  2. Connector把该请求交给它所在的Service的Engine来处理,并等待Engine的回应。
  3. Engine获得请求localhost/test/helloword.do,匹配所有的虚拟主机Host。
  4. Engine匹配到名为localhost的Host虚拟主机来处理/test/helloword.do请求(即使匹配不到会请求交给默认Host处理)。
  5. 匹配到的Context获得请求/helloword.do。
  6. 构造HttpServletRequest对象和HttpServletResponse对象,作为参数调用HelloWorld的doGet()或doPost().执行业务逻辑、数据存储等程序。
  7. Context把执行完之后的结果通过HttpServletResponse对象返回给Host。
  8. Host把HttpServletResponse返回给Engine。
  9. Engine把HttpServletResponse对象返回Connector。
  10. Connector把HttpServletResponse对象返回给客户Browser。

4.7 Servlet继承结构

Servlet接口

  1. init(),创建Servlet对象后立即调用该方法完成一些初始化工作。
  2. service(),处理客户端请求,执行业务操作,利用响应对象响应客户端请求。
  3. destroy(),在销毁Servlet对象之前调用该方法,释放资源。
  4. getServletConfig(),ServletConfig是容器向servlet传递参数的载体。(可以获取配置文件web.xml的信息)
  5. getServletInfo(),获取servlet相关信息。

ServletConfig接口

  1. String getServletName(),返回 Servlet 的名字,即 web.xml 中 元素的值。
  2. ServletContext getServletContext(),返回一个代表当前 Web 应用的 ServletContext 对象。
  3. String getInitParameter(String name),根据初始化参数名返回对应的初始化参数值。
  4. Enumeration getInitParameterNames(),返回一个 Enumeration 对象,其中包含了所有的初始化参数名。

GenericServle抽象类

GenericServlet是实现了Servlet接口的抽象类。在GenericServlet中进一步的定义了Servlet接口的具体实现,其设计的目的是为了和应用层协议解耦,在GenericServlet中包含一个Service抽象方法。

HttpServlet类

继承自 GenericServlet,针对于处理 HTTP 协议的请求所定制。在 HttpServlet的service() 方法中已经把 ServletReuqest 和 ServletResponse 转为 HttpServletRequest 和 HttpServletResponse。 直接使用 HttpServletRequest 和 HttpServletResponse, 不再需要强转。实际开发中, 直接继承 HttpServlet, 并根据请求方式复写 doXxx() 方法即可。

Tomcat实现了servlet技术规范,所以在tomcat的lib中的servlet-api.jar中可以查看这些接口和实现类。使用反编译小工具jd

4.8 Servlet的生命周期

Servlet的生命周期是由容器(tomcat,即servlet是由tomcat实例化的)管理的,分别经历三各阶段:

init():初始化

service():服务

destroy():销毁

(注意面试)当客户端浏览器第一次请求Servlet时,容器会实例化这个Servlet,然后调用一次init方法,并在新的线程中执行service方法处理请求。service方法执行完毕后容器不会销毁这个Servlet而是做缓存处理,当客户端浏览器再次请求这个Servlet时,容器会从缓存中直接找到这个Servlet对象,并再一次在新的线程中执行Service方法(单例模式)。当容器在销毁Servlet之前对调用一次destroy方法。

4.9 Servlet处理请求的原理

当浏览器基于get方式请求我们创建Servlet时,我们自定义的Servlet中的doGet方法会被执行。doGet方法能够被执行并处理get请求的原因是,容器在启动时会解析web工程中WEB-INF目录中的web.xml文件,在该文件中我们配置了Servlet与URI的绑定,容器通过对请求的解析可以获取请求资源的URI,然后找到与该URI绑定的Servlet并做实例化处理(注意:只实例化一次,如果在缓存中能够找到这个Servlet就不会再做次实例化处理)。在实例化时会使用Servlet接口类型作为引用类型的定义,并调用一次init方法,由于GenericServlet中重写了该方法所以最终执行的是GenericServlet中init方法(GenericServlet中的Init方法是一个空的方法体),然后在新的线程中调用service方法。由于在HttpServlet中重写了Service方法所以最终执行的是HttpServlet中的service方法。在service方法中通过request.getMethod()获取到请求方式进行判断如果是Get方式请求就执行doGet方法,如果是POST请求就执行doPost方法。如果是基于GET方式提交的,并且在我们的Servlet中又重写了HttpServlet中的doGet方法,那么最终会根据Java的多态特性转而执行我们自定义的Servlet中的doGet方法。

4.10 Servlet的作用

  • 获取用户提交的数据
  • 获取浏览器附加的信息
  • 处理数据(访问数据库或调用接口)
  • 给浏览器产生一个响应
  • 在响应中添加附加信息

4.12 在Idea中创建web工程

三个步骤:

  1. 创建Web工程
  2. 添加servlet-api.jar
  3. 配置Tomcat

新建一个Java项目

项目名称右键选择第二个命令

勾选Web Application

为项目添加依赖

配置tomcat

4.13 在web工程中编写Servlet

新建MyServlet类,继承HttpServlet,重写doGet();方法。配置web.xml文件。启动tomcat在浏览器访问即可。

public class MyServlet extends HttpServlet {
    //处理get请求
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        PrintWriter pw = resp.getWriter();
        pw.println("<!DOCTYPE html>");
        pw.println("<html lang=en>");
        pw.println("<head>");
        pw.println("<meta charset=UTF-8>");
        pw.println("<title>Document</title>");
        pw.println("</head>");
        pw.println("<body>");
        pw.println("<font color=blue>Hello Servlet</font>");
        pw.println("</body>");
        pw.println("</html>");
        pw.flush();
        pw.close();
    }
}
<?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_4_0.xsd"
         version="4.0">
    <!--配置servlet位置信息-->
    <servlet>
        <servlet-name>MyServlet</servlet-name>
        <servlet-class>cn.it.servlet.MyServlet</servlet-class>
    </servlet>
    <!--URL映射-->
    <servlet-mapping>
        <servlet-name>MyServlet</servlet-name>
        <url-pattern>/MyServlet.do</url-pattern>
    </servlet-mapping>
</web-app>

4.14 Idea中的web项目部署详解

在Idea中默认的并不会把web项目真正的部署到Tomcat的webapps目录中,而是通过为每个web项目创建一个独立的Tomcat副本并在Tomcat副本中通过的Tomcat的Context组件完成项目的目录指定,在Context组件的docBase属性中会指定Idea对web项目编译后的目录out/artifacts/.....。

默认部署方式

Idea会在C:\Users\Administrator\AppData\Local\JetBrains\IntelliJIdea2020.2\tomcat中为每个Web项目创建一个独立的Tomcat副本。

Idea通过执行Tomcat的catalina.bat启动脚本启动Tomcat,通过启动参数来指定启动Tomcat副本运行指定目录中的web项目。

Idaa在启动Tomcat之前会先在操作系统中设置一些临时环境变量,这些变量会被Tomcat的启动脚本所读取。

4.15 将web项目部署到Tomcat的webapps中

点击项目结构选项

指定输出artifacts的目录为Tomcat的webapps中的demo目录。

启动Tomcat,查看demo目录中的内容。

4.16 获取请求信息

4.16.1 HttpServletRequest对象

HttpServletRequest对象代表客户端浏览器的请求,当客户端浏览器通过HTTP协议访问服务器时,HTTP请求中的所有信息都会被Tomcat所解析并封装在这个对象中,通过这个对象提供的方法,可以获得客户端请求的所有信息。

获取请求信息

req.getRequestURL()

返回客户端浏览器发出请求时的完整URL。

req.getRequestURI()

返回请求行中指定资源部分。

req.getRemoteAddr()

返回发出请求的客户机的IP地址。

req.getLocalAddr()

返回WEB服务器的IP地址。

req.getLocalPort()

返回WEB服务器处理Http协议的连接器所监听的端口。

package cn.it.servlet;
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.io.PrintWriter;
//获取请求信息
public class GetRequestInfoServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取浏览器发出请求的完整的url
        StringBuffer requestURL = req.getRequestURL();
        String s = requestURL.toString();
        //获取请求行中指定的资源部分
        String requestURI = req.getRequestURI();
        //获取发送请求的客户机的IP地址
        String remoteAddr = req.getRemoteAddr();
        //获取服务端的IP地址
        String localAddr = req.getLocalAddr();
        //获取服务端监听的端口
        int localPort = req.getLocalPort();
        PrintWriter writer = resp.getWriter();
        writer.println("浏览器发出请求的完整的url:"+s);
        writer.println("求行中指定的资源部分:"+requestURI);
        writer.println("发送请求的客户机的IP地址:"+remoteAddr);
        writer.println("服务端的IP地址:"+localAddr);
        writer.println("服务端监听的端口:"+localPort);
    }
}
<servlet>
        <servlet-name>getRequestInfoServlet</servlet-name>
        <servlet-class>cn.it.servlet.GetRequestInfoServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>getRequestInfoServlet</servlet-name>
        <url-pattern>/getRequestInfo.do</url-pattern>
    </servlet-mapping>

4.16.2 获取请求数据(表单)

根据key获取指定value

req.getParameter("key");

根据key获取对应的value,返回一个字符串。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!-- action="getRequestData.do" 不能加 “/”-->
<form action="getRequestData.do" method="post">
     <input type="text" name="username"/>
     <input type="text" name="password"/>
     <input type="submit" value="确定"/>
</form>
</body>
</html>

注意:html要在web下创建要不然不能直接访问到。action="getRequestData.do" 不能加 “/”

package cn.it.servlet;
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.io.PrintWriter;
//获取表单数据
public class GetRequestData extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        PrintWriter writer = resp.getWriter();
        writer.println("username=" + username);
        writer.println("password=" + password);
        writer.flush();
        writer.close();
    }
}
<servlet>
        <servlet-name>getRequestData</servlet-name>
        <servlet-class>cn.it.servlet.GetRequestData</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>getRequestData</servlet-name>
        <url-pattern>/getRequestData.do</url-pattern>
    </servlet-mapping>

4.16.3 获取复选框(checkbox组件)中的值

String[] userlikes  =  req.getParameterValues("checkboxkey");

获取复选框(checkbox组件)中的值,返回一个字符串数组。

String[] userLikes = req.getParameterValues("userLike");
        List<String> userLikesList = Arrays.asList(userLikes); //将数组转换为集合

4.16.4 获取所有提交数据的key

req.getParameterNames()

获取请求中所有数据的key,该方法返回一个枚举类型。

Enumeration<String> parameterNames = req.getParameterNames();
//获取参数的key
        Enumeration<String> parameterNames = req.getParameterNames();
        List<String> parameterNamesList = new ArrayList<String>();
        while (parameterNames.hasMoreElements()) {
            parameterNamesList.add(parameterNames.nextElement());
        }

4.17 设置请求编码

请求的数据包基于字节在网络上传输,Tomcat接收到请求的数据包后会将数据包中的字节转换为字符。在Tomcat中使用的是ISO-8859-1的单字节编码完成字节与字符的转换,所以数据中含有中文就会出现乱码,可以通过req.setCharacterEncoding("utf-8")方法来对提交的数据根据指定的编码方式重新做编码处理。

req.setCharacterEncoding("UTF-8");

4.18 资源访问路径

绝对路径

绝对路径访问资源表示直接以”/”作为项目的Context Path。该方式适用于以”/”作为项目的Context Path。

<form action="/getInfo.do" method="post">

相对路径

相对路径访问资源表示会相对于项目的Context Path作为相对路径。该方式适用于为项目指定的具体的Context Path。

<form action="getInfo.do" method="post">

4.19 获取请求头信息

获取请求头信息

根据请求头中的key获取对应的value。

String headerValue = req.getHeader("headerKey");

获取请求头中所有的key,该方法返回枚举类型。

Enumeration<String> headerNames = req.getHeaderNames();

4.19.1 获取请求头案例

需求:编写一个Servlet,如果浏览器的语言是zh-CN,显示“你好,聪明的中国人!”,如果浏览器的语言设置为en-US,那么则显示“Hello,American”。

package cn.it.servlet;
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.io.PrintWriter;
public class Practise extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String header = req.getHeader("Accept-Language");
        resp.setContentType("text/html;charset=UTF-8");
        PrintWriter writer = resp.getWriter();
        if (header.startsWith("zh-CN")) {
            writer.println("你好");
        }else if (header.startsWith("en-US")) {
            writer.println("hello");
        }else {
            writer.println("####");
        }
        writer.flush();
        writer.close();
    }
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }
}


相关文章
|
4月前
|
缓存 Java 应用服务中间件
javaweb实训第三天上午——Servlet(1)
Servlet基础 课程介绍 Servlet基础; (掌握) 基本结构 生命周期 执行流程 接收参数 响应数据
53 0
|
8天前
|
设计模式 存储 前端开发
Java从入门到精通:2.2.1学习Java Web开发,了解Servlet和JSP技术,掌握MVC设计模式
Java从入门到精通:2.2.1学习Java Web开发,了解Servlet和JSP技术,掌握MVC设计模式
|
29天前
|
前端开发 Java API
深入理解Servlet技术:Java Web开发的核心
【4月更文挑战第3天】Servlet是Java Web开发的核心技术,定义了响应客户端请求的接口。它遵循请求-响应模型,处理动态Web内容,生命周期由Web容器管理。Servlet API包含接口和类,如HttpServletRequest和HttpServletResponse,支持请求处理和会话管理。尽管现代开发常使用Spring MVC等框架,但理解Servlet对于理解框架底层机制至关重要。掌握Servlet基础知识对构建健壮的Web应用仍然必要。
|
2月前
|
Java 数据处理 数据库
Java Web开发中的Servlet
Java Web开发中的Servlet
|
3月前
|
Java 应用服务中间件 API
深入解析Java Servlet技术在Web开发中的应用
深入解析Java Servlet技术在Web开发中的应用
215 1
|
3月前
|
存储 Java 应用服务中间件
JavaWeb----Servlet技术
JavaWeb----Servlet技术
327 0
|
4月前
|
存储 前端开发 Java
JavaWeb:servlet+jsp+mybatis商品管理增删改查
商品管理通常包括增加(添加)、删除、修改和查询商品信息
57 1
JavaWeb:servlet+jsp+mybatis商品管理增删改查
|
4月前
|
安全 Java
javaweb实训第四天下午——员工管理系统-JSP&Servlet&JDBC综合练习-CRUD
1.课程介绍 Servlet细节; (掌握) 员工信息相关的CRUD; (掌握) 部门信息相关的CRUD; (掌握) 2.Servlet细节 2.1.多种匹配方式
41 0
|
4月前
|
编解码 应用服务中间件 数据库
|
4月前
|
Java 数据库连接 数据库
通过JSP、JavaBean、JDBC、Servlet技术,实现用户登录功能
通过JSP、JavaBean、JDBC、Servlet技术,实现用户登录功能