Servlet知识入门

Servlet: server applet

Servlet概念:运行在服务器端的小程序,是Java EE的灵魂组成部分,servlet和jsp的依赖都在tomcat服务器中。

  • Servlet就是一个接口,定义了Java类被浏览器访问到(tomcat识别)的规则。他不跟正常的Java类一样,没有main方法,只能用tomcat等Web服务器来执行它。
  • 将来我们自定义一个类,实现Servlet接口,复写这个接口的方法 ,才可以使用Servlet

在这里插入图片描述

1、servlet入门程序

1.配置servlet:在WEB-INF中的web.xml中进行配置,这里我们给入门程序ServletDemo1和ServletDemo2配置xml,每一个servlet都要在xml文件中配置这两项

<!--配置Servlet -->
	    <servlet>
	        <servlet-name>demo1</servlet-name>   // 给servlet起的名字
	        <servlet-class>cn.itcast.web.servlet.ServletDemo1</servlet-class>  //该servlet的全类名
	    </servlet>
	
	    <servlet-mapping>    // 一个映射
	        <servlet-name>demo1</servlet-name>   
	        <url-pattern>/demo1</url-pattern>    // 资源路径
	    </servlet-mapping>

<!--  配置servlet  -->
	    <servlet>
	        <servlet-name>demo2</servlet-name>
	        <servlet-class>cn.itcast.web.servlet.ServletDemo2</servlet-class>
	    </servlet>
	
	    <servlet-mapping>
	    <servlet-name>demo2</servlet-name>
	    <url-pattern>/demo2</url-pattern>
	    </servlet-mapping>

2.编写程序,定义servletDemo1这个Java类,继承Servlet接口,然后覆盖重写接口中的5个方法即可。

package cn.itcast.web.servlet;

import javax.servlet.*;
import java.io.IOException;

/**
* servlet快速入门
*/
public class ServletDemo1 implements Servlet {

   @Override
   public void init(ServletConfig servletConfig) throws ServletException {

   }

   @Override
   public ServletConfig getServletConfig() {
       return null;
   }

   @Override
   public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
       System.out.println("hello servlet");
   }

   @Override
   public String getServletInfo() {
       return null;
   }

   @Override
   public void destroy() {

   }
}

3.启动tomcat服务器后,在浏览器中输入url访问tomcat,输入http://localhost/day13_tomcat/demo1,访问第一个servlet。xml文件中的url-pattern是demo1,对应到ServletDemo1这个servlet,所以服务器会运行其中的service,把hello servlet打印到Idea的Tomcat运行窗口中。

Servlet的执行原理:

  1. 当服务器接受到客户端浏览器的请求后,会解析请求URL路径,获取访问的Servlet的资源路径
  2. 查找web.xml文件,是否有对应的标签体内容。
  3. 如果有,则在找到对应的全类名
  4. tomcat会将字节码文件加载进内存(反射技术),并且创建其对象
  5. 调用其方法

2、Servlet的五个方法详解

Servlet中的五个方法,重要的有三个,是生命周期方法。

package cn.itcast.web.servlet;

import javax.servlet.*;
import java.io.IOException;

public class ServletDemo2 implements Servlet {

    /**
     * 初始化方法
     * 在servlet被创建时执行,只会执行一次
     * @param servletConfig
     * @throws ServletException
     */
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("init...");
    }

    /**
     * 获取ServletConfig对象(了解即可)
     * ServletConfig:Servlet的配置对象
     * @return
     */
    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    /**
     * 提供服务方法
     * 每一次Servlet被访问时都会执行,执行多次
     * @param servletRequest
     * @param servletResponse
     * @throws ServletException
     * @throws IOException
     */
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("service...");
    }

    /**
     * 获取servlet的一些信息,版本,作者等等(了解即可)
     * @return
     */
    @Override
    public String getServletInfo() {
        return null;
    }

    /**
     * 销毁方法
     * 在servlet被杀死(即服务器正常关闭时),非正常关闭就不会被执行
     */
    @Override
    public void destroy() {
        System.out.println("destory...");
    }
}

 Servlet中的生命周期方法:
	1. 被创建:执行init方法,只执行一次一般用于加载资源
		* Servlet什么时候被创建?
			* 默认情况下,第一次被访问时,Servlet被创建
			* 可以配置执行Servlet的创建时机:
				* 在web.xml文件中的<servlet>标签下配置
					1. 第一次被访问时,创建
                		* <load-on-startup>的值为负数
		            2. 在服务器启动时,创建
		                * <load-on-startup>的值为0或正整数
		            实例代码:
		            <!--  配置servlet  -->
    <servlet>
        <servlet-name>demo2</servlet-name>
        <servlet-class>cn.itcast.web.servlet.ServletDemo2</servlet-class>
		<!--        指定Servlet的创建时机
                1.第一次被访问时,创建  <load-on-startup>的值为负数
                2.在服务器启动时,创建  <load-on-startup>的值为0或正整数
		-->
        <load-on-startup>-5</load-on-startup>
    </servlet>
    					* Servlet的init方法,只执行一次,说明一个Servlet在内存中只存在一个对象,Servlet是单例的
						* 多个用户同时访问时,可能存在线程安全问题,同一个Servlet变成了多个用户的共享资源。
						* 解决:尽量不要在Servlet中定义成员变量。即使定义了成员变量,也不要对修改值,修改值就会存在并发安全问题(多个用户同时修改造成数据不一致)。
		
		2. 提供服务:执行service方法,执行多次
		* 每次访问Servlet时,Service方法都会被调用一次。
		3. 被销毁:执行destroy方法,只执行一次
			* Servlet被销毁时执行。服务器关闭时,Servlet被销毁
			* 只有服务器正常关闭时,才会执行destroy方法。
			* destroy方法在Servlet被销毁之前执行,一般用于释放资源
			

3、Servlet3.0版本(支持注解配置了)

Servlet3.0:由于之前的servlet每增加一个就要在web.xml文件中增加配置,非常麻烦,所以到了Servlet3.0版本也可以支持注解配置。可以不需要web.xml了

对于注解不熟悉的同学可以参考我关于注解的一篇文章:[https://editor.csdn.net/md/?articleId=123341140]

下面我们就来创建一个Servlet3.0以上版本的项目:
在这里插入图片描述
使用servlet3.0:


步骤:
		1. 创建JavaEE项目,选择Servlet的版本3.0以上,可以不创建web.xml
		2. 定义一个类,实现Servlet接口
		3. 复写Servlet接口中的方法
		4. 在类上使用@WebServlet注解,进行配置,因为注解是加在类上,所以不需要知道全类名,只需知道url
			* @WebServlet("资源路径")
			
package cn.itcast.wen.servlet;

import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;
/**
 * servlet3注解配置
 */
@WebServlet( "/demo2")
public class Servletdemo implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {

    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("Servlet3.0来了...");
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}

然后在浏览器输入url,http://localhost/day13_servlet/demo2,localhost是本机IP,day13_servlet是项目虚拟路径,可以在run->edit configuration->Deploymen->Application context进行配置,demo2就是注解中给该servlet添加的资源路径,所以就可以直接找到Servletdemo这个类,如图
在这里插入图片描述
服务器端显示如下(idea)
在这里插入图片描述
让我们看一看WebServlet这个注解的内容:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package javax.servlet.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface WebServlet {
			    String name() default "";//相当于<Servlet-name>
			
			    String[] value() default {};//代表urlPatterns()属性配置
			
			    String[] urlPatterns() default {};//相当于<url-pattern>
			
			    int loadOnStartup() default -1;//相当于<load-on-startup>
			
			    WebInitParam[] initParams() default {};
			
			    boolean asyncSupported() default false;
			
			    String smallIcon() default "";
			
			    String largeIcon() default "";
			
			    String description() default "";
			
			    String displayName() default "";
			}

注意两个最重要的属性String[] urlPatterns() default {};这是该资源的url,所以可以这么加注解:

@WebServlet(urlPatterns = “/demo2”)

还有String[] value() default {};也代表了url(value属性通常都是设为最重要的属性),但是value的好处是可以默认不写,所以可以简写

@WebServlet( “/demo2”)

另外,@WebServlet注解还有一些不太常用的方式来配置urlpartten,这个注解的属性: String[] urlPatterns() default {};//相当于是一个字符串数组,所以一个Servlet可以配置多个资源路径可以访问:

/**
 * servlet路径配置的几种方式,*是通配符,表示可以书写任意内容就能访问到
 */
// @WebServlet({"/d4","/dd4","/ddd4"})  // 一个servlet可以配置多个路径
//    @WebServlet("/user/demo4")   // 两层路径  需要输入 http://localhost/user/demo4
//    @WebServlet("/user/*")            //需要输入 http://localhost/user/任何内容
      @WebServlet("*.do")               //需要输入 http://localhost/任意内容.do
public class ServletDemo4 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("demo4...");
    }
}

Tomcat和Idea的相关配置:

  1. IDEA会为每一个tomcat部署的项目单独建立一份配置文件,所以Idea可以直接用图形化操作直接修改虚拟目录、端口号等等东西。但是这个跟实际tomcat部署的web项目不是一个东西,

    • 查看控制台的log输出:Using CATALINA_BASE: “C:\Users\fqy.IntelliJIdea2018.1\system\tomcat_itcast”
  2. 工作空间项目 和 tomcat部署的web项目

    • tomcat真正访问的是“tomcat部署的web项目”,“tomcat部署的web项目"对应着"工作空间项目” 的web目录下的所有资源
    • WEB-INF目录下的资源不能被浏览器直接访问,所以那些静态资源注意不要写到WEB-INF中,要写到Web下。
  3. 断点调试Tomcat项目:加断点后,使用"小虫子"启动 dubug 启动Tomcat

Servlet体系结构(接口的两个子类)

众所周知,要实现原生Servlet接口,每次都要覆盖重写其中的五个方法,其实除了service方法我们都很不常用,所以我们很难受,所以对Servlet接口进行了升级,GenericServlet 类和HttpServlet类。

Servlet的体系结构:	
	Servlet -- 接口
		|
	GenericServlet -- 抽象类
		|
	HttpServlet  -- 抽象类
	
GenericServlet类将Servlet接口中四个不常用的方法进行了空实现,当我们继承它时,
只需要重写其中的抽象方法service,方便了许多,其他四个如果需要也可以直接覆盖重写。

但是我们最常用的还是继承了GenericServlet类的HttpServlet 类,以后我们使用的基本都是这个类
*HttpServlet 类:对HTTP协议进行了封装,对servlet中的service方法增加了对请求方式的判断(通过request对象)
我们继承这个类的时候,直接覆盖重写doget和dopost方法(其他五个不太常用),非常的方便。

如图HTTPServlet中将service方法增添了对请求方式的判断,并用响应的请求方式进行响应(doget、dopost)
在这里插入图片描述


// HTTPservlet部分重要源码



public abstract class HttpServlet extends GenericServlet {
    private static final long serialVersionUID = 1L;
    private static final String METHOD_DELETE = "DELETE";
    private static final String METHOD_HEAD = "HEAD";
    private static final String METHOD_GET = "GET";
    private static final String METHOD_OPTIONS = "OPTIONS";
    private static final String METHOD_POST = "POST";
    private static final String METHOD_PUT = "PUT";
    private static final String METHOD_TRACE = "TRACE";
    private static final String HEADER_IFMODSINCE = "If-Modified-Since";
    private static final String HEADER_LASTMOD = "Last-Modified";
    private static final String LSTRING_FILE = "javax.servlet.http.LocalStrings";
    private static final ResourceBundle lStrings = ResourceBundle.getBundle("javax.servlet.http.LocalStrings");

    public HttpServlet() {
    }

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String protocol = req.getProtocol();
        String msg = lStrings.getString("http.method_get_not_supported");
        if (protocol.endsWith("1.1")) {
            resp.sendError(405, msg);
        } else {
            resp.sendError(400, msg);
        }

    }

    protected void doHead(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        if (DispatcherType.INCLUDE.equals(req.getDispatcherType())) {
            this.doGet(req, resp);
        } else {
            NoBodyResponse response = new NoBodyResponse(resp);
            this.doGet(req, response);
            response.setContentLength();
        }

    }

    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String protocol = req.getProtocol();
        String msg = lStrings.getString("http.method_post_not_supported");
        if (protocol.endsWith("1.1")) {
            resp.sendError(405, msg);
        } else {
            resp.sendError(400, msg);
        }

    }


	// 这个service方法就是判断请求方式,并对应相应的方法进行反应
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String method = req.getMethod();
        long lastModified;
        if (method.equals("GET")) {
            lastModified = this.getLastModified(req);
            if (lastModified == -1L) {
                this.doGet(req, resp);
            } else {
                long ifModifiedSince;
                try {
                    ifModifiedSince = req.getDateHeader("If-Modified-Since");
                } catch (IllegalArgumentException var9) {
                    ifModifiedSince = -1L;
                }

                if (ifModifiedSince < lastModified / 1000L * 1000L) {
                    this.maybeSetLastModified(resp, lastModified);
                    this.doGet(req, resp);
                } else {
                    resp.setStatus(304);
                }
            }
        } else if (method.equals("HEAD")) {
            lastModified = this.getLastModified(req);
            this.maybeSetLastModified(resp, lastModified);
            this.doHead(req, resp);
        } else if (method.equals("POST")) {
            this.doPost(req, resp);
        } else if (method.equals("PUT")) {
            this.doPut(req, resp);
        } else if (method.equals("DELETE")) {
            this.doDelete(req, resp);
        } else if (method.equals("OPTIONS")) {
            this.doOptions(req, resp);
        } else if (method.equals("TRACE")) {
            this.doTrace(req, resp);
        } else {
            String errMsg = lStrings.getString("http.method_not_implemented");
            Object[] errArgs = new Object[]{method};
            errMsg = MessageFormat.format(errMsg, errArgs);
            resp.sendError(501, errMsg);
        }

    }

    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        HttpServletRequest request;
        HttpServletResponse response;
        try {
            request = (HttpServletRequest)req;
            response = (HttpServletResponse)res;
        } catch (ClassCastException var6) {
            throw new ServletException("non-HTTP request or response");
        }

        this.service(request, response);
    }
}

由于HttpServlet已经对所有方法进行了实现,我们在使用时通常只需直接覆盖重写doGet和doPost方法即可:

package cn.itcast.web.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;

/**
 * HttpServlet的简单使用
 */
@WebServlet("/demo3")
public class ServletDemo3 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doGet");

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doPost");
    }
}

关于HTTP协议,以及HTTPServlet的两个重要参数request和response将会在下一篇文章介绍,关于servlet的内容暂且告一段落。

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java Web开发教程: 入门与提高篇(JSP Servlet)PDF》是一本针对Java Web开发的教程,旨在帮助读者从入门到提高掌握JSP和Servlet的使用。 这本教程包括两个主要部分:JSP和Servlet。JSP(Java Server Pages)是一种动态网页开发技术,它允许开发人员在HTML网页上嵌入Java代码。Servlet是一种运行在服务器端的Java程序,用于处理客户端请求和生成响应。 在入门部分,教程首先介绍了Java Web开发的基础知识,包括HTML和CSS的基本语法、HTTP协议的工作原理等。然后,它详细介绍了JSP的语法和标签,包括如何在JSP页面中嵌入Java代码,如何使用JSTL(JSP标准标签库)等。同时,它还介绍了如何使用Eclipse等常用的开发工具来编写和调试JSP页面。 在提高部分,教程进一步深入讲解了Servlet的使用。它介绍了Servlet的生命周期、请求处理过程和Servlet API的常用类和方法。此外,教程还介绍了如何使用Cookie和Session来实现用户认证和数据共享,以及如何使用过滤器和监听器来实现请求过滤和监听事件。 该教程的特点是通俗易懂,结合实例和练习,帮助读者进行实践。此外,教程还提供了一些实际项目案例,帮助读者理解和应用所学知识。 总之,《Java Web开发教程: 入门与提高篇(JSP Servlet)PDF》是一本适合Java Web开发初学者和有一定基础的开发人员学习的教材,通过学习该教程,读者可以全面掌握JSP和Servlet的使用,为自己的Web开发之路做好铺垫。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值