Servlet02

6.GET和POST请求的分发处理

  • 开发Servlet,通常编写doGet,doPost方法。来对表单的get和post请求进行分发处理

例子

在web文件夹下面创建一个html页面,用于提交表单

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>注册</title>
</head>
<body>
<h1>用户注册</h1>
<!--注意:这里的helloServlet不是你的类名,是你在web.xml里面配置的<url-pattern>-->
<form action="http://localhost:8080/servlet_demo/helloServlet" method="get">
u:<input type="text" name="username"/><br/><br/>
<input type="submit" value="注册用户"/>
</form>
</body>
</html>

在src目录下面创建HelloServlet类,该类实现了Servlet接口,并重写init(),getServletConfig(),service(),getServletInfo(),destroy()这5个方法,并在该类中增加两个方法,用来处理get和post请求

/**
* 用于响应get请求
*/
public void doGet() {
System.out.println("doGet()方法被调用..");
} /**
* 用于响应post请求
*/
public void doPost() {
System.out.println("doPost()方法被调用..");
}

同时在HelloServlet的service方法中编写操作,用于接收get和post请求

@Override
public void service(ServletRequest servletRequest,
ServletResponse servletResponse)
throws ServletException, IOException {
//思考-->从servletRequest对象去获取请求方式->
//1.发现ServletRequest没有得到提交方式的方法
//2.就去看看ServletRequest的子接口有没有相关方法
//3.快捷键ctrl+alt+b=>可以看到接口的子接口和实现子类
//4.发现HttpServletRequest子类中有getMethod方法
//5.把ServletRequest转成HttpServletRequest引用
HttpServletRequest 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请求
}
}

然后重新发布redeploy

在浏览器中输入地址http://localhost:8080/servlet_demo/register.html,在表单中输入内容,点击按钮,发送请求

可以看到后台输出了调用哪个方法,说明HelloServlet成功获得了请求方式

7.通过继承HttpServlet来开发Servlet

在实际的开发中,我们很少去实现Servlet接口,因为该接口中有很多方法实际上很少会用到。

为了开发更加简便,Servlet的设计者提供了另一套更简洁的开发方式,就是通过继承HttpServlet来开发Servlet。

  • HttpServlet介绍

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

例子

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

思路:

  • 编写一个类去继承HttpServlet类
  • 根据业务需要重写doGet或doPost方法
  • 到web.xml中配置Servlet程序

编写一个类去继承HttpServlet类:

package com.li.servlet;

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 HiServlet extends HttpServlet {
//重写HttpServlet的doGet和doPost方法 /**
* 处理doGet请求
*
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("HiServlet doGet()....");
} /**
* 处理doPost请求
*
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("HiServlet doPost()....");
}
}

到web.xml中配置Servlet程序:

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

点击Tomcat,选择redeploy

在浏览器中输入http://localhost:8080/web应用名/hiServlet,后台显示如下:

说明HiServlet类重写HttpServlet的doGet方法被调用了

7.1怎么执行到doGet和doPost

如上图所示,HiServlet类(自己写的)继承了HttpServlet,HttpServlet继承了GenericServlet抽象类,而GenericServlet抽象类又实现了Servlet接口,Servlet接口里面有service方法。

当Tomcat调用HiServlet里面service方法的时候,发现HiServlet里没有该方法,就会根据类的查找关系,在HttpServlet里面去找service方法,找到了就去执行。


如上图所示,this实际的运行类型是HiServlet,因此在执行doGet方法的时候,实际上运行的是HiServlet中的doGet方法。

动态绑定:当调用对象方法的时候,该方法会和该对象的内存地址/运行类型绑定

8.IDEA开发Servlet程序

  • 说明

    手动开发Servlet需要程序员自己配置Servlet,比较麻烦,在工作中,直接使用IDEA开发Servlet会更加方便

例子

  1. 如下图:选中右键在src目录下创建的servlet文件夹,选择new->选择Servlet

    idea文件右键创建New没有Create New Servlet的解决办法

  2. 在弹出的窗口中按照需求进行选择,然后点击OK

    如果使用xml的方式进行开发,就不用选择Create Java EE 6+ annotated class

    否则就是使用注解的方式。

  3. 点击ok后,如果使用的是xml文件开发,就会自动配置<servlet>标签

    注意:自动配置的只有<servlet>标签,<servlet-mapping>标签需要自己写

  4. 在自动生成的OkServlet.java中编写自己的业务处理代码

    package com.li.servlet;
    
    import javax.servlet.*;
    import javax.servlet.http.*;
    import java.io.IOException; public class OkServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //可以写自己的业务处理代码
    System.out.println("OkServlet doGet()");
    } @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //可以写自己的业务处理代码
    System.out.println("OkServlet doPost()");
    }
    }
  5. 点击redeploy,重新发布。然后在浏览器中输入http://localhost:8080/servlet_demo/okServlet发送请求。

    后台输出如下:

9.Servlet注意事项和细节

  1. Servlet是一个供其他 Java程序(Servlet引擎)调用的Java类,不能独立运行

  2. 针对浏览器的多次Servlet请求,通常情况下,服务器只会创建一个Servlet实例对象,也就是说Servlet实例对象一旦创建,它就会驻留在内存中,为后续的其他请求服务,直至web容器退出,或者redeploy该web应用,Servlet实例对象才会销毁

  3. 在Servlet的整个生命周期内,init方法只被调用一次。而对每次请求都导致Servlet引擎调用一次Servlet的service()方法

  4. 对于每次请求访问,Servlet引擎都会创建一个新的HttpServletRequest请求对象和一个新的HttpServletResponse响应对象,然后将这两个对象作为参数传递给它调用的Servlet的service()方法,service()方法再根据请求方式分别调用doXxx()方法

    详见7.1

  5. 如果在<servlet>元素中配置了一个<load-on-startup>元素,那么WEB应用程序在启动时,就会装载并创建Servlet的实例对象,以及调用Servlet实例对象的init()方法

    <load-on-startup>的应用场景:比如服务器定时发送邮件的服务:自动启动-->完成任务

10.Servlet注解方式

之前演示的Servlet例子都是使用web.xml文件来配置的,现在来看看使用注解方式配置Servlet

10.1快速入门

具体步骤:

  1. 编写类OkServlet去继承HttpServlet
  2. 注解方式配置OkServlet,一个Servlet支持配置多个urlPattern(即通过不同的urlPattern可以访问同一个Servlet)

package com.li.servlet.annotation;

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; /**
* 注解的方式来配置:
*
* 1.@WebServlet 是一个注解
* 2.@WebServlet 源码:
*@Target({ElementType.TYPE}) =>用于指定 被修饰的Annotation可以用于修饰 哪些程序元素
* @Retention(RetentionPolicy.RUNTIME) =>用于指定该Annotation可以保留多长时间
* @Documented =>在Javadoc工具生成文档时,可以看到该注解。
* public @interface WebServlet {
* String name() default "";
*
* String[] value() default {};
*
* String[] urlPatterns() default {};
*
* int loadOnStartup() default -1;
* }
* 3. urlPatterns对应 web.xml的 <url-pattern></url-pattern>
* 4. {"/ok1","/ok2"} 表示可以给OKServlet配置多个url-pattern
* 5. 相当于这个@WebServlet(urlPatterns = {"/ok1","/ok2"}) 代替了web.xml的配置
* 底层使用了反射+注解+IO+集合 来完成一个支撑
* 6. 浏览器访问OkServlet时,可以输入 http://localhost:8080/web应用名/ok1
* 或者 http://localhost:8080/web应用名/ok2
* 7.
*/
@WebServlet(urlPatterns = {"/ok1", "/ok2"})
public class OkServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("注解方式 OkServlet doGet()");
} @Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("注解方式 OkServlet doPost()");
}
}

在浏览器中输入:http://localhost:8080/servlet_demo/ok1或者http://localhost:8080/servlet_demo/ok2


后台的显示如下:说明两次都能正常地访问OkServlet

10.2注解方式是如何完成Servlet配置的?

一个疑问:web.xml文件是通过dom4j来获取数据,然后进行反射。那注解为什么也能进行Servlet的调用或者是初始化等操作的呢?它的原理是什么?

根据上图:Tomcat得到http请求的工作如下

详见Servlet01--浏览器调用Servlet流程分析

  1. 如果是注解的方式,就对包进行扫描,如果发现某个类是用@WebServlet注解过的,就说明该类是一个Servlet,就会读取@WebServlet的urlPatterns的值
  2. 看看浏览器请求的资源 /XxxServlet 有没有在包配置过
  3. 如果找到对应的urlPatterns,就会得到对应的servletname
  4. Tomcat维护了一个大的HashMap<id,Servlet>,查询该HashMap,看看有没有这个Servlet实例
  5. 如果没有查询到该servlet-name对应的id,即没有这个Servlet实例时
  6. 就去得到servlet类的全路径(之前扫描包的时候就可以获取全路径)
  7. 使用反射技术,将servlet实例化(同时调用init方法),并将该实例放入到Tomcat维护的HashMap<id,Servlet>中

注解方式开发Servlet和web.xml配置Servlet,本质上机制是一样的

不要同时配置注解和web.xml。即不要配置了该Servlet的web.xml,又在该Servlet类上添加注解


下面模拟一下Tomcat是如何通过@WebServlet(urlPatterns = {"/ok1", "/ok2"})来装载一个Servlet的:

反射+注解+IO+集合

package com.li.servlet.annotation;

import javax.servlet.annotation.WebServlet;
import java.util.HashMap; /**
* 模拟一下Tomcat是如何通过@WebServlet(urlPatterns = {"/ok1", "/ok2"})
* 来装载一个Servlet的
*/
public class TestAnnotationServlet {
private static final HashMap<String, Object> hm = new HashMap<>(); public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
//1.首先要得到扫描的包 路径(IO),进而得到类的全路径(如何扫描包的过程暂时略过)
String classAllPath = "com.li.servlet.annotation.OkServlet";
//2.得到OkServlet的class对象
Class<?> aclass = Class.forName(classAllPath);
//3.通过class对象,得到annotation
WebServlet annotation = aclass.getAnnotation(WebServlet.class);
//4.获取annotation的属性
System.out.println(annotation);
String[] strings = annotation.urlPatterns();
for (String url : strings) {
System.out.println("url=" + url);
}
//如果匹配url,如果是第一次请求tomcat,tomcat就会创建一个OkServlet实例,放入HashMap中
Object instance = aclass.newInstance();
System.out.println(instance);//instance就是一个OkServlet的实例对象
//简单地模拟
hm.put("OkServlet", instance);
System.out.println(hm); //如果是第二次及以后请求tomcat,就会直接去HashMap中去查找OkServlet的实例对象
}
}

10.3@WebServlet注解参数说明

我们可以根据@interface WebServlet 源码知道可以配置哪些信息

http://c.biancheng.net/servlet2/webservlet.html

10.4Servlet urlPattern配置

day12-Servlet02的更多相关文章

  1. python_way day12 sqlalchemy,原生mysql命令

    python_way day12  sqlalchemy,mysql原生命令 1.sqlalchemy 2.mysql 原生命令 一,sqlalchemy SQLAlchemy本身无法操作数据库,其必 ...

  2. python_way day12 RabbitMQ ,pymysql

    python_way day12 1.RabbitMQ 2.pymysql RabbitMQ 1.基本用法 """ producer """ ...

  3. Spark Streaming揭秘 Day12 数据安全容错(Executor篇)

    Spark Streaming揭秘 Day12 数据安全容错(Executor篇) 今天,让我们研究下SparkStreaming在Executor端的数据安全及容错机制. 在SparkStreami ...

  4. Python之路,Day12 - 那就做个堡垒机吧

    Python之路,Day12 - 那就做个堡垒机吧   本节内容 项目实战:运维堡垒机开发 前景介绍 到目前为止,很多公司对堡垒机依然不太感冒,其实是没有充分认识到堡垒机在IT管理中的重要作用的,很多 ...

  5. Day12 - 堡垒机开发

    Python之路,Day12 - 那就做个堡垒机吧   本节内容 项目实战:运维堡垒机开发 前景介绍 到目前为止,很多公司对堡垒机依然不太感冒,其实是没有充分认识到堡垒机在IT管理中的重要作用的,很多 ...

  6. ##DAY12 UITableViewCell自定义

    ##DAY12 UITableViewCell自定义 #pragma mark -------自定义视图步骤--------- 自定义视图步骤: 1)在自定义cell类中,将所有cell要显示的子视图 ...

  7. Python之路 Day12

    day12主要内容:html基础.CSS基础 HTML HTML概述: HTML是英文Hyper Text Mark-up Language(超文本标记语言)的缩写,他是一种制作万维网页面标准语言(标 ...

  8. 【JAVA零基础入门系列】Day12 Java类的简单应用

    俗话说的好,实践出真知,所以除了理论知识掌握扎实以外,更重要的是要多加操练,这样才能掌握核心科技. 今天我们就用刚学会的类来实践一下,目标便是完成上一篇中的剁手任务. 我们的商品类已经准备好了,代码重 ...

  9. Alpha冲刺Day12

    Alpha冲刺Day12 一:站立式会议 今日安排: 由黄腾飞和张梨贤继续完成政府人员模块下的风险管控子模块下的分级统计展示 由林静继续完成企业注册模块 由周静平完成登录页面模块 二:实际项目进展 人 ...

  10. day12 EL 表达式和国际化开发

    day12 EL 表达式和国际化开发 1. EL(Expression Language) 表达式简介 1.1 执行运算 1.2 获取web开发常用对象(el 中定义了11个隐式对象) 1.3 使用 ...

随机推荐

  1. DLL Proxy Loading Bypass AV

    DLL Proxy Loading Bypass AV 前言 感谢国外大佬开源的免杀思路,本文就是基于该文章的一次实践. https://redteaming.co.uk/2020/07/12/dll ...

  2. 【JDBC】学习路径1-JDBC背景知识

    学习完本系列JDBC课程后,你就可以愉快使用Java操作我们的MySQL数据库了. 各种数据分析都不在话下了. 第一章:废话 JDBC编程,就是写Java的时候,调用了数据库. Java Databa ...

  3. 「题解报告」P3354

    P3354 题解 题目传送门 一道很恶心的树形dp 但是我喜欢 题目大意: 一片海旁边有一条树状的河,入海口有一个大伐木场,每条河的分叉处都有村庄.建了伐木场的村庄可以直接处理木料,否则要往下游的伐木 ...

  4. pod资源的健康检查-liveness探针的httpGet使用

    使用liveness探针httpget方式检测pod健康,httpGet方式使用的最多 [root@k8s-master1 tanzhen]# cat nginx_pod_httpGet.yaml a ...

  5. 从原理剖析带你理解Stream

    摘要:Stream是jdk1.8给我们提供的新特性 本文分享自华为云社区<深入理解Stream之原理剖析>,作者: 李哥技术 . Stream是jdk1.8给我们提供的新特性,主要就是允许 ...

  6. KingbaseES V8R6集群外部备份案例

    案例说明: 本案例采用sys_backup.sh执行物理备份,备份使用如下逻辑架构:集群采用CentOS 7系统,repo采用kylin V10 Server. 一主一备+外部备份 此场景为主备双机常 ...

  7. Linux做bond4

    一.编辑bond网络配置 vim /etc/sysconfig/network-scripts/ifcfg-bond4 DEVICE=bond4 NAME=bond4 TYPE=Bond ONBOOT ...

  8. 【ASP.NET Core】自定义Session的存储方式

    在开始今天的表演之前,老周先跟大伙伴们说一句:"中秋节快乐". 今天咱们来聊一下如何自己动手,实现会话(Session)的存储方式.默认是存放在分布式内存中.由于HTTP消息是无状 ...

  9. 图-kruskal算法,prim算法

    要求无向图 最小生成树: 连通性,累加和最小 并查集 结构 K算法 从最小的边开始,加上有没有形成环,没有就加,加上有环就不要 难点:如何判断加上一条边,有没有形成环. P算法 从点的角度开始

  10. 使用 Elastic Agents 把定制的日志摄入到 Elasticsearch 中

    转载自:https://mp.weixin.qq.com/s/QQxwYh1uLCkKn1LK72ojJA 在以前的系统中,我们可以使用如下的几种方式来采集日志: 1.我们可以直接使用 Beats 把 ...