Servlet规范了JavaWeb项目的结构
Servlet的规范约束了服务器如何来实现Servlet规范,如何解析JavaWeb项目的结构。

Java就是通过接口来约束

Servlet规范的jar就在tomcat的lib目录下面,文件名:servlet-api.jar,其中还有webSocket-api.jar
创建servlet先只用servlet-api.jar即可。

一、开始使用Servlet规范开发JavaWeb项目:

然后开始配置:

注意:<url-pattern>里面的资源名称必须要用"/"开头

源码:

 <?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_3_1.xsd"
version="3.1"
metadata-complete="true"> <servlet>
<!-- 配置Servlet类的全限定名 -->
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.demo.testServlet.HelloServlet</servlet-class>
</servlet> <!-- Servlet映射,用来访问资源名称,通过helloHeYang就可以访问资源 -->
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/helloHeYang</url-pattern>
</servlet-mapping> </web-app>

另外:

Servlet中的方法含义:

public void init(ServletConfig config):Servlet的初始化操作方法

public void service(ServletRequest req, ServletResponse res):处理请求和响应的方法

public void destroy():资源回收

public ServletConfig getServletConfig():获取Servlet的配置信息

public String getServletInfo():获取Servlet的相关的信息(作者/版本)

     @Override
public void init(ServletConfig config) throws ServletException {
// TODO Auto-generated method stub
System.out.println("init初始化方法");
} @Override
public ServletConfig getServletConfig() {
// TODO Auto-generated method stub
System.out.println("getServletConfig获取Servlet配置信息");
return null;
} @Override
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException {
// TODO Auto-generated method stub
System.out.println("service(ServletRequest req, ServletResponse res)处理请求和响应");
} @Override
public String getServletInfo() {
// TODO Auto-generated method stub
System.out.println("getServletInfo():获取Servlet的相关的信息(作者/版本)");
return null;
} @Override
public void destroy() {
// TODO Auto-generated method stub
System.out.println("destroy():资源回收");
}

启动tomcat服务器之后,然后打开浏览器:

---------------------------------------------------------------------------------------------------------------

Servlet的生命周期方法:

public void init(ServletConfig config):Servlet的初始化操作方法(在被第一次访问的时候执行)

public void service(ServletRequest req, ServletResponse res):处理请求和响应的方法(每次访问都会执行)

public void destroy():资源回收(在服务器正常关闭的时候执行)

----------------------------------------------------------------------------------------------

Servlet的生命周期方法的执行顺序:

Servlet是单例的(在其整个应用中只有一个对象)

执行顺序:

1.调用公共无参数的构造器创建对象(只会在第一次访问的时候执行)

2.执行init方法(只会在第一次访问的时候执行)

3.执行服务方法(每次访问都会执行)

4.执行destroy方法(在服务器被正常关闭的时候执行),不要将关闭资源的操作放到该方法中

注意:在Servlet类中必须保证有一个公共的无参数的构造器(使用反射创建对象,类的Class实例.newInstance())

   类中的默认构造器的访问权限和类的访问权限一致

二、Servlet的请求流程:

1.通过浏览器发送请求

http://localhost:8080/demo/helloHeYang

2.Tomcat解析请求路径

协议:http

主机地址:localhost

端口:8080,确定访问的是该主机上的哪一个程序

上下文的路径:server.xml文件中配置的信息,/demo

资源名称:访问的资源是什么,/helloHeYang,在项目下的web.xml文件中配置的<url-pattern>的文本

3.根据上下文的路径去找到server.xml文件中的<Context>节点,确定项目的根路径

如果没有找到,返回404错误

反之,执行第4步

4.根据资源名称去项目下的WEB-INF下的web.xml文件中找到<url-pattern>文本内容为/hello的节点

可以确定找到Servlet对应的<servlet-name>

5.根据<Servlet-name>找到Servlet 的全限定名

6.使用反射创建对象

Tomcat中的缓存池:

Map<String, Servlet> cache=new HashMap<>();

Servlet obj = cache.get("类的全限定名");

if(obj==null){

//如果是第一次访问:

Object obj2 = Class.forName("类的全限定名").newInstance();

//将创建好的对象放到缓存池中

cache.put("类的全限定名",obj2);

} else {

//不是第一次访问:

//GOTO 7;

}

7.调用init方法进行初始化操作

创建ServletConfig对象,调用init(config)

8.执行service(ServletRequest req, ServletResponse resp),

执行之前先创建ServletRequest , ServletResponse 两个对象

9.给浏览器一个响应信息

三、Servlet初始化参数

在Servlet类中定义初始化参数,会将代码写死,应该将配置信息放到web.xml文件中

问题:如何将配置好的初始化参数获取到?

解决方案:使用ServletConfig来获取

------------------------------------------------------------------------------------

ServletConfig中的常用方法:

public String getServletName():获取Servlet的名称,配置中的<servlet-name>文本

public ServletContext getServletContext():获取Servlet的上下文信息

-------------------------------------

获取初始化参数的相关方法:

public String getInitParameter(String name):根据指定的名称获取当前的Servlet中的初始化参数

public Enumeration<String> getInitParameterNames():获取当前Servlet中的所有的初始化参数的名称

Enumeration:迭代器(Iterator)

关键代码:

     @Override
public void init(ServletConfig config) throws ServletException {
// TODO Auto-generated method stub
System.out.println("init初始化方法"); // 初始化方法的参数
System.out.println(config.getServletName());
System.out.println(config.getInitParameter("encoding"));
System.out.println("----------------------------------");
Enumeration<String> inits = config.getInitParameterNames();
while (inits.hasMoreElements()) {
String name = inits.nextElement();
System.out.println("name");
System.out.println(name+"--->"+config.getInitParameter(name));
} }

------------------------------------------------------------

目前的初始化参数只是为当前的Servlet做的配置,如果在多个Servlet中有相同的配置,那么该配置就重复了---解决方案(使用全局的初始化参数)。

四、Servlet继承体系

其实我们实际开发中需要继承HttpServlet这个关键的类,下面我们就来自己实现这个类,然后体会它里面的继承体系,了解它内部的关联性。

首先是自定义一个 HelloServlet,并且实现Servlet,ServletConfig两个接口以及接口的所有的方法。

 import java.io.IOException;
import java.util.Enumeration; import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse; public class HelloServlet implements Servlet,ServletConfig{ // 声明私有的全局变量
private ServletConfig config; public void init(){
// 事实上,如果子类没有用super方法,就不会被调用
System.out.println("调用了父类的init方法");
} @Override
public void init(ServletConfig config) throws ServletException {
// TODO Auto-generated method stub
System.out.println("HelloServlet:init初始化方法");
this.config = config;
init();
}
@Override
public ServletConfig getServletConfig() {
// TODO Auto-generated method stub
System.out.println("HelloServlet:getServletConfig获取Servlet配置信息");
return config;// 在这里直接返回ServletConfig对象
}
@Override
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException {
// TODO Auto-generated method stub
System.out.println("HelloServlet:service(ServletRequest req, ServletResponse res)处理请求和响应"); }
@Override
public String getServletInfo() {
// TODO Auto-generated method stub
System.out.println("getServletInfo():获取Servlet的相关的信息(作者/版本)");
return null;
}
@Override
public void destroy() {
// TODO Auto-generated method stub
System.out.println("HelloServlet:destroy():资源回收");
} // 为什么要实现ServletConfig的接口,为了使用接口里面的方法,方便子类调用 @Override
public String getServletName() {
// TODO Auto-generated method stub
return config.getServletName();
} @Override
public ServletContext getServletContext() {
// TODO Auto-generated method stub
return config.getServletContext();
} @Override
public String getInitParameter(String name) {
// TODO Auto-generated method stub
return config.getInitParameter(name);
} @Override
public Enumeration<String> getInitParameterNames() {
// TODO Auto-generated method stub
return config.getInitParameterNames();
} }

然后再创建一个MyHttpServlet继承HelloServlet,来处理http请求和响应的类

 import java.io.IOException;

 import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; // 单独一个子类处理service方法 public class MyHttpServlet extends HelloServlet {
@Override
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException {
// TODO Auto-generated method stub // 如果要访问http协议的方法,需要强转类型
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
service(req, res);
} public void service(HttpServletRequest req,HttpServletResponse res){
// super.service(req, res);
}
}

最后再创建一个子类HelloSubServlet,直接继承自MyHttpServlet,注意不是继承最前面的HelloServlet基类哦。

 import java.io.IOException;

 import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; public class HelloSubServlet extends MyHttpServlet { /*
@Override
public void init(ServletConfig config) throws ServletException {
// TODO Auto-generated method stub
super.init(config);
}
* 由于config已经作为父类中全局变量来处理了,所以以上方法其实是多余了
* 但是又需要调用父类的初始化servlet方法init(ServletConfig...)方法,
* 如果子类没有实现,就会去找父类方法,如果子类实现了,而子类中没有用super调用父类方法,父类方法就不会执行
* 所以就采用在父类中声明一个init空的方法,然后在init(ServletConfig...)调用,然后子类只要重写init()方法即可
*
* 但是,前提是:如果子类重写了init(ServletConfig...),就一定要记得要用super调用父类同样的方法
*/ @Override
public void init() {
// 所有初始化的方法写在这里
System.out.println("HelloSubServlet初始化方法");
} @Override
public void service(HttpServletRequest req, HttpServletResponse res) {
super.service(req, res); // 因为子类实现了ServletConfig的接口方法,所以可以直接调用即可。
String name = this.getInitParameter("name");
System.out.println(name);
}; }

然后仔细体会他们之间的关系。

下面是展示直接开发需要知道的继承体系:

五、HttpServletRequest常用的方法

HttpServletRequest接口:处理基于HTTP协议的请求信息

常用的方法:

String getContextPath()  :获取上下文的路径

String getHeader(String name)  :根据名称获取请求头信息

String getMethod()  :获取请求的类型

String getRequestURI()  :获取请求的资源路径

StringBuffer getRequestURL():获取请求的全路径

String getParameter(String name)  :根据名称获取请求参数的值

String getRemoteAddr()  :获取请求的客户端的地址

---------------------------------------------------------------

ServletConfig中的getInitParameter(String name)

获取web.xml文件中配置的初始化参数的值

HttpServletRequest中的getParameter(String name)

获取用户提交的参数值

六、简单案例

一般情况下,一个表单对应一个Servlet。

在webapp目录下创建一个register.html

 <!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<!-- action:表单提交到哪个页面
method: 提交方式
get:提交之后,表单中的数据会显示到地址栏中(不安全)
post:提交之后,表单中的数据不会显示到地址中
enctype:application/x-www-form-urlencoded(默认)
上传文件:multipart/form-data
-->
<form action="/demo/register" method="post" enctype="application/x-www-form-urlencoded">
姓名:<input type="text" name="name">
<br>
密码:<input type="password" name="password">
<br>
<br>
性别:
<input type="radio" name="sex" value="男" checked>男
<input type="radio" name="sex" value="女">女
<br>
职业:
<input type="checkbox" name="java" value="java">Java
<input type="checkbox" name="c" value="c">C
<input type="checkbox" name="IOS" value="ios">IOS <br>
<br>
城市:
<select name="address">
<option value="1">成都</option>
<option value="2" selected="selected">上海</option>
<option value="3">广州</option>
</select> <br>
<br>
评论:
<textarea name="textarea" rows="10" cols="40">在这里输入文本。。。</textarea> <br>
<br>
<input type="submit" value="提交">
<input type="reset" value="重置">
<br> </form> </body>
</html>

然后创建一个RegisterServlet.class

 package com.demo.request;

 import java.io.IOException;
import java.util.Map; import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; public class RegisterServlet extends HttpServlet { /**
*
*/
private static final long serialVersionUID = 1L; @Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// TODO Auto-generated method stub System.out.println("开始执行这段代码。"); // 1、获取请求参数
String name = req.getParameter("name");
String password = req.getParameter("password"); System.out.println("name"+name+" password"+password); Map<String,String[]> map = req.getParameterMap();
String name2 = map.get("name")[0];
System.out.println("name2"+name2);
// 2、调用方法来处理业务逻辑 // 3、控制页面跳转
} }

还要在web.xml中写好配置代码:

 <!-- 配置的是子类Servlet -->
<servlet>
<!-- 配置Servlet类的全限定名 -->
<servlet-name>RegisterServlet</servlet-name>
<servlet-class>com.demo.request.RegisterServlet</servlet-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
<param-name>name</param-name>
<param-value>hahaha</param-value>
</init-param>
</servlet> <!-- Servlet映射,用来访问资源名称,通过helloHeYang就可以访问资源 -->
<servlet-mapping>
<servlet-name>RegisterServlet</servlet-name>
<url-pattern>/register</url-pattern>
</servlet-mapping>

Toncat中默认处理请求参数的编码方式默认是ISO-8859-1,只有一个字节,所以中文会乱码。

--解决方案:

  方式一:

  方式二:

    Post:

      // 将处理请求参数的编码改为UTF-8

      req.setCharacterEncoding("UTF-8");

    Get:

      在service.xml文件中需要设置的配置(可能默认是URIEncoding="ISO-8859-1"):

 <Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" URIEncoding="UTF-8"/>

另外规定:提交表单只能用POST请求。

HttpServletResponse接口:处理基于HTTP协议的响应信息

常用的方法:

PrintWriter getWriter()  :向页面输出字符流

ServletOutputStream getOutputStream()  :向页面输出字节流,实现文件下载

以上两个方法不能被同时调用

void setCharacterEncoding(String charset)  :设置响应信息的字符编码

向页面输出一个html内容,必须要下面两个设置

resp.setCharacterEncoding("UTF-8");

resp.setContentType("text/html");:MIME的类型

上面两个设置可以合在一行代码中

resp.setContentType("text/html; charset=UTF-8");

         // 处理响应
resp.setContentType("text/html;charset=UTF-8");
PrintWriter out = resp.getWriter(); out.print("<thml>");
out.print("<head>");
out.print("<title>");
out.print("你好");
out.print("</title>");
out.print("</head>");
out.print("<body>");
out.print("<font color='red'>你好</font>,世界");
out.print("</body>");
out.print("</html>");

Java之Servlet的更多相关文章

  1. Ed Burns谈HTTP/2和Java EE Servlet 4规范

    在2015年JavaLand大会上,Ed Burns展示了Java EE Servlet 4.0规范(JSR 369)的概要,演讲的重点在于Java EE平台对HTTP/2的支持.HTTP/2旨在解决 ...

  2. 用Delphi的TIdHttp控件发起POST请求和Java的Servlet响应

    http://blog.csdn.net/panjunbiao/article/details/8615880   用Delphi的TIdHttp控件发起POST请求和Java的Servlet响应

  3. 如何使用Java、Servlet创建二维码

    归功于智能手机,QR码逐渐成为主流,它们正变得越来越有用.从候车亭.产品包装.家装卖场.汽车到很多网站,都在自己的网页集成QR码,让人们快速找到它们.随着智能手机的用户量日益增长,二维码的使用正在呈指 ...

  4. java之servlet入门操作教程一续

    本节主要是在java之servlet入门操作教程一  的基础上使用myeclipse实现自动部署的功能 准备: java之servlet入门操作教程一 中完成myFirstServlet项目的创建: ...

  5. JSP、Java和Servlet获取当前工程的路径

    JSP.Java和Servlet获取当前工程的路径: 1.JSP中取得路径: 以工程名为TEST为例: (1)得到包含工程名的当前页面全路径:request.getRequestURI()结果:/TE ...

  6. 【转】如何使用Java、Servlet创建二维码

    归功于智能手机,QR码逐渐成为主流,它们正变得越来越有用.从候车亭.产品包装.家装卖场.汽车到很多网站,都在自己的网页集成QR码,让人们快速找到它们.随着智能手机的用户量日益增长,二维码的使用正在呈指 ...

  7. (转)如何使用Java、Servlet创建二维码

    归功于智能手机,QR码逐渐成为主流,它们正变得越来越有用.从候车亭.产品包装.家装卖场.汽车到很多网站,都在自己的网页集成QR码,让人们快速找到它们.随着智能手机的用户量日益增长,二维码的使用正在呈指 ...

  8. java的servlet执行过程是怎么样的?

    java的servlet执行过程是怎么样   答: Servlet执行过程:程序第一次访问,会调用servlet的init()方法初始化(只执行一次),每次程序执行都会根据请求调用doGet()或者d ...

  9. Java Web Servlet知识点讲解(一)

    一.Web应用架构 如图所示: HTTP协议:一个简单的请求一响应协议,通常运行在TCP之上,它指定了客户端可能发送给服务器什么样的信息以及得到什么样的响应. JDBC:Java语言中用来规范客户端程 ...

  10. java+jsp+servlet实现分页

    web.xml配置: <servlet> <servlet-name>abc</servlet-name> <servlet-class>test.pa ...

随机推荐

  1. APP开发,微信第三方登录的介绍

    去年做了一阵APP相关的开发,经常遇到第三方登陆的需求,比如微信.微博.fb的第三方登陆等等,其实主要的流程都大同小异,这里就以微信为例来介绍,希望对大家有帮助. 微信开放平台(open.weixin ...

  2. tar 打包压缩

    tar命令详解 -c: 建立压缩档案 -x:解压 -t:查看内容 -r:向压缩归档文件末尾追加文件 -u:更新原压缩包中的文件 这五个是独立的命令,压缩解压都要用到其中一个,可以和别的命令连用但只能用 ...

  3. mongoose update操作属性中的变量

    最近在学习mongoose操作数据库,利用schema模型.记录一下通过使用update()操作实现数据库更新: 可在属性中添加变量,'属性名.0',可以修改该属性的第一条属性,依次类推,但是如果想实 ...

  4. spring boot + jpa + bootstrap + thymeleaf 简单的增删改查Demo

    对springboot和bootstrap初学者来说是一个不错Demo 下载地址:点击进入下载Demo 首页(http://localhost:8081) 增加 编辑 搜索

  5. JavaScript基础笔记(十)表单脚本

    表单脚本 一.表单基础知识 JavaScript中表单对应的是HTMLFormElement类型,该类型继承自HTMLElement类型. 通过document.forms可以获得所有表单元素,通过数 ...

  6. python基础一 ------利用生成器生成一个可迭代对象

    #利用生成器生成一个可迭代对象#需求:生成可迭代对象,输出指定范围内的素数,利用生成器产生一个可迭代对象#生成器:本身是可迭代的,只是 yield 好比return返回,yield返回后函数冻结状态, ...

  7. 测试中,重现偶发的BUG问题。

    1.严格按用例执行: 2.如果是作随机测试时,把测试步骤的点进行速记; 3.偶发BUG一般都是严重的,保留现场,让开发人员一起分析留下的现场(如数据的变化,界面窗口的变化等,找出问题的引子,那怕是千丝 ...

  8. vue动态切换视图

    big.vue <template> <div> big <p>{{view}}</p> <!--标准规范--> <component ...

  9. 从零开始搭建一个从Win7环境备份至CentOS7的SVN双机备份环境

    ★几个关键的事项★ 需要关闭防火墙filewalld跟selinux ,在root用户下操作: [root@localhost svnRepos]# systemctl stop firewalld ...

  10. ES6 模板字面量

    模板字面量 解决的问题 1.多行字符串 一个正式的多行字符串的概念 2.基本的字符串格式化 将变量的值嵌入字符串的能力 3.HTML转义 向HTML插入安全转换后的字符串的能力 (1)基础语法 相当于 ...