JavaWeb系列六: 动态WEB开发核心(Servlet) 上

2024-06-24 11:20

本文主要是介绍JavaWeb系列六: 动态WEB开发核心(Servlet) 上,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

韩老师学生

  • 官网文档
  • 为什么会出现Servlet
  • 什么是Servlet
  • Servlet在JavaWeb项目位置
  • Servlet基本使用
    • Servlet开发方式说明
    • 快速入门- 手动开发 servlet
    • 浏览器请求Servlet UML分析
    • Servlet生命周期
    • GET和POST请求分发处理
    • 通过继承HttpServlet开发Servlet
    • IDEA配置Servlet
    • Servlet注意事项和细节
  • Servlet注解方式
    • 快速入门
      • 注解详解
      • initParams
    • Servlet urlPattern 配置
      • 精准匹配
      • 目录匹配
      • 扩展名匹配
      • 任意匹配
      • 注解注意事项

在这里插入图片描述

官网文档

官网文档: https://tomcat.apache.org/tomcat-8.0-doc/servletapi/index.html

离线文档
JAVA_EE_api_中英文对照版

●Servlet和Tomcat的关系: 一句话, Tomcat支持Servlet
在这里插入图片描述

为什么会出现Servlet

1.提出需求: 请用你现有的html css javascript, 开发网站, 比如可以让用户留言/购物/支付, 你能搞定吗?

2.引入我们动态网页(能和用户交互)技术 ⇒ Servlet

3.对Java Web技术体系的流程图改造说明(细化).[整体的概念]
在这里插入图片描述

什么是Servlet

Servlet在开发动态WEB工程中, 得到广泛的应用. 掌握好Servlet非常重要, Servlet(基石)是SpringMVC的基础

Servlet(java 服务器小程序), 它的特点:
1.它是由服务器端调用和执行的(一句话: 是Tomcat解析和执行)
2.它使用java语言编写的, 本质就是Java
3.它是按照Servlet规范开发的(除了tomcat->Servlet weblogic->Servlet)
4.功能强大, 可以完成几乎所有的网站功能(在以前, 老程序员, 使用Servlet开发网站) 技术栈要求高, 内卷(硬起来)

Servlet在JavaWeb项目位置

在这里插入图片描述

Servlet基本使用

Servlet开发方式说明

1.servlet3.0前使用web.xml, servlet3.0版本以后(包括3.0)支持注解, 同时支持web.xml配置

2.如何查看servlet版本[如图]
在这里插入图片描述

3.讲解SpringBoot时, 我们用注解方式, 从ssm, springboot后面全部使用注解

4.这里专门讲servlet, 为让大家更清晰地知道servlet使用原理, 我们用配置方式(说明, 原生的Servlet在项目中使用很少)

5.不管使用哪种方式, 本质都一样

快速入门- 手动开发 servlet

需求说明
1.开发一个HelloServlet
2.当浏览器 访问 http://localhost:8080/web应用名/helloServlet时, 后台输出 hi HelloServlet

●具体步骤
1.编写类HelloServlet去实现Servlet接口
2.实现service方法, 处理请求, 并响应数据
3.在web.xml中去配置servlet程序的访问地址

1.创建servlet Java Web工程, 并配置好Tomcat. IDEA开发部署JavaWeb工程

2.添加servlet-api.jar(在tomcat/lib下) 到工程, 因为servlet.jar 不是jdk自带的, 要引入

3.在src目录 com.zzw.servlet包下新建HelloServlet.java, 并实现Servlet接口

package com.zzw.servlet;import javax.servlet.*;
import java.io.IOException;/*** @author 赵志伟* @version 1.0* 1.开发一个Servlet需要实现Servlet接口* 2.实现Servlet接口的五个方法*/
@SuppressWarnings({"all"})
public class HelloServlet implements Servlet {private int count;/*** 1.初始化 servlet* 2.当创建HelloServlet实例时, 会调用init方法* 3.该方法只会被调用一次** @param servletConfig* @throws ServletException*/@Overridepublic void init(ServletConfig servletConfig) throws ServletException {System.out.println("init() 被调用");}/*** 返回ServletConfig 也就是返回Servlet的配置** @return*/@Overridepublic ServletConfig getServletConfig() {return null;}/*** 1.service方法处理浏览器的请求(包括get和post)* 2.当浏览器每次请求Servlet时,就会调用一次service方法* 3.当tomcat调用该方法时,会把http请求的数据封装成实现了ServletRequest接口的request对象* 4.通过servletRequest对象,可以得到用户提交的数据* 5.servletResponse对象可以用于返回数据给tomcat->浏览器** @param servletRequest* @param servletResponse* @throws ServletException* @throws IOException*/@Overridepublic void service(ServletRequest servletRequest,ServletResponse servletResponse) throws ServletException, IOException {//如果count的值在不停地累积, 说明HelloServlet是单例的System.out.println("hi HelloServlet~, count=" + count++);}/*** 返回servlet的信息,使用较少* @return*/@Overridepublic String getServletInfo() {return null;}/*** 1.该方法是在servlet被销毁时,调用* 2.只会调用一次*/@Overridepublic void destroy() {}
}

web.xml注释时发现前面有空格
在这里插入图片描述
解决方案 Settings->Editor->Code Style->XML, 取消勾选
在这里插入图片描述
IDEA配置快捷键: settings->Keymap
重启(Alt+R)选择重新部署,速度快, 不要选Restart server, 这样会把JDK都重启, 速度很慢
在这里插入图片描述

  1. 在web.xml文件中配置由Tomat访问HelloServlet的路径
<?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"><!--小技巧:web.xml主要用来配置该web应用使用到的Servlet--><!--1.servlet-name: 给Servlet取名(由程序员决定), 这个名字是不能重复取的2.servlet-class:该Servlet的类的全路径, Tomcat在反射生成Servlet时需要使用3.url-pattern: 这个就是访问该Servlet的url地址这时我们可以这样访问:http://localhost:8080/servlet/helloServlet4.url-pattern 访问地址是由程序员决定的5.load-on-startup 表示在tomcat 启动时, 会自动地加载servlet实例小技巧: alt+R -> Redeploy选择重新部署, 速度更快--><servlet><servlet-name>HelloServlet</servlet-name><servlet-class>com.zzw.servlet.HelloServlet</servlet-class><load-on-startup>1</load-on-startup> </servlet><servlet-mapping><servlet-name>HelloServlet</servlet-name><url-pattern>/helloServlet</url-pattern></servlet-mapping>
</web-app>

浏览器请求Servlet UML分析

在这里插入图片描述

Servlet生命周期

●主要有三个方法
1.init方法
2.service方法
3.destroy方法

在这里插入图片描述

●初始化阶段

Servlet容器(比如:Tomcat) 加载Servlet, 加载完成后, Servlet容器会创建一个Servlet实例并调用init方法(创建的实例放入HashMap), init方法只会调用一次, Servlet容器在下面的几种情况下会装载Servlet:

在这里插入图片描述
1.Servlet容器(比如: Tomcat)启动时自动装载某些servlet, 实现这个需要在web.xml文件中添加
<load-on-startup>1</load-on-startup> 1表示装载的顺序
2.在Servlet容器启动后, 浏览器首次向Servlet发送请求
3.Servlet重新装载时(比如tomcat 进行redeployredeploy会销毁所有的Servlet实例】), 浏览器再向Servlet发送请求的第1

●处理浏览器请求阶段(service方法)
1.每收到一个http请求, 服务器就会产生一个新的线程处理[线程]
2. 创建一个用于封装HTTP请求消息的ServletRequest对象和一个代表HTTP响应消息的ServletResponse对象
3. 然后调用Servletservice()方法并将请求和响应对象, 作为参数传递进去


●终止阶段(destroy方法)(体现Servlet完整的生命周期)
web应用被终止, 或者Servlet容器终止运行, 或者Servlet类重新装载时, 会调用destroy()方法, 比如重启tomcat, 或者 redeploy web应用

GET和POST请求分发处理

●开发Servlet, 通常编写doGet, doPost方法, 来对表单的getpost请求进行分发处理

●代码演示
1.web路径下新建register.html

<body>
<h1>注册用户</h1>
<form action="http://localhost:8080/servlet3/helloServlet" method="post">u: <input type="text" name="username"/><br/><input type="submit" value="注册用户"/>
</form>
</body>

2.修改HelloServletservice方法完成分发请求

/*** 1.service方法处理浏览器的请求(包括get和post)* 2.当浏览器每次请求Servlet时, 就会调用一次service方法* 3.当tomcat调用该方法时, 会把http请求的数据封装成实现了ServletRequest接口的request对象* 4.通过servletRequest对象, 可以得到用户提交的数据* 5.servletResponse对象可以用于返回数据给tomcat->浏览器** @param servletRequest* @param servletResponse* @throws ServletException* @throws IOException*/
@Override
public void service(ServletRequest servletRequest,ServletResponse servletResponse) throws ServletException, IOException {//如果count的值在不停地累积, 说明HelloServlet是单例的System.out.println("hi HelloServlet ~~count="+ ++count);//Tomcat每处理一次http请求, 就生成一个新的线程System.out.println("当前线程id=" + Thread.currentThread().getId());//思考->从servletRequest对象来获取请求方式//1.ServletRequest 没有得到提交方式的方法//2.ServletRequest 看看ServletRequest子接口有没有相关方法//3.老师小技巧: ctrl+alt+b 可以看到接口的子接口和实现子类//4.把servletRequest转成 HttpServletRequest引用//5.仍然是Java基础的OOPHttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;String method = httpServletRequest.getMethod();System.out.println("method=" + method);//method=GET 大写的if ("GET".equals(method)) {doGet();//用doGet() 处理GET请求} else if ("POST".equals(method)) {doPost();//用doPost() 处理POST请求}
}/*** 用于响应get请求*/
public void doGet() {System.out.println("HelloServlet doGet()...");
}/*** 用于响应post请求*/
public void doPost() {System.out.println("HelloServlet doPost()...");
}

3.测试…

通过继承HttpServlet开发Servlet

HttpServlet介绍
在实际项目中, 都是使用继承 HttpServlet 类来开发 Servlet 程序, 更加方便

HttpServlet类图如下
在这里插入图片描述

Http介绍
1.通过继承HttpServlet开发一个HiServlet
2.当浏览器 访问 http://localhost:8080/web应用名/hiServlet时,后台输出hi HiServlet

●具体的开发步骤
1.编写一个类去继承 HttpServlet
2.根据业务需要重写doGetdoPost 方法
3.到 web.xml 中配置 Servlet程序

1.com.zzw.servlet包下新建HiServlet

public class HiServlet extends HttpServlet {//重写HttpServlet的doGet 和 doPost//alt + insert@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("HiServlet doGet()...");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("HiServlet doPost()...");}
}

2.配置web.xml

<!--配置HiServlet--><servlet><servlet-name>HiServlet</servlet-name><servlet-class>com.zzw.servlet.HiServlet</servlet-class></servlet><servlet-mapping><servlet-name>HiServlet</servlet-name><url-pattern>/hiServlet</url-pattern></servlet-mapping>

IDEA配置Servlet

在WEB-INF目录下的lib文件夹下导入servlet-api.jar包并且Add As Library后右键才有新建Servlet的选项

在这里插入图片描述
在这里插入图片描述
会自动生成Servlet类和web.xml配置

public class OkServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//可以写自己的业务处理代码}@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//可以写自己的业务处理代码}

web.xml自动生成以下半截代码, 这里需要手动配置url-pattern
在这里插入图片描述

Servlet注意事项和细节

  1. Servlet是一个供其它Java程序(Servlet)引擎调用的Java类, 不能独立运行
  2. 针对浏览器的多次Servlet请求, 通常情况下, 服务器只会创建一个Servlet实例对象, 也就是说Servlet实例对象一旦创建, 它就会驻留在内存中,存在于Tomcat维护的HashMap中, 为后续的其他请求而服务, 直至web容器退出/或者redeploy该web应用, servlet实例对象才会销毁, 从HashMap中移除
  3. 在Servlet的整个生命周期中,init方法只被调用一次, 而对每次请求都导致Servlet引擎调用一次servlet的service方法
  4. 对于每次访问请求, Servlet引擎都会创建一个新的HttpServletRequest请求对象和一个新的HttpServletResponse响应对象, 然后将这两个对象作为参数传递给它调用的Servlet的service()方法, service方法再根据请求方式分别调用doGet()方法和doPost()方法
  5. 如果在<servlet>元素中配置了一个<load-on-startup>元素, 那么web应用程序在启动时, 就会装载并创建Servlet的实例对象, 以及调用Servlet实例对象的init()方法

Servlet注解方式

快速入门

省去了在web.xml配置的麻烦

方法外不能使用.var

/*** 显示方法之间的分割线 Editor->General->Appearance->Show method separators* 1.@WebServlet是一个注解* 2.@WebServlet的源码* 3.urlPatterns 对应web.xml中的 <url-Pattern></url-Pattern>*   {"/ok1", "/ok2"} 可以给OkServlet配置多个 urlPattern*   相当于这个@WebServlet(urlPatterns={"/ok1", "/ok2"}) 代替了web.xml的配置* 4.浏览器可以这样访问OkServlet: http://localhost:8080/servlet/ok1 或者 http://localhost:8080/servlet/ok2*/
@WebServlet(urlPatterns = {"/ok1", "/ok2"})
public class OkServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("annotation doGet method");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("annotation doPost method");}
}

@WebServlet注解源码

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented => 在javadoc工具生成记录
public @interface WebServlet {String name() default "";String[] value() default {};String[] urlPatterns() default {};int loadOnStartup() default -1;WebInitParam[] initParams() default {};boolean asyncSupported() default false;String smallIcon() default "";String largeIcon() default "";String description() default "";String displayName() default "";
}

注解详解

在这里插入图片描述

说明: 注解是对包进行扫描, 如果发现某个类是用@WebServlet, 就说明该类是Servlet, 然后读取urlPatterns, 看看请求的资源和urlPatterns的参数是否一致

●模拟代码

/*** @author 赵志伟* @version 1.0* 模拟Tomcat是如何通过注解@WebServlet(urlPatterns={"/ok1", "/ok2"})来装载一个Servlet的*/
@SuppressWarnings({"all"})
public class TestAnnotationServlet {private static final HashMap<String, HttpServlet> hm = new HashMap<>();public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {//1.首先要得到扫描的包 路径 IO, 进而得到类的全路径String path = "com.zzw.servlet.annotation.OkServlet";//2.得到OkServlet的Class对象Class<?> aClass = Class.forName(path);//3.根据class对象得到对应的注解WebServlet annotation = aClass.getAnnotation(WebServlet.class);String[] urlPatterns = annotation.urlPatterns();for (String urlPattern : urlPatterns) {System.out.println("urlPattern=" + urlPattern);}//如果匹配url, 如果是第一次, tomcat就会创建一个OkServlet实例, 放入到HashMap中Object instance = aClass.newInstance();System.out.println("instance=" + instance);//OkServlet实例hm.put("OkServlet", (HttpServlet) instance);System.out.println(hm);}
}

initParams

@WebServlet(urlPatterns = {"/ok1", "/ok2"}, initParams = {@WebInitParam(name = "zzw", value = "123"), @WebInitParam(name = "xx", value = "yy")})
public class OkServlet extends HttpServlet {}

等同于

<servlet><servlet-name>OkServlet</servlet-name><servlet-class>com.zzw.servlet.OkServlet</servlet-class><init-param><param-name>zzw</param-name><param-value>123</param-value></init-param><init-param><param-name>xx</param-name><param-value>yy</param-value></init-param></servlet>

Servlet urlPattern 配置

精准匹配

@WebServlet(urlPatterns = {"/ok1/aa/bb", "/ok2"}

目录匹配

@WebServlet(urlPatterns = {"/ok1/*", "/ok2"})
http://localhost:8888/servlet/ok1
http://localhost:8888/servlet/ok1/aa
http://localhost:8888/servlet/ok1/aa/bb/cc

扩展名匹配

@WebServlet(urlPatterns = {"*.action", "/ok2"}
http://localhost:8888/servlet/zzw.action
http://localhost:8888/servlet/zzw.521.action

3.2不能带斜杠

@WebServlet(urlPatterns = {"/*.action", "/ok2"},这样是错误的

任意匹配

@WebServlet(urlPatterns = {"/", "/ok2"}
或者
@WebServlet(urlPatterns = {"/*", "/ok2"}
http://localhost:8888/servlet/aa/bb/cc
http://localhost:8888/servlet/zzw.521.action

注解注意事项

shortcuts: ctrl+alt+⬅ 回到上次访问的窗口

1.当Servlet配置了"/", 会覆盖掉tomcat的DefaultServlet, 当其它的的url-pattern都匹配不上时, 就会走这个默认的Servlet, 这样可以拦截到其它请求中的静态资源

这个默认的Servlet是处理静态资源的, 一旦拦截, 静态资源则不能处理

 <!-- The default servlet for all web applications, that serves static     --><!-- resources.  It processes all requests that are not mapped to other   --><!-- servlets with servlet mappings (defined either here or in your own   --><!-- web.xml file). --><servlet><servlet-name>default</servlet-name><servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class><init-param><param-name>debug</param-name><param-value>0</param-value></init-param><init-param><param-name>listings</param-name><param-value>false</param-value></init-param><load-on-startup>1</load-on-startup></servlet>

2.当Servlet配置了"/*", 表示可以匹配任意访问路径

3.建议不要使用/ 和 /*, 尽量使用精准匹配

4.优先级遵守: 精确路径 > 目录路径 > 扩展名路径 > /* > / > DefaultServlet(访问静态资源)

访问:http://localhost:8888/servlet/ok1/aa
@WebServlet(urlPatterns = {"/ok1/aa"}//优先
@WebServlet(urlPatterns = {"/ok1/*"}

这篇关于JavaWeb系列六: 动态WEB开发核心(Servlet) 上的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1090009

相关文章

Java五子棋之坐标校正

上篇针对了Java项目中的解构思维,在这篇内容中我们不妨从整体项目中拆解拿出一个非常重要的五子棋逻辑实现:坐标校正,我们如何使漫无目的鼠标点击变得有序化和可控化呢? 目录 一、从鼠标监听到获取坐标 1.MouseListener和MouseAdapter 2.mousePressed方法 二、坐标校正的具体实现方法 1.关于fillOval方法 2.坐标获取 3.坐标转换 4.坐

Spring Cloud:构建分布式系统的利器

引言 在当今的云计算和微服务架构时代,构建高效、可靠的分布式系统成为软件开发的重要任务。Spring Cloud 提供了一套完整的解决方案,帮助开发者快速构建分布式系统中的一些常见模式(例如配置管理、服务发现、断路器等)。本文将探讨 Spring Cloud 的定义、核心组件、应用场景以及未来的发展趋势。 什么是 Spring Cloud Spring Cloud 是一个基于 Spring

Javascript高级程序设计(第四版)--学习记录之变量、内存

原始值与引用值 原始值:简单的数据即基础数据类型,按值访问。 引用值:由多个值构成的对象即复杂数据类型,按引用访问。 动态属性 对于引用值而言,可以随时添加、修改和删除其属性和方法。 let person = new Object();person.name = 'Jason';person.age = 42;console.log(person.name,person.age);//'J

java8的新特性之一(Java Lambda表达式)

1:Java8的新特性 Lambda 表达式: 允许以更简洁的方式表示匿名函数(或称为闭包)。可以将Lambda表达式作为参数传递给方法或赋值给函数式接口类型的变量。 Stream API: 提供了一种处理集合数据的流式处理方式,支持函数式编程风格。 允许以声明性方式处理数据集合(如List、Set等)。提供了一系列操作,如map、filter、reduce等,以支持复杂的查询和转

Java面试八股之怎么通过Java程序判断JVM是32位还是64位

怎么通过Java程序判断JVM是32位还是64位 可以通过Java程序内部检查系统属性来判断当前运行的JVM是32位还是64位。以下是一个简单的方法: public class JvmBitCheck {public static void main(String[] args) {String arch = System.getProperty("os.arch");String dataM

详细分析Springmvc中的@ModelAttribute基本知识(附Demo)

目录 前言1. 注解用法1.1 方法参数1.2 方法1.3 类 2. 注解场景2.1 表单参数2.2 AJAX请求2.3 文件上传 3. 实战4. 总结 前言 将请求参数绑定到模型对象上,或者在请求处理之前添加模型属性 可以在方法参数、方法或者类上使用 一般适用这几种场景: 表单处理:通过 @ModelAttribute 将表单数据绑定到模型对象上预处理逻辑:在请求处理之前

eclipse运行springboot项目,找不到主类

解决办法尝试了很多种,下载sts压缩包行不通。最后解决办法如图: help--->Eclipse Marketplace--->Popular--->找到Spring Tools 3---->Installed。

JAVA读取MongoDB中的二进制图片并显示在页面上

1:Jsp页面: <td><img src="${ctx}/mongoImg/show"></td> 2:xml配置: <?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001

Java面试题:通过实例说明内连接、左外连接和右外连接的区别

在 SQL 中,连接(JOIN)用于在多个表之间组合行。最常用的连接类型是内连接(INNER JOIN)、左外连接(LEFT OUTER JOIN)和右外连接(RIGHT OUTER JOIN)。它们的主要区别在于它们如何处理表之间的匹配和不匹配行。下面是每种连接的详细说明和示例。 表示例 假设有两个表:Customers 和 Orders。 Customers CustomerIDCus

22.手绘Spring DI运行时序图

1.依赖注入发生的时间 当Spring loC容器完成了 Bean定义资源的定位、载入和解析注册以后,loC容器中已经管理类Bean 定义的相关数据,但是此时loC容器还没有对所管理的Bean进行依赖注入,依赖注入在以下两种情况 发生: 、用户第一次调用getBean()方法时,loC容器触发依赖注入。 、当用户在配置文件中将<bean>元素配置了 lazy-init二false属性,即让