还不会Servlet开发?来这里带你了解Servlet开发的基础知识

来看看在Servlet开发中的一些真实场景的应用

关于Servlet的规范扩展———监听器与过滤器

一、Servlet规范介绍:

1. servlet规范来自于JavaEE规范中的一种
2. 作用:
  1. 在Servlet规范中,指定【动态资源文件】开发步骤
  2. 在Servlet规范中,指定Http服务器调用动态资源文件规则
  3. 在Servlet规范中,指定Http服务器管理动态资源文件实例对象规则

二、Servlet接口实现类

1. Servlet接口来自于Servlet规范下一个接口,这个接口存在Http服务器提供的jar包
2. Tomcat服务器下lib文件有一个servlet-api.jar存放Servlet接口(javax.servlet.Servlet)
```java
package javax.servlet;
import java.io.IOException;
public interface Servlet{
	void init(ServletConfig var1) throws ServletException;
	
	ServletConfig getServletConfig();

	void service(ServletRequest var1,ServletResponse var2) throes ServletException,IOException;

	String getServletInfo();
	
	void destory();
}
```
3. Servlet规范中认为,Http服务器能调用的【动态资源文件】必须是一个Servlet接口实现类
例子:
		

```java
class Student{
				//不是动态资源文件,Tomcat无权调用
			}
			class Teacher implements Servlet{
				//合法动态资源文件,Tomcat有权调用
				Servlet obj = new Teacher();
				obj.doGet();
			}
```

三、Servlet接口实现类开发步骤

1. 创建一个Java类继承于HttpServlet父类,使之成为一个Servlet接口实现类
2. 重写HttpServlet父类的两个方法。doGet或者doPost
			get
浏览器 -------》oneServlet.doGet() 
			post
浏览器 -------》oneServlet.doPost() 
3. 将Servlet接口实现类信息【注册】到Tomcat服务器
【网站】-------》【web】-------》【WEB-INF】------》web.xml
<!--将Servlet接口实现类类路径地址交给Tomcat-->
<servlet>
	<servlet-name>name</servlet-name>	<!--声明一个变量存储servlet接口实现类类路径-->
	<servlet-class>com.lht.controller.OneServlet</servlet-class>	<!--声明servlet接口实现类类路径-->
	//这就相当于Tomcat  String name = "com.lht.controller.OneServlet"
	<!--为了降低用户访问Servlet接口实现类难度,需要设置简短请求别名-->
	<servlet-mapping>
		<servlet-name>name</servlet-name>
		<url-pattern>/one</url-pattern>		<!--设置简短请求别名,别名在书写时必须以“/”为开头-->
	<.servlet-mapping>
</servlet>

//如果先烈浏览器向Tomcat索要OneServlet地址------》http://localhost:8080/myWeb/one
/* HttpServlet是一个抽象类,继承于GenericServlet
 * public abstract class HttpServlet extends GenericServlet{}
 * 我们知道如果父类实现了一个接口,那么它的子类也是这个接口的实现类。
 * 
 * 其实我们可以直接实现Servlet类public class OneServlet implements Servlet{},但是这样就需要重写上面的五个方法,但是在实际开发中只需要用到service方法,这就使得开发难度有所提高。
 * 
 * 抽象类的作用就是降低了接口实现类对接口实现过程的的难度,将接口中不需要使用抽象方法交给抽象类进行完成,这样接口实现类只需要对接口需要的方法进行重写。
 * 
 * 我们前面提到servlet接口中只有service()方法对于Servlet接口实现类有用,其他四个方法都是没用的。
 * 是因为Tomcat根据Servlet规范调用Servlet接口实现类规则:
 * 1. Tomcat有权创建Servlet接口实现类实例对象  
 * 		 Servlet oneservlet = new OneServlet();
 * 2. Tomcat根据实例对象调用service方法处理当前请求
 * 		 oneServlet.service();
 *
 *			   extends						extends                         implements                    
 *  oneServlet-------->(sbatract)HttpServlet------->(abstract)GenericServlet----------->servlet接口
 * 					           service							init
 * 																destory
 * 																getServletInfo
 * 																getServlet
 *
 *通过父类决定在何种情况下调用子类中方法
 *HttpServlet: service(){
 *					if(请求方法 == GET){
 *						this.doGet;					
 *					}else if(请求方法 == POST){
 *						this.doPost;
 *					}
 *				}
 * OneServlet:   doGet    doPost
 *   Servlet oneServlet  new OneServlet();
 *   oneServlet.service();
 */
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class OneServlet extends HttpServlet {
    @Override
    //将父类中的doGet和doPost继承并重写
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("调用Get方法");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
    }
}
<?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-name>oneServlet</servlet-name>
            <servlet-class>com.lht.controller.OneServlet</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>oneServlet</servlet-name>
            <url-pattern>/one</url-pattern>
        </servlet-mapping>

</web-app>

完成代码之后在 Run——>Edit Configurations
在这里插入图片描述

点击Apply之后点击OK

在这里插入图片描述

点Debug(小虫)后在浏览器中出现,再加上别名one之后返回IDEA在控制台中就可以查看到返回结果(调用GET方法)。

在这里插入图片描述

四、Servlet对象生命周期

1. 网站中所有的Servlet接口实现类的实例对象,只能由Http服务器负责创建。开发人员不能手动创建Servlet接口实现类的实例对象。
2. 在默认情况下,Http服务器接收到对于Servlet接口实现类第一次请求时自动创建这个Servlet接口实现类的实例对象。
在手动情况下,要求Http服务器在启动时自动创建某个Servlet接口实现类的实例对象


```xml
<servlet>
	<servlet-name>name</servlet-name>	<!--声明一个变量存储servlet皆苦实现类类路径-->
	<servlet-class>com.lht.controller.OneServlet</servlet-class>
	<load-on-start>7</load-on-start>	<!--填写一个大于0的整数即可-->
</sevlet>
```
3. 在Http服务器运行期间,一个Servlet接口实现列只能创建出一个实例对象。
4. 在Http服务器关闭时刻,自动将网站中所有的Servlet对象进行销毁。(同样由Http服务器完成)
<?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-name>OneServlet</servlet-name>
        <servlet-class>com.lht.controller.OneServlet</servlet-class>
    </servlet>
    
    <servlet>
        <servlet-name>TwoServlet</servlet-name>
        <servlet-class>com.lht.controller.TwoServlet</servlet-class>
        <!--通知Tomcat在启动时负责创建TwoServlet实例对象-->
        <load-on-startup>9</load-on-startup>
    </servlet>
    <!--别名1-->
    <servlet-mapping>
        <servlet-name>TwoServlet</servlet-name>
        <url-pattern>/two</url-pattern>
    </servlet-mapping>
    <!--别名2-->
    <servlet-mapping>
        <servlet-name>OneServlet</servlet-name>
        <url-pattern>/one</url-pattern>
    </servlet-mapping>
</web-app>
//创建第一个实例对象
package com.lht.controller;

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

public class OneServlet extends HttpServlet {
    public OneServlet(){
        System.out.println("OneServlet类被创建实例对象");
    }
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("OneServlet doGet is run");
    }
}
//创建第二个实例对象
package com.lht.controller;

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

public class TwoServlet extends HttpServlet {
    public TwoServlet(){
        System.out.println("TwoServlet被创建了");
    }
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("TwoServlet doGet is run");
    }
}

由于TwoServlet是在启动Tomcat时创建的实例对象,所以会直接创建。
在这里插入图片描述

当在浏览器中加入one别名才会创建OneServlet实例对象,并且只能创建一个,之后再进行访问时只会调用方法。

在这里插入图片描述

点击图片所指的按钮就会销毁这两个实例对象。
在这里插入图片描述

五、HttpServletResponse接口

1. 介绍:

(1)HttpServletResponse接口来自于Servlet规范中,在Tomcat中存在servlet-api.jar
(2)HttpServletResponse接口实现类由Http服务器负责提供
(3)HttpServletResponse接口负责将doGet/doPost方法执行结果写入到【响应体】交给浏览器
(4)开发人员习惯于将HttpServletResponse接口修饰的对象称为【响应对象】

2. 主要功能

(1)将执行结果以二进制形式写入到【响应体】中

package com.lht.controller;

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 OneServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String result = "Hello World";
        //------------响应对象将结果写入到响应体中---------start
            //1.通过响应对象,向Tomcat索要输出流
            PrintWriter out = response.getWriter();
            //2.通过输出流,将执行结果以二进制形式写入到响应体中
            out.write(result);
        //------------响应对象将结果写入到响应体中---------end
    }//doGet执行完毕
     //Tomcat将响应包推送给浏览器
}
package com.lht.controller;

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;
/*
 * 出现问题:浏览器接收到数据是2,不是50
 * 问题原因:out.write方法可以将【字符】【字符串】【ASCII码】写入到响应体
 * 而50的ASCII码正好是2
 *
 * 解决方法:实际开发过程中,都是通过out.print()方法将真是数据写入到响应体中的
 */

public class TwoServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        int money = 50;
        PrintWriter out = response.getWriter();
        //out.write(money);
        out.print(50);
    }
}
<?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-name>OneServlet</servlet-name>
        <servlet-class>com.lht.controller.OneServlet</servlet-class>
    </servlet>
    <servlet>
        <servlet-name>TwoServlet</servlet-name>
        <servlet-class>com.lht.controller.TwoServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>TwoServlet</servlet-name>
        <url-pattern>/two</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>OneServlet</servlet-name>
        <url-pattern>/one</url-pattern>
    </servlet-mapping>
</web-app>

(2)设置响应头中[content-type]属性值,从而控制浏览器使用对应编译器将响应体二进制数据编译为【文字、图片、视频、命令】

<?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-name>OneServlet</servlet-name>
        <servlet-class>com.lht.controller.OneServlet</servlet-class>
    </servlet>
    <servlet>
        <servlet-name>TwoServlet</servlet-name>
        <servlet-class>com.lht.controller.TwoServlet</servlet-class>
    </servlet>
    <servlet>
        <servlet-name>ThreeServlet</servlet-name>
        <servlet-class>com.lht.controller.ThreeServlet</servlet-class>
    </servlet>
    <servlet>
        <servlet-name>FourServlet</servlet-name>
        <servlet-class>com.lht.controller.FourServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>FourServlet</servlet-name>
        <url-pattern>/four</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>ThreeServlet</servlet-name>
        <url-pattern>/three</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>TwoServlet</servlet-name>
        <url-pattern>/two</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>OneServlet</servlet-name>
        <url-pattern>/one</url-pattern>
    </servlet-mapping>
</web-app>
package com.lht.controller;

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;

/*
 *  问题:Java</br>MySql</br>HTML</br>
 *
 * 问题原因:浏览器在接收到响应包之后,根据【响应头中content-type】属性的值,来采用对应【编译器】对【响应体中二进制内容】进行编译处理。
 *          在默认情况下,content-type属性的值“text” content-type="text"
 *          此时浏览器将会采用【文本编译器】对响应体二进制数据进行解析
 *
 * 解决方案:一定要在得到输出流之前,通过响应对象对响应头中content-type属性进行一次重新赋值用于指定浏览器采用正确编译器
 *
 *
 */
public class ThreeServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String result1 = "Java</br>MySql</br>HTML</br>"; //既有文字内容又有HTML标签内容
        String result2 = "科比</br>乔丹</br>詹姆斯";
        //设置响应头content-type,text/html属性将文字和html标签都进行输出,utf-8可以输出所有文字
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.print(result1);
        out.print(result2);
    }
}

(3)设置响应头中[location]属性,及那个一个请求地址赋值给location,从而控制浏览器向指定服务器发送请求

package com.lht.controller;

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

public class FourServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String result = "http://www.baidu.com?user=zack";

        //通过响应对象,将地址栏赋值给响应头中location属性
        response.sendRedirect(result);  //响应头   location="http://www.baidu.com"
    }
    /*
     *  浏览器在接收到相应包之后,如果发现响应头存在location属性,自动通过地址栏向location指定网站发送请求
     *  sendRedirect方法运城控制浏览器请求行为【请求地址,请求方式,请求参数】
     */
}

六、HttpServletRequest接口

1. 介绍

(1)HttpServletResquest接口来自于Servlet规范中,在Tomcat中存在servlet-api.jar
(2)HttpServletResquest接口实现类由Http服务器负责提供
(3)HttpServletResquest接口负责在doGet/doPost方法时读取Http请求协议包中信息
(4)开发人员习惯于将HttpServletResquest接口修饰的对象称为【请求对象】

2. 作用:

(1)可以读取Http请求协议包中【请求行】信息

<?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-name>OneServlet</servlet-name>
        <servlet-class>com.lht.controller.OneServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>OneServlet</servlet-name>
        <url-pattern>/one</url-pattern>
    </servlet-mapping>
</web-app>
package com.lht.controller;

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

public class OneServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.通过请求对象,读取【请求行】中【url】信息
        String url = request.getRequestURL().toString();
        //2.通过请求对象,读取【请求行】中【method】信息
        String method = request.getMethod();
        /* 3.通过请求资源文件,读取【请求行】中的uri信息
         *  URI:资源文件精准定位地址,在请求行中并没有URI这个属性。
         *       实际上是URL中截取的一个字符串,这个字符串格式“/网站吗/资源文件名”
         *       URI用于让Http服务器对被访问的资源文件进行定位
         */
        String uri = request.getRequestURI();
        System.out.println("URL" +url);
        System.out.println("Method"+method);
        System.out.println("URI"+uri);
    }
}

(2)可以读取保存在Http请求协议包中【请求头】或【请求体】中请求信息

<?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-name>OneServlet</servlet-name>
        <servlet-class>com.lht.controller.OneServlet</servlet-class>
    </servlet>
    <servlet>
        <servlet-name>TwoServlet</servlet-name>
        <servlet-class>com.lht.controller.TwoServlet</servlet-class>
    </servlet>
    <servlet>
        <servlet-name>ThreeServlet</servlet-name>
        <servlet-class>com.lht.controller.ThreeServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>ThreeServlet</servlet-name>
        <url-pattern>/three</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>TwoServlet</servlet-name>
        <url-pattern>/two</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>OneServlet</servlet-name>
        <url-pattern>/one</url-pattern>
    </servlet-mapping>
</web-app>
package com.lht.controller;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;

public class TwoServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.通过请求对象获得【请求头】中【所有请求参数名】
        Enumeration paramNames = request.getParameterNames();     //将所有请求参数名称保存到一个枚举对象进行返回
        while(paramNames.hasMoreElements()){
            String paramName = (String)paramNames.nextElement();
            //2.通过请求对象读取指定的请求参数的值
            String value = request.getParameter(paramName);
            System.out.println("请求参数名"+paramName+" 请求参数值 "+value);
        }
    }
}
package com.lht.controller;

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


/*
 * 问题:以get方式发送中文参数内容时,得到的是正常结果
 *       以post方式发送中文参数内容时,得到的是乱码
 *
 * 原因:浏览器以get方式发送请求,请求参数保存在【请求头】中,在Http请求协议包到达Http服务器之后,第一件事就是进行解码
 *      【请求头】中二进制内容由Tomcat负责解码,其中使用【utf-8】字符集,可以解释一切国家文字
 *
 *      浏览器以post方式发送内容,请求参数保存在【请求体】中,在Http请求协议包到达Http服务器之后,第一件事就是进行解码
 *      【请求体】二进制内容由当前请求对象(request)负责解码,request默认使用【ISO-8859-1】字符集,不能解释中文字符
 *
 * 解决方法:在post请求方式下,在读取请求体内容之前,应该通知请求对象使用utf-8字符集对请求体内容进行一次重新解码
 */
public class ThreeServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //通知请求对象,使用utf-8字符集对请求体二进制内容进行一次重新解码
        request.setCharacterEncoding("utf-8");
        //通过请求对象,读取【请求体】参数信息
        String value1 = request.getParameter("username");
        System.out.println("从请求体得到参数值"+value1);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
       //通过请求对象,读取【请求头】参数信息
        String value2 = request.getParameter("username");
        System.out.println("从请求头得到参数值"+value2);
    }
}

(3)可以代替浏览器向Http服务器申请资源文件调用

七、请求对象和响应对象生命周期

  1. 在Http服务器接收到浏览器发送的【Http请求协议包】之后,自动为当前的【Http请求协议包】生成一个【请求对象】和一个【响应对象】
  2. 在Http服务器调用doGet/doPost方法时,负责将【请求对象】和【响应对象】作为实参传递到方法,确保doGet/doPost正确执行
  3. 在Http服务器推送http响应协议包之前,负责将本次请求关联的【请求对象】和【响应对象】销毁

【请求对象】和【响应对象】生命周期贯穿一次请求的处理过程
【请求对象】和【响应对象】相当于用户在服务器端的代言人
在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值