JavaWeb Servlet

Servlet

Service()

servlet中的service方法实际上就是完成请求的分发处理,会根据客户端不同的提交的方式来执行不同的方法!

@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

    //获取客户端的提交方式
    String method=req.getMethod();
    System.out.println("客户端提交方式为:"+method);
    
    if (method.equals("GET"))
    {
        doGet(req,resp);
    }else if (method.equals("POST"))
    {
        doPost(req,resp);
    }
}

 @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("执行了doGet方法!!!");

        //获取servlet核心配置对象
        ServletConfig servletConfig = getServletConfig();
        String mysql = servletConfig.getInitParameter("mysql_url");
        System.out.println(mysql);

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("执行了doPost方法!!!");
    }
<!--xml中servletConfig.getInitParameter("mysql_url")的配置-->
<servlet>
    <servlet-name>hello</servlet-name>
    <servlet-class>com.zc.servlet.HelloServlet</servlet-class>
    <init-param>
        <param-name>mysql_url</param-name>
        <param-value>jdbc:mysql://localhost:3306</param-value>
    </init-param>
</servlet>

一般来说客户端提交的方式是Get形式,所以Service()方法据此执行doGet()方法。

如果我们写一个前端html文件,生成一个form表单,设置提交方式为Post,那么Service()方法据此执行doPost()方法。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="http://localhost:8080/Servlet/HelloServlet" method="post">
        <input type="submit" value="提交">

    </form>


</body>
</html>

Servletconfig、ServletContext

Servletconfig

生命周期:ServletConfig代表当前Servlet在web.xml中的配置信息,是Servlet中的一个核心配置对象,而且该对象的生命周期是随着容器的创建而创建,容器的销毁而销毁,在工程的任意位置去获取该实例的时候,指向的都是同一份内存地址

作用: 在Servlet实例加载的时候去获取局部的(当前Servlet实例)初始化信息。在Servlet的配置文件中,可以使用一个或多个标签为servlet配置一些初始化参数。当servlet配置了初始化参数后,web容器在创建servlet实例对象时,会自动将这些初始化参数封装到ServletConfig对象中,并在调用Servlet的init()方法时,

public void init(ServletConfig config) throws ServletException {
    this.config = config;
    this.init();
}

将ServletConfig对象传递给Servlet。进而,通过ServletConfig对象就可以得到当前Servlet的初始化参数信息。

作用范围:当前Servlet类

单例:

ServletConfig servletConfig01 = getServletConfig();
 ServletConfig servletConfig02 = getServletConfig();
 System.out.println("-------------ServletConfig配置对象是否是单例的-----------------");
 System.out.println(servletConfig01);
 System.out.println(servletConfig02);
 System.out.println(servletConfig01 == servletConfig02);//true

ServletConfig配置

栗子:

有一个名为HelloServlet的Servlet,在web.xml中的标签下,通过标签为这个Servlet配置一个初始化参数mysql_url:

<servlet>
    <servlet-name>hello</servlet-name>
    <servlet-class>com.zc.servlet.HelloServlet</servlet-class>
    <init-param>
        <param-name>mysql_url</param-name>
        <param-value>jdbc:mysql://localhost:3306</param-value>
    </init-param>
</servlet>

那么在当前的Servlet类中就可以获取到上面的参数:

ServletConfig servletConfig = getServletConfig();
String mysql = servletConfig.getInitParameter("mysql_url");
System.out.println(mysql);

ServletContext

ServletContext 上下文域对象。

生命周期:ServletContext是Servlet中的一个上下文对象,而且该对象的声明周期是随着容器的创建而创建,容器的销毁而销毁,在工程的任意位置去获取该实例的时候,指向的都是同一份内存地址。

作用:ServletConfig对象中维护了ServletContext对象的引用,开发人员在编写servlet时,可以通过ServletConfig.getServletContext()方法获得ServletContext对象。可以像map一样存放数据,取出数据,而且是在工程的任意位置取出数据,作业范围是整个web工程,可以去读取全局的初始化信息,可以在工程的任何位置读取。

其他域对象:

  •     request(也是一个域对象,也可以去存取数据,不过该对象的取值范围比较小)
    
  •     session(会话对象,会对客户端和服务端进行绑定)
    

作用范围:由于一个WEB应用中的所有Servlet共享同一个ServletContext对象,因此Servlet对象之间可以通过ServletContext对象来实现通讯。ServletContext对象通常也被称之为context域对象

单例:

ServletContext servletContext1 = getServletContext();
System.out.println("-------------Servlet上下文配置对象是否是单例的-----------------");
System.out.println(servletContext);
System.out.println(servletContext1);
System.out.println(servletContext == servletContext1);//true

ServletContext共享数据

栗子:

HelloServlet02.java:

 @Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取域对象
ServletContext servletContext = getServletContext();
//往域中存放数据 以类似键值对的形式
servletContext.setAttribute("username","root");
servletContext.setAttribute("password","123456");

//取出域中的数据 除此类的此方法外 其他类的其他方法都可以获取到
System.out.println("username的值:"+servletContext.getAttribute("username"));
System.out.println("password的值:"+servletContext.getAttribute("password"));
}

HelloServlet03.java:

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

    //获取上下文域对象
    ServletContext servletContext = getServletContext();

    //要先访问HelloServlet02后端资源 存入ServletContext的值 再访问HelloServlet03后端资源获取值
    //取出域中的数据
    System.out.println("username的值:"+servletContext.getAttribute("username"));
    System.out.println("password的值:"+servletContext.getAttribute("password"));

}

在xml中配置全局初始化数据

栗子:

<!--配置全局的初始化数据-->
<context-param>
    <param-name>name</param-name>
    <param-value>jack</param-value>
</context-param>
<context-param>
    <param-name>age</param-name>
    <param-value>20</param-value>
</context-param>
<context-param>
    <param-name>sex</param-name>
    <param-value>男</param-value>
</context-param>
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		ServletContext servletContext = getServletContext();
		//取出全局的初始化数据
        String name = servletContext.getInitParameter("name");
    
        String age = servletContext.getInitParameter("age");
    
        String sex = servletContext.getInitParameter("sex");
    
        System.out.println(name+" "+age+" "+sex);
}

HTTP协议:

Get和Post请求方式

Get请求方式会将发送到服务器端的数据封装在地址上,Post请求方式会将数据封装在请求体中,所以Post请求方式相对来说安全一点,因为数据是隐藏在请求体中的。而Get方式相对不安全,在地址栏上可以直接看见请求的数据,而且Post请求方式所能够传递的数据大小要高于Get方式。所以经常使用的请求方式一般是Post。

Get请求

  1. 请求行
    1)请求的方式Get
    2)请求的资源路径 [+?+请求参数] 请求的协议的版本号HTTP/1.1

  2. 请求头
    key : value组成不同的键值对,表示不同的含义

    image-20210731143238579

Post请求

  1. 请求行
    1)请求的方式Post
    2)请求的资源路径 [+?+请求参数]
    3)请求的协议的版本号HTTP/1.1

  2. 请求头key : value不同的请求头,有不同的含义

  3. 请求体:就是发送给服务器的数据

    image-20210731143212888

HttpRequestServlet

常用方法

Get方式

@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

    //处理中文乱码,一般POST方式会出现中文乱码
    req.setCharacterEncoding("utf-8");
    if (req.getMethod().equals("GET"))
        doGet(req,resp);
    else if (req.getMethod().equals("POST"))
        doPost(req,resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取请求的资源路径
String requestURI = req.getRequestURI();

// /Servlet/hello05
System.out.println("请求的资源路径为:"+requestURI);

StringBuffer requestURL = req.getRequestURL();

// http://localhost:8080/Servlet/hello05
System.out.println("统一资源定位符"+requestURL);

String remoteHost = req.getRemoteHost();

// 0:0:0:0:0:0:0:1
System.out.println(remoteHost);

String header = req.getHeader("User-Agent");
    
// Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36
System.out.println(header);
}

通过Get方式传递数据给后端,后端通过req.getParameter()方法获取数据

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name = req.getParameter("name");
String age = req.getParameter("age");
String sex = req.getParameter("sex");
System.out.println(name);
System.out.println(age);
System.out.println(sex);
}
  1. 在浏览器端输入地址后面带上参数

  1. 然后访问后,也可以在浏览器的开发者工具(按下键盘的F12)Network下面查看到传递的数据

  1. 如果要接收的key值有多个value,则需要调用请求对象的req.getParameterValues()方法
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //通过请求对象来接收value有多个的key
    String[] hobbies = request.getParameterValues("hobby");

    for (String hobby : hobbies) {
        System.out.println(hobby);
    }
}
  1. 在浏览器端输入带参数的地址,hobby一共有3个值

  1. 同理我们可以在网页的开发者工具中看到参数,也可以在控制台上看到打印的输出
打篮球
敲代码
打游戏

Post方式

  1. 要以Post方式进行提交,需要在新html文件中使用表单标签,设置提交方式为Post

hello.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <!--跳转到后端的HelloServlet05资源-->
    <form action="http://localhost:8080/Servlet/HelloServlet05" method="post">

        username: <input type="text" name="username"><br>
        password: <input type="password" name="password"><br>

        <!--单选按钮表单控件-->
        sex: 男:<input type="radio" value="男" name="sex">
             女:<input type="radio" value="女" name="sex">
        <br>

        <!--下拉菜单控件-->
        country: <select name="country">
        <option name="1">--请选择--</option>
        <option name="美国">美国</option>
        <option name="中国">中国</option>
        <option name="德国">德国</option>
        </select>
        <br>
        
        <!--复选框 跟单选框的区别就是可以选多个值-->
        hobby:
        睡觉<input type="checkbox" name="hobby" value="睡觉"><br>
        打篮球<input type="checkbox" name="hobby" value="打篮球"><br>
        打乒乓球<input type="checkbox" name="hobby" value="打乒乓球"><br>
    </select><br>
        <input type="submit" value="提交">
    </form>
</body>
</html>
  1. 浏览器访问:

  1. HelloServlet05.java

除了在Web.xml中手动配置资源外,还可以基于注解的方式进行xml资源配置

例如

//基于注解进行xml资源配置
@WebServlet("/HelloServlet05")
//基于注解进行xml资源配置
@WebServlet("/HelloServlet05")
public class HelloServlet05 extends HttpServlet {

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //处理中文乱码,一般POST方式会出现中文乱码
        req.setCharacterEncoding("utf-8");
        if (req.getMethod().equals("GET"))
            doGet(req,resp);
        else if (req.getMethod().equals("POST"))
            doPost(req,resp);
    }

    //这里主要演示Post方式,doGet方法忽略
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        String sex = req.getParameter("sex");
        String country = req.getParameter("country");
        System.out.println(username);
        System.out.println(password);
        System.out.println(sex);
        System.out.println(country);
        
        //用getParameterValue方法返回多个值
        //通过请求对象来接收value有多个的key
        String[] hobbies = req.getParameterValues("hobby");

        for (String hobby : hobbies) {
            System.out.println(hobby);
        }
    }
}
  1. 点击浏览器页面表单的提交按钮,在 网页-检查-Network-HelloServlet05 里可以看到以Post方式传递的数据:

  1. 此外,在后端控制台上,也调用了doPost()方法输出:
jack
123456
男
德国
睡觉
打篮球
打乒乓球

HttpServletResponse

  1. 后端通过HttpServletResponse对象响应给客户端传递数据
  • 字节流getOutPutStream()

    常用于下载(传递二进制数据)

  • 字符流getWriter()

    常用于回传字符串(常用)

  • 响应的乱码解决

    setContentType("text/html;charset=utf-8")

package com.zc.servlet;


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

//基于注解进行xml资源配置
@WebServlet("/HelloServlet06")
public class HelloServlet06 extends HttpServlet {

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //传递数据给前端
        //response.setCharacterEncoding("utf-8"); 这样一般不解决问题,

        //可以让前后端字符集统一的方法
        resp.setContentType("text/html;charset=utf-8");

        //向Web容器(Tomcat 服务器)请求字符流对象
        resp.getWriter().print("hello servlet");
        resp.getWriter().print("<br/>");
        resp.getWriter().print("响应成功!!");
        resp.getWriter().print("<br/>");
        resp.getWriter().print("<input type='text'>");

        /*
        //向Web容器(Tomcat 服务器)请求字节流对象
        response.getOutputStream().print("hello servlet");
        response.getOutputStream().print("hello servlet");
        */

    }

}
  1. 浏览器端显示服务器端回传的数据:

posted @ 2021-07-31 20:31  ins1mnia  阅读(27)  评论(0编辑  收藏  举报