Servlet的基本使用及基础笔记

简介

Servlet是JavaWeb最为核心的内容,它是Java提供的一门动态的web资源开发技术。

使用Servlet就可以实现,根据不同的登录用户在页面上动态显示不同内容。

Servlet是JavaEE规范之一,其实就是一个接口,将来我们需要定义Servlet类实现Servlet接口,并由web服务器运行Servlet

快速入门

编写一个Servlet类,并使用IDEA中Tomcat插件进行部署,最终通过浏览器访问所编写的Servlet程序

创建Web项目web-demo:

配置:在类上使用@WebServlet注解,配置该Servlet的访问路径:@WebServlet("/demo1")

访问:启动Tomcat,浏览器中输入URL地址访问该Servlet:http://localhost:8080/web-demo/demo1

访问成功后会在控制台会打印servlet hello world~ 说明servlet程序已经成功运行。

执行流程:

浏览器发出http://localhost:8080/web-demo/demo1请求,从请求中可以解析出三部分内容,分别是localhost:8080、web-demo、demo1

  • 根据localhost:8080可以找到要访问的Tomcat Web服务器

  • 根据web-demo可以找到部署在Tomcat服务器上的web-demo项目

  • 根据demo1可以找到要访问的是项目中的哪个Servlet类,根据@WebServlet后面的值进行匹配

找到ServletDemo1这个类后,Tomcat Web服务器就会为ServletDemo1这个类创建一个对象,然后调用对象中的service方法

  • ServletDemo1实现了Servlet接口,所以类中必然会重写service方法供Tomcat Web服务器进行调用

  • service方法中有ServletRequest和ServletResponse两个参数,ServletRequest封装的是请求数据,ServletResponse封装的是响应数据,后期我们可以通过这两个参数实现前后端的数据交互

生命周期:对象的生命周期指一个对象从被创建到被销毁的整个过程。

Servlet运行在Servlet容器(web服务器)中,其生命周期由容器来管理,分为4个阶段:

加载和实例化:默认情况下,当Servlet第一次被访问时,由容器创建Servlet对象

默认情况,Servlet会在第一次访问被容器创建,但是如果创建Servlet比较耗时的话,那么第一个访问的人等待的时间就比较长,用户的体验就比较差,那么我们能不能把Servlet的创建放到服务器启动的时候来创建,具体如何来配置?

@WebServlet(urlPatterns = "/demo1",loadOnStartup = 1)

loadOnstartup的取值有两类情况

(1)负整数:第一次访问时创建Servlet对象

(2)0或正整数:服务器启动时创建Servlet对象,数字越小优先级越高

初始化:在Servlet实例化之后,容器将调用Servlet的init()方法初始化这个对象,完成一些如加载配置文件、创建连接等初始化的工作。该方法只调用一次

请求处理:每次请求Servlet时,Servlet容器都会调用Servlet的service()方法对请求进行处理

服务终止:当需要释放内存或者容器关闭时,容器就会调用Servlet实例的destroy()方法完成资源的释放。在destroy()方法调用之后,容器会释放这个Servlet实例,该实例随后会被Java的垃圾收集器所回收

通过案例演示下上述的生命周期:

package com.web;

import javax.servlet.*;

import javax.servlet.annotation.WebServlet;

import java.io.IOException;

/**

* Servlet生命周期方法

*/

@WebServlet(urlPatterns = "/demo2",loadOnStartup = 1)

public class ServletDemo2 implements Servlet {

/**

* 初始化方法

* 1.调用时机:默认情况下,Servlet被第一次访问时,调用

* * loadOnStartup: 默认为-1,修改为0或者正整数,则会在服务器启动的时候,调用

* 2.调用次数: 1次

* @param config

* @throws ServletException

*/

public void init(ServletConfig config) throws ServletException {

System.out.println("init...");

}

/**

* 提供服务

* 1.调用时机:每一次Servlet被访问时,调用

* 2.调用次数: 多次

* @param req

* @param res

* @throws ServletException

* @throws IOException

*/

public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {

System.out.println("servlet hello world~");

}

/**

* 销毁方法

* 1.调用时机:内存释放或者服务器关闭的时候,Servlet对象会被销毁,调用

* 2.调用次数: 1次

*/

public void destroy() {

System.out.println("destroy...");

}

public ServletConfig getServletConfig() {

return null;

}

public String getServletInfo() {

return null;

}

}

方法介绍:

Servlet中总共有5个方法:

初始化方法:在Servlet被创建时执行,只执行一次:void init(ServletConfig config)

提供服务方法: 每次Servlet被访问,都会调用该方法:void service(ServletRequest req, ServletResponse res)

销毁方法:当Servlet被销毁时,调用该方法。在内存释放或服务器关闭时销毁Servlet:void destroy()

获取Servlet信息:

String getServletInfo()

//该方法用来返回Servlet的相关信息,没有什么太大的用处,一般我们返回一个空字符串即可

public String getServletInfo() {

return "";

}

获取ServletConfig对象:ServletConfig getServletConfig()

ServletConfig对象,在init方法的参数中有,而Tomcat Web服务器在创建Servlet对象的时候会调用init方法,必定会传入一个ServletConfig对象,我们只需要将服务器传过来的ServletConfig进行返回即可。具体如何操作?

package com.web;

import javax.servlet.*;

import javax.servlet.annotation.WebServlet;

import java.io.IOException;

/**

* Servlet方法介绍

*/

@WebServlet(urlPatterns = "/demo3",loadOnStartup = 1)

public class ServletDemo3 implements Servlet {

private ServletConfig servletConfig;

/**

* 初始化方法

* 1.调用时机:默认情况下,Servlet被第一次访问时,调用

* * loadOnStartup: 默认为-1,修改为0或者正整数,则会在服务器启动的时候,调用

* 2.调用次数: 1次

* @param config

* @throws ServletException

*/

public void init(ServletConfig config) throws ServletException {

this.servletConfig = config;

System.out.println("init...");

}

public ServletConfig getServletConfig() {

return servletConfig;

}

/**

* 提供服务

* 1.调用时机:每一次Servlet被访问时,调用

* 2.调用次数: 多次

* @param req

* @param res

* @throws ServletException

* @throws IOException

*/

public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {

System.out.println("servlet hello world~");

}

/**

* 销毁方法

* 1.调用时机:内存释放或者服务器关闭的时候,Servlet对象会被销毁,调用

* 2.调用次数: 1次

*/

public void destroy() {

System.out.println("destroy...");

}

public String getServletInfo() {

return "";

}

}

体系结构:

如果我们将来开发B/S架构的web项目,都是针对HTTP协议,所以我们自定义Servlet,会通过继承HttpServlet

具体的编写格式如下:

@WebServlet("/demo4")

public class ServletDemo4 extends HttpServlet {

@Override

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

//TODO GET 请求方式处理逻辑

System.out.println("get...");

}

@Override

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

//TODO Post 请求方式处理逻辑

System.out.println("post...");

}

}

要想发送一个GET请求,请求该Servlet,只需要通过浏览器发送http://localhost:8080/web-demo/demo4,就能看到doGet方法被执行了

要想发送一个POST请求,请求该Servlet,单单通过浏览器是无法实现的,这个时候就需要编写一个form表单来发送请求,在webapp下创建一个a.html页面,内容如下:

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<title>Title</title>

</head>

<body>

<form action="/web-demo/demo4" method="post">

<input name="username"/><input type="submit"/>

</form>

</body>

</html>

HttpServlet中为什么要根据请求方式的不同,调用不同的方法

package com.web;

import javax.servlet.*;

import javax.servlet.annotation.WebServlet;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;

@WebServlet("/demo5")

public class ServletDemo5 implements Servlet {

public void init(ServletConfig config) throws ServletException {

}

public ServletConfig getServletConfig() {

return null;

}

public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {

//如何调用?

//获取请求方式,根据不同的请求方式进行不同的业务处理

HttpServletRequest request = (HttpServletRequest)req;

//1. 获取请求方式

String method = request.getMethod();

//2. 判断

if("GET".equals(method)){

// get方式的处理逻辑

}else if("POST".equals(method)){

// post方式的处理逻辑

}

}

public String getServletInfo() {

return null;

}

public void destroy() {

}

}

要解决上述问题,我们可以对Servlet接口进行继承封装,来简化代码开发。

packagecom.web;

importjavax.servlet.*;

importjavax.servlet.http.HttpServletRequest;

importjava.io.IOException;

public class MyHttpServlet implements Servlet {

publicvoidinit(ServletConfigconfig) throwsServletException {

}

publicServletConfiggetServletConfig() {

returnnull;

}

publicvoidservice(ServletRequestreq, ServletResponseres) throwsServletException, IOException {

HttpServletRequestrequest= (HttpServletRequest)req;

//1. 获取请求方式

Stringmethod=request.getMethod();

//2. 判断

if("GET".equals(method)){

// get方式的处理逻辑

doGet(req,res);

}elseif("POST".equals(method)){

// post方式的处理逻辑

doPost(req,res);

}

}

protectedvoiddoPost(ServletRequestreq, ServletResponseres) { }

protectedvoiddoGet(ServletRequestreq, ServletResponseres) {}

publicStringgetServletInfo() {returnnull;}

publicvoiddestroy() {}

}

类似MyHttpServlet这样的类Servlet中已经为我们提供好了,就是HttpServlet,翻开源码,大家可以搜索service()方法,你会发现HttpServlet做的事更多,不仅可以处理GET和POST还可以处理其他五种请求方式。​

protected void service(HttpServletRequest req, HttpServletResponse resp)

throws ServletException, IOException

{

String method = req.getMethod();

if (method.equals(METHOD_GET)) {

long lastModified = getLastModified(req);

if (lastModified == -1) {

// servlet doesn't support if-modified-since, no reason

// to go through further expensive logic

doGet(req, resp);

} else {

long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);

if (ifModifiedSince < lastModified) {

// If the servlet mod time is later, call doGet()

// Round down to the nearest second for a proper compare

// A ifModifiedSince of -1 will always be less

maybeSetLastModified(resp, lastModified);

doGet(req, resp);

} else {

resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);

}

}

} else if (method.equals(METHOD_HEAD)) {

long lastModified = getLastModified(req);

maybeSetLastModified(resp, lastModified);

doHead(req, resp);

} else if (method.equals(METHOD_POST)) {

doPost(req, resp);

} else if (method.equals(METHOD_PUT)) {

doPut(req, resp);

} else if (method.equals(METHOD_DELETE)) {

doDelete(req, resp);

} else if (method.equals(METHOD_OPTIONS)) {

doOptions(req,resp);

} else if (method.equals(METHOD_TRACE)) {

doTrace(req,resp);

} else {

//

// Note that this means NO servlet supports whatever

// method was requested, anywhere on this server.

//

String errMsg = lStrings.getString("http.method_not_implemented");

Object[] errArgs = new Object[1];

errArgs[0] = method;

errMsg = MessageFormat.format(errMsg, errArgs);

resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);

}

}

urlPattern配置:

Servlet类编写好后,要想被访问到,就需要配置其访问路径(urlPattern)

  • 一个Servlet,可以配置多个urlPattern

package com.web;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

import javax.servlet.annotation.WebServlet;

/**

* urlPattern: 一个Servlet可以配置多个访问路径

*/

@WebServlet(urlPatterns = {"/demo7","/demo8"})

public class ServletDemo7 extends MyHttpServlet {

@Override

protected void doGet(ServletRequest req, ServletResponse res) {

System.out.println("demo7 get...");

}

@Override

protected void doPost(ServletRequest req, ServletResponse res) {

}

}

在浏览器上输入http://localhost:8080/web-demo/demo7,http://localhost:8080/web-demo/demo8这两个地址都能访问到ServletDemo7的doGet方法。

urlPattern配置规则

访问路径http://localhost:8080/web-demo/user/select

目录匹配:

访问路径http://localhost:8080/web-demo/user/任意

扩展名匹配:

访问路径http://localhost:8080/web-demo/任意.do

任意匹配:

访问路径http://localhost:8080/demo-web/任意

注意:/和/*的区别?

  1. 当我们的项目中的Servlet配置了 "/",会覆盖掉tomcat中的DefaultServlet,当其他的url-pattern都匹配不上时都会走这个Servlet

  1. 当我们的项目中配置了"/*",意味着匹配任意访问路径

  1. DefaultServlet是用来处理静态资源,如果配置了"/"会把默认的覆盖掉,就会引发请求静态资源的时候没有走默认的而是走了自定义的Servlet类,最终导致静态资源不能被访问

XML配置:

前面对应Servlet的配置,我们都使用的是@WebServlet,这个是Servlet从3.0版本后开始支持注解配置,3.0版本前只支持XML配置文件的配置方法。

对于XML的配置步骤有两步:

编写Servlet类

package com.web;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

import javax.servlet.annotation.WebServlet;

public class ServletDemo13 extends MyHttpServlet {

@Override

protected void doGet(ServletRequest req, ServletResponse res) {

System.out.println("demo13 get...");

}

@Override

protected void doPost(ServletRequest req, ServletResponse res) {

}

}

在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 全类名

-->

<servlet>

<!-- servlet的名称,名字任意-->

<servlet-name>demo13</servlet-name>

<!--servlet的类全名-->

<servlet-class>com.itwanxi.web.ServletDemo13</servlet-class>

</servlet>

<!--

Servlet 访问路径

-->

<servlet-mapping>

<!-- servlet的名称,要和上面的名称一致-->

<servlet-name>demo13</servlet-name>

<!-- servlet的访问路径-->

<url-pattern>/demo13</url-pattern>

</servlet-mapping>

</web-app>

这种配置方式和注解比起来,确认麻烦很多,所以建议大家使用注解来开发。但是大家要认识上面这种配置方式,因为并不是所有的项目都是基于注解开发的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值