网络应用程序设计(IDEA版)—— 实验一:Servlet技术及应用

目录

如何使用idea创建一个servlet项目可以参考:

实验预习报告

一、实验目的

二、实验要求

三、实验原理

四、实验预习内容

实验报告

一、实验目的

二、实验要求

三、实验原理

四、实验内容与步骤


如何使用idea创建一个servlet项目可以参考:

如何使用idea创建一个servlet项目(详细版)

实验预习报告

一、实验目的

1. 掌握如何获得请求参数;

2. 掌握如何检索请求头;

3. 了解如何通过请求对象获得客户信息;

4. 重点掌握使用请求对象存储数据和请求转发;

5. 掌握如何通过ServletConfig获取Servlet的初始化参数;

6. 掌握ServletContext的概念,如何获得ServletContext对象;

7. 掌握如何通过ServletContex对象的RequestDispatcher进行请求转发;

8. 了解Servlet的多线程问题及解决方法。

二、实验要求

1. 实验前进行预习,完成实验预习报告;

2.按照每一项实验内容进行上机实践与编程,将程序源代码(或程序截图)和程序运行结果截图附在实验报告中实验内容对应的部分。

3. 每次实验预习报告和实验报告打印装订成一份,左侧装订。

4. 每一次实验创建一个Web项目,每一项实验内容的源代码保存在该项目下,按目录组织保存好并压缩,按照老师指定的要求进行提交。代码保存方式如下:exp01表示实验一的Web项目的名称,其下保存各项实验内容的源文件及相关资源,将整个exp01文件夹进行压缩后命名为班级-姓名-实验1,如计算机181-张三-实验1。

三、实验原理

对客户的请求,容器根据请求调用Servlet的相应doXxx()方法,该方法带有两个参数,一个是HttpServletRequest,一个是HttpServletResponse,它们分别表示请求对象和响应对象,它们是容器自动创建的两个对象。可以使用这两个接口定义的若干方法完成有关操作。

Web应用程序有严格定义的目录结构,它需要一个称为部署描述文件的文件web.xml来配置。对应用程序的每个Servlet,可以在web.xml中定义若干个初始化参数,然后通过ServletConfig对象获取这些参数。

ServletContext对象表示该应用程序的环境,通过该对象可以获得应用程序范围的初始化参数、容器版本信息、资源的URL、在其中存放共享数据以及登录日志等。

四、实验预习内容

1. Web页面中都可以使用哪些方式来发送HTTP请求?

答:(1)用户在浏览器的地址栏中输入URL并按回车键;
        (2)用户点击了HTML页面中的超链接;
        (3)用户在HTML页面中添写一个表单并提交.

2.GET与POST两种请求方式有什么区别?分别适用于什么情况?

答:(1)GET方法用来检索资源.它的含义是”获得由该URI标识的资源”.GET方法请求的资源通常是静态资源.使用GET也可以请求动态资源,但一般要提供少量的请求参数.
        (2)POST方法用来向服务器发送需要处理的数据,它的含义是”将数据发送到由该URI标识的动态资源”.

3. HTTP响应内容的类型都有哪些?如何设置HTTP响应内容的类型?

答:(1)类型有:

1)public PrintWriter getWriter():返回一个PrintWriter对象用于向客户发送文本数据.

2)public ServletOutStream getOutputStream() throws IOException:返回一个输出流对象,它用来向客户发送二进制数据.

3)public void setContentType(String type):设置发送到客户端响应的MIME内容类型.

(2)设置方法:

设置响应数据内容类型应该使用相应对象的setContentType(),如果没有调用该方法,内容类型将使用默认值text/html,即HTML文档.

可以调用响应对象response的setCharacterEncoding()设置响应的字符编码.如果没有指定响应的字符编码,PrintWriter将使用ISO-8859-1编码.

如果不使用默认的响应的内容类型和字符编码,应该先调用响应的setContentType(),然后再调用getWriter()或getOutputStream()获得输出流对象.

4. 什么是ServletContext对象,它的生存周期如何?

答:Web容器在启动时会加载每个Web应用程序,并为每个Web应用程序创建一个唯一的ServletContext实例对象,该对象称为Servlet上下文对象。
ServletContext是一个作用域对象,使用它可以存储数据,它的作用域是整个应用程序。

5. ServletContext与ServletRequest的getRequestDispatcher()方法有什么区别?

答:区别是:对ServletContext的getRequestDispatcher()只能传递以”/”开头的路径,而对ServletRequest的getRequestDispatcher(),可以传递一个相对路径。

实验报告

一、实验目的

1. 掌握如何获得请求参数;

2. 掌握如何检索请求头;

3. 了解如何通过请求对象获得客户信息;

4. 重点掌握使用请求对象存储数据和请求转发;

5. 掌握如何通过ServletConfig获取Servlet的初始化参数;

6. 掌握ServletContext的概念,如何获得ServletContext对象;

7. 掌握如何通过ServletContex对象的RequestDispatcher进行请求转发;

8. 了解Servlet的多线程问题及解决方法。

二、实验要求

1. 实验前进行预习,完成实验预习报告;

2.按照每一项实验内容进行上机实践与编程,将程序源代码和程序运行结果图附在实验报告中实验内容对应的部分。

3. 每次实验预习报告和实验报告打印装订成一份,左侧装订。

4. 每一次实验创建一个Web项目,每一项实验内容的源代码保存在该项目下,按目录组织保存好并压缩,按照老师指定的要求进行提交。代码保存方式如下:exp01表示实验一的Web项目的名称,其下保存各项实验内容的源文件及相关资源,将整个exp01文件夹进行压缩后命名为班级-姓名-实验1,如计算机181-张三-实验1。

三、实验原理

对客户的请求,容器根据请求调用Servlet的相应doXxx()方法,该方法带有两个参数,一个是HttpServletRequest,一个是HttpServletResponse,它们分别表示请求对象和响应对象,它们是容器自动创建的两个对象。可以使用这两个接口定义的若干方法完成有关操作。

Web应用程序有严格定义的目录结构,它需要一个称为部署描述文件的文件web.xml来配置。对应用程序的每个Servlet,可以在web.xml中定义若干个初始化参数,然后通过ServletConfig对象获取这些参数。

ServletContext对象表示该应用程序的环境,通过该对象可以获得应用程序范围的初始化参数、容器版本信息、资源的URL、在其中存放共享数据以及登录日志等。

四、实验内容与步骤

项目总目录如下(在这里项目名应该为exp01,可以自己在创项目时改一下):

网络应用程序设计(IDEA版)—— 实验一:Servlet技术及应用_第1张图片

如果是新手,最好按照文章刚开始的链接创建servlet项目,不然可能会有些不一样。

先配置一下pom.xml文件:




  4.0.0

  org.example
  school_servlet
  1.0-SNAPSHOT
  war

  school_servlet Maven Webapp
  
  http://www.example.com

  
    UTF-8
    1.7
    1.7
  

  
    
      javax.servlet
      javax.servlet-api
      
      3.1.0
      
      provided
    
    
    
      com.fasterxml.jackson.core
      jackson-databind
      2.14.1
    
    
    
      org.projectlombok
      lombok
      1.18.24
      provided
    
    
      mysql
      mysql-connector-java
      8.0.31
    
    
      junit
      junit
      4.11
      test
    
  

  
    school_servlet
    
      
        
          maven-clean-plugin
          3.1.0
        
        
        
          maven-resources-plugin
          3.0.2
        
        
          maven-compiler-plugin
          3.8.0
        
        
          maven-surefire-plugin
          2.22.1
        
        
          maven-war-plugin
          3.2.2
        
        
          maven-install-plugin
          2.5.2
        
        
          maven-deploy-plugin
          2.8.2
        
      
    
  

1. 简单的综合应用,掌握Servlet将请求转发给另一个Servlet的方法。

【步骤1】创建一个名为input.html的HTML页面,其中包括一个表单,表单中包含两个文本域,分别供用户输入学号和姓名,该页面也包含提交和重置按钮。

网络应用程序设计(IDEA版)—— 实验一:Servlet技术及应用_第2张图片




    
    输入学生信息


学号
姓名

【步骤2】 定义一个名为com.demo.Student类,其中包括学号sno和姓名name两个private的成员变量,定义访问和修改sno和name的方法。

网络应用程序设计(IDEA版)—— 实验一:Servlet技术及应用_第3张图片

package com.demo;

public class Student {
    private String sno;
    private String name;
    public Student(String sno, String name) {
        // TODO Auto-generated constructor stub
        this.sno=sno;
        this.name=name;
    }
    public String getSno() {
        return sno;
    }
    public void setSno(String sno) {
        this.sno = sno;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

【步骤3】编写名为FirstServlet的Servlet,要求当用户在input.html中输入信息后点击“提交”按钮,请求FirstServlet对其处理。在FirstServlet中使用表单提交的请求参数(学号和姓名)创建一个Student对象并将其作为属性存储在请求作用域中,然后通过请求对象的getRequestDispatcher()方法获得RequestDispatcher()对象,将请求转发到SecondServlet。

网络应用程序设计(IDEA版)—— 实验一:Servlet技术及应用_第4张图片

package com.demo;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/FirstServlet")
public class FirstServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request,
                          HttpServletResponse response)
            throws ServletException, IOException {
        String sno = request.getParameter("sno");
        String name = request.getParameter("sname");
        Student student = new Student(sno,name);
        request.setAttribute("student", student);
        RequestDispatcher rd = request.getRequestDispatcher("/SecondServlet");
        rd.forward(request, response);
    }
}

【步骤4】在SecondServlet中取出请求作用域中存储的Student对象,并显示输出该学生的学号和姓名,5秒钟之后,自动返回input.html页面。

网络应用程序设计(IDEA版)—— 实验一:Servlet技术及应用_第5张图片     网络应用程序设计(IDEA版)—— 实验一:Servlet技术及应用_第6张图片 

图2.1  input.html页面显示结果             图2.2  SecondServlet显示结果

网络应用程序设计(IDEA版)—— 实验一:Servlet技术及应用_第7张图片      网络应用程序设计(IDEA版)—— 实验一:Servlet技术及应用_第8张图片

网络应用程序设计(IDEA版)—— 实验一:Servlet技术及应用_第9张图片

右上角运行。

网络应用程序设计(IDEA版)—— 实验一:Servlet技术及应用_第10张图片

网络应用程序设计(IDEA版)—— 实验一:Servlet技术及应用_第11张图片

网络应用程序设计(IDEA版)—— 实验一:Servlet技术及应用_第12张图片

package com.demo;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/SecondServlet")
public class SecondServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request,
                          HttpServletResponse response)
            throws ServletException, IOException {
        Student student= (Student)request.getAttribute("student");
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.println("学生信息");
        out.println("学号:"+student.getSno()+"
"); out.println("姓名:"+new String( student.getName().getBytes("iso-8859-1"),"UTF-8")+"
"); response.setHeader("Refresh","5;url=input.html"); } }

2. 编写一个Servlet,显示所有请求头信息:

【步骤1】在exp01项目下编写一个名为ShowHeadersServlet.java的Servlet程序,使其能够检索所有的请求头,并且能够以表格的形式将请求头的参数名和参数值显示出来。

网络应用程序设计(IDEA版)—— 实验一:Servlet技术及应用_第13张图片

package com.demo;

import java.io.PrintWriter;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;

@WebServlet(name = "ShowHeadersServlet", value = "/ShowHeadersServlet")
public class ShowHeadersServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=gb2312");
        PrintWriter out = response.getWriter();

        out.println("");
        out.println("All Headers");
        out.println("");
        out.println("");
        out.println("

All Request Headers

"); out.println("\n"+"\n"+"
Header NameHeader Value"); Enumeration headerNames = request.getHeaderNames(); while(headerNames.hasMoreElements()){ String headerName = (String)headerNames.nextElement(); out.println("
"+headerName); out.println(""+request.getHeader(headerName)); } out.println("
\n"); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request,response); } }

【步骤2】在浏览器地址栏中输入正确的URL,访问并测试该Servlet。

网络应用程序设计(IDEA版)—— 实验一:Servlet技术及应用_第14张图片3. 编写一个名为ExcelServlet的Servlet程序,通过设置响应内容类型和输出流,向客户端浏览器响应一个带数据的Excel电子表格,程序的运行结果要求如下图所示。

网络应用程序设计(IDEA版)—— 实验一:Servlet技术及应用_第15张图片

图3.1 生成Excel电子表格

访问界面,把文件下载下来用excel打开即可。 

网络应用程序设计(IDEA版)—— 实验一:Servlet技术及应用_第16张图片

网络应用程序设计(IDEA版)—— 实验一:Servlet技术及应用_第17张图片

package com.demo;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet(name = "ExcelServlet", value = "/ExcelServlet")
public class ExcelServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setHeader("Cache-Control","no-cache");
        response.setContentType("application/vnd.ms-excel;charset=GB2312");
        PrintWriter out = response.getWriter();
        out.println("学号\t姓名\t性别\t年龄\t所在系");
        out.println("95001\t李勇\t男\t20\t信息");
        out.println("95002\t刘晨\t女\t19\t数学");
    }

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

4. 使用ServletConfig检索Servlet的初始化参数。

【步骤1】编写ConfigDemoServlet程序,通过注释为其添加初始化参数email、telephone,在Servlet中读取该servlet的名称和初始化参数email、telephone,并将这两个参数的值在响应的HTML文本中输出。

【步骤3】在浏览器的地址栏中输入下面URL请求该Servlet:

exp01/configDemo.do

     要求程序的运行结果如下图所示:

网络应用程序设计(IDEA版)—— 实验一:Servlet技术及应用_第18张图片

  

图4.1 ConfigDemoServlet程序的运行结果

网络应用程序设计(IDEA版)—— 实验一:Servlet技术及应用_第19张图片

网络应用程序设计(IDEA版)—— 实验一:Servlet技术及应用_第20张图片

package com.demo;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class ConfigDemoServlet
 */
@WebServlet(
        urlPatterns = { "/configDemo.do" },
        initParams = {
                @WebInitParam(name = "email", value = "[email protected]"),
                @WebInitParam(name = "telephone", value = "8899123")
        })
public class ConfigDemoServlet extends HttpServlet {
    String servletName = null;
    ServletConfig config = null;
    String email = null;
    String telephone = null;
    /**
     * @see HttpServlet#init(ServletConfig)
     */
    public void init(ServletConfig config) throws ServletException {
        // TODO Auto-generated method stub
        this.config = config;
        servletName = config.getServletName();
        email = config.getInitParameter("email");
        telephone = config.getInitParameter("telephone");
    }
    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.println("");
        out.println("配置对象");
        out.println("Servlet名称:"+servletName+"
"); out.println("Email地址:"+email+"
"); out.println("电话:"+telephone); out.println(""); } }

5. 为ServletContext配置初始化参数并进行访问。

在web.xml文件中为当前web应用添加两个名为admin-email和admin-tel的ServletContext初始化参数,在ConfigDemoServlet中获取这两个参数的参数值,使用ServletContext对象将admin-email和admin-tel的参数值写入日志文件中,并查看日志文件。

web.xml:

网络应用程序设计(IDEA版)—— 实验一:Servlet技术及应用_第21张图片



  chapter02
  
    index.html
    index.htm
    index.jsp
    default.html
    default.htm
    default.jsp
  
  
    admin-email
    生菜虾@qq.com
  
  
    admin-tel
    1025
  

 ServletContext:

网络应用程序设计(IDEA版)—— 实验一:Servlet技术及应用_第22张图片

访问网页后看控制台:

网络应用程序设计(IDEA版)—— 实验一:Servlet技术及应用_第23张图片

package com.demo;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
 * Servlet implementation class ServletContextDemo
 */
@WebServlet(
        urlPatterns = { "/ServletContext" }
)
public class ServletContext extends HttpServlet {
    private static final long serialVersionUID = 1L;
    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        PrintWriter out=response.getWriter();
        javax.servlet.ServletContext context=getServletConfig().getServletContext();
        String admin_Email=(String)context.getInitParameter("admin-email");
        String admin_tel=(String)context.getInitParameter("admin-tel");
        context.log(admin_tel);
        context.log(admin_Email);
    }
}

6. 编写一个名为CountServlet的Servlet程序:

1)使用成员变量保存该Servlet被访问的次数,试打开多个浏览器窗口模拟多个用户同时访问该Servlet,观察该Servlet被访问次数的变化。

2)修改该Servlet,通过ServletContext属性保存被多用户同时访问的次数,体会用ServletContext在应用作用域共享数据的方法。

网络应用程序设计(IDEA版)—— 实验一:Servlet技术及应用_第24张图片网络应用程序设计(IDEA版)—— 实验一:Servlet技术及应用_第25张图片网络应用程序设计(IDEA版)—— 实验一:Servlet技术及应用_第26张图片

网络应用程序设计(IDEA版)—— 实验一:Servlet技术及应用_第27张图片

package com.demo;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class countServlet1
 */
@WebServlet("/CountServlet")
public class CountServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    public CountServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置字符编码
        request.setCharacterEncoding("utf-8");
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html; charset=utf-8");


        //获取全局的共享数据
        ServletContext servletContext = this.getServletContext();

        //获取计数器count
        Integer count = (Integer) servletContext.getAttribute("count");

        //如果获取的计算器对象为空 ,说明是第一次访问,并将count,放入servletCount
        if( servletContext.getAttribute("count") == null) {
            count = 1;
            servletContext.setAttribute("count", count);
        }else {
            //否则就不是第一次访问,将登陆的计数器进行加1的数据更新
            servletContext.setAttribute("count", count+1);
        }

        //将登陆的次数显示在页面上
        PrintWriter out =response.getWriter();
        out.print("\r\n" +
                "\r\n" +
                "\r\n" +
                "\r\n" +
                "登陆网页次数统计\r\n" +
                "\r\n" +
                "");
        out.print("

"); out.print("count="+ servletContext.getAttribute("count")); out.print("

"); out.print("\r\n" + ""); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub doGet(request, response); } }

四、思考题

1. 请求中的参数如果是中文,如何正常显示中文参数值?

答:对中文参数进行两次URLEncode,由于服务器会自动进行一次URLDecode,所以我们在服务端编程再进行一次URLDecode。

2. 使用RequestDispatcher的forward()方法转发请求和使用HttpServletResponse的sendRedirect()方法重定向请求有什么区别?

答:(1)RequestDispatcher.forward 方法只能将请求转发给同一个WEB应用中的组件;而HttpServletResponse.sendRedirect 方法不仅可以重定向到当前应用程序中的其他资源,还可以重定向到同一个站点上的其他应用程序中的资源,甚至是使用绝对URL重定向到其他站点的资源。

(2)调用HttpServletResponse.sendRedirect 方法重定向的访问过程结束后,浏览器地址栏中显示的URL会发生改变,由初始的URL地址变成重定向的目标URL;而调用 RequestDispatcher.forward 方法的请求转发过程结束后,浏览器地址栏保持初始的URL地址不变。

(3)HttpServletResponse.sendRedirect 方法对浏览器的请求直接作出响应,响应的结果就是告诉浏览器去重新发出对另外一个URL的访问请求。

(4)RequestDispatcher.forward 方法的调用者与被调用者之间共享相同的request 对象和response 对象,它们属于同一个访问请求和响应过程;而HttpServletResponse.sendRedirect 方法调用者与被调用者使用各自的request 对象和response 对象,它们属于两个独立的访问请求和响应过程。

(5)无论是RequestDispatcher.forward 方法,还是HttpServletResponse.sendRedirect 方法,在调用它们之前,都不能有内容已经被实际输出到了客户端。如果缓冲区中已经有了一些内容,这些内容将被从缓冲区中清除。

3. 什么是Web归档文件?如何为一个Web应用创建一个WAR文件?如何发布WAR文件?

答:(1)相当于 windows 下保存网页为 web档案(.mht)的功能,即把页面上所有元素(文字、格式、图片等)都保存在硬盘上的一个特殊文件里边方便离线查看和使用。

(2)可以在命令行中运用jar命令。或者直接利用IDE工具进行打包。

(3)方法一:直接将应用目录复制到%tomcat_home%\webapps目录下。方法二:在%tomcat_home%\conf下的server.xml的下增加。方法三:在%tomcat_home%\conf\catalina\localhost\下创建news.xml,内容同上,文件名必须与path路径一致。方法四:在Tomcat Manager中发布:

Context Path=/news

xml configuration file URL:\conf\catalina\localhost

WAR or Directory URL:C:\News

4. 如何编写线程安全的Servlet?

答:(1)变量的线程安全:这里的变量指字段和共享数据(如表单参数值)。

(2)属性的线程安全。

(3)使用同步的集合类。

(4)不要在Servlet中创建自己的线程来完成某个功能。

(5)在多个servlet中对外部对象(比方文件)进行修改操作一定要加锁,做到互斥的访问。

(6)javax.servlet.SingleThreadModel接口是一个标识接口,如果一个Servlet实现了这个接口,那Servlet容器将保证在一个时刻仅有一个线程可以在给定的servlet实例的service方法中执行。将其他所有请求进行排队。

如有建议或想法,欢迎一起讨论学习~

如果觉得有帮助的话就点个赞8~

你可能感兴趣的:(网络应用程序设计实验,servlet,intellij-idea,java)