Servlet入门
今日目标
1. 创建servlet
xml
anno(注解)
2. servlet执行原理
3. servlet生命周期
4. servlet体系结构
一 Servlet概述
-
servlet= server+applet 运行在服务器端的java小程序。
-
Servlet是一个接口(规范),一个类要想通过浏览器被访问到,那么这个类就必须直接或间接的实现Servlet接口
作用
接收请求,处理业务,响应结果
二 Servlet快速入门
目标:编写一个普通的java类,通过浏览器可以访问
#编写步骤
1. 定义一个类,实现Servlet接口,重写所有的抽象方法(特别是service方法)
2. 配置web.xml文件
2.1 代码编写
① 创建web项目
② 编写普通java类,实现servlet接口
重写抽象方法(service方法)
package com.itheima01.servlet;
import javax.servlet.*;
import java.io.IOException;
/*
* ctrl+i(implements) : 提示重写所有抽象方法
* ctrl+ enter: 万能提示
* */
public class MyServlet implements Servlet {
/*
* servletRequest : 请求
* servletResponse : 响应
* */
@Override
public void service(ServletRequest servletRequest,
ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("接收到请求"); //控制台打印
//网页上显示出来,不要写中文,会乱码
servletResponse.getWriter().print("hello servlet");//响应给浏览器
}
@Override
public void init(ServletConfig servletConfig) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
③ 配置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_3_1.xsd"
version="3.1">
<!--
1. servlet和servlet-mapping标签里都有servlet-name子标签
内部文本可以随意命名,但是必须一致
2. servlet-class标签: 写Servlet实现类的全限定名(包名+类名)
3. url-pattern : 指定的是该Servlet的虚拟路径
-->
<servlet>
<servlet-name>MyServlet01</servlet-name>
<servlet-class>com.itheima01.servlet.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyServlet01</servlet-name>
<url-pattern>/myServlet</url-pattern>
</servlet-mapping>
</web-app>
④ 部署web项目
⑤ 启动测试
2.2 执行原理
三 Servlet相关API
3.1 生命周期方法
3.1.1 思想介绍
- 生命周期:指的是一个对象从生(创建)到死(销毁)的一个过程
// 1. servlet对象创建时,调用此方法
public void init(ServletConfig servletConfig);
// 2. 用户访问servlet时,调用此方法 (每次访问都会调用一次)
public void service(ServletRequest servletRequest, ServletResponse servletResponse);
// 3. servlet对象销毁时,调用此方法
public void destroy();
* 创建
1)默认情况下
用户第一次访问时,创建servlet,执行init方法
2)修改创建时机
<load-on-startup></load-onstartup>
正数:5-N 【服务器启动时,创建】
补充:Tomcat的web.xml里有1,4 所以推荐5-n
负数(默认值):-1 【用户第一次访问时,创建】
* 运行(提供服务)
用户每次访问时,都执行service方法
* 销毁
服务器正常关闭时,销毁servlet,执行destroy方法
3.1.2 代码演示
① LifeServlet
package com.itheima02.life;
import javax.servlet.*;
import java.io.IOException;
/*
# 观察
1. 第一次访问LifeServlet
init
service
2. 再次访问LifeServlet
service
3. 关闭tomcat之前
destroy
# Servlet中的API
1. 生命周期方法(lifecycle)
对象从创建到销毁的整个过程
1). init : 初始化
a. 默认情况下,浏览器第一次访问时调用
b. 适合执行初始化相关的操作: 加载初始配置
2). service : 服务
a. 浏览器每次访问,都会执行一次
b. 处理业务
3). destroy
a. tomcat在关闭之前,先执行此方法
b. 适合释放资源,保存数据
2. 启动加载
1). 问题: init方法默认浏览器第一次访问才调用,
如果这时候执行加载数据,为时太晚, 用户体验不好
2). 解决: tomcat一启动就加载这个Servlet,并且调用init方法
3). 方式:
在web.xml的servlet下配置
*/
public class LifeServlet implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("LifeServlet init");
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("service");
}
@Override
public void destroy() {
System.out.println("destroy");
}
@Override
public ServletConfig getServletConfig() {
System.out.println("getServletConfig");
return null;
}
@Override
public String getServletInfo() {
System.out.println("getServletInfo");
return null;
}
}
② 配置web.xml
<servlet>
<servlet-name>LifeServlet</servlet-name>
<servlet-class>com.itheima02.life.LifeServlet</servlet-class>
<!--
load-on-startup (写在servlet标签内)
1. 取值是整数n
2. 默认 n=-1,表示不启动加载(第一次访问才会被加载)
3. 当n>=0的时候, 启动加载(数字越小,优先级越高)
-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>LifeServlet</servlet-name>
<url-pattern>/life</url-pattern>
</servlet-mapping>
3.1.3 启动加载
# 启动加载
* 1)问题: 发现 init 默认第一次被访问的时候才调用,适合用来初始化项目数据
* 如果项目数据很多, 加载就需要一定的时间,这样就会给第一个用户的体验不好,因为要等比较久
*
* 2)解决: 服务器一启动,就执行init方法
*
* 3) 实现: 要在web.xml配置
<?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">
<servlet>
<servlet-name>MyServlet_sb</servlet-name>
<servlet-class>com.itheima01.servlet.MyServlet</servlet-class>
<load-on-startup>6</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>MyServlet_sb</servlet-name>
<url-pattern>/myServlet</url-pattern>
</servlet-mapping>
<!--
# 启动加载
1)问题: 发现 init 默认第一次被访问的时候才调用,适合用来初始化项目数据
如果项目数据很多, 加载就需要一定的时间,这样给第一个用户打来的体验不好,因为要等比较久
2)解决: 服务器一启动,就执行init方法
3) 实现: 要在web.xml配置
1). servlet标签内补充一个子标签 load-on-startup (启动时加载)
2). 在load-on-startup里写一个非负整数
n >= 0 , 数字越小,优先级越高 (我们自己写n=5开始写, 0~4被tomcat使用掉了)
默认n=-1, 表示启动时不加载
-->
<servlet>
<servlet-name>LifecycleServlet</servlet-name>
<servlet-class>com.itheima02.life.LifecycleServlet</servlet-class>
<load-on-startup>5</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>LifecycleServlet</servlet-name>
<url-pattern>/LifecycleServlet</url-pattern>
</servlet-mapping>
</web-app>
四 Servlet体系结构
快捷键:
1. ctrl + alt + u : 查看一个类的继承结构图
2. ctrl + h : 这个类的简化版继承结构(类)
1
4.1 GenericServlet
1. 问题:
Servlet中使用频率最高,最重要的方法是service方法(大部分场景)
但是我们每次编写Servlet实现类,都是直接实现Servlet接口,重写5个抽象方法(太冗余了)
2. 需求: 如果我们以后编写Servlet实现类,只要重写service方法就好了
3. 解决:
1). 建立一个抽象类GenericServlet, 继承Servlet接口,重写除了service之外的四个抽象方法,空实现
2). 以后编写其他Servlet,只要继承 GenericServlet, 这时候就只要重写service方法
4. 发现 : 很巧, 开发包已经有了这个类GenericServlet
① 编写普通java类,继承GenericServlet抽象类
public class GoodServlet extends GenericServlet {
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("GoodServlet被访问");
}
}
② 配置web.xml
<servlet>
<servlet-name>GoodServlet</servlet-name>
<servlet-class>com.itheima03.generic.GoodServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>GoodServlet</servlet-name>
<url-pattern>/goodServlet</url-pattern>
</servlet-mapping>
4.2 HttpServlet
1. 问题:
我们在前端的form表单中,method属性, 学习过有两种常用的请求方式(get/post)
我们现在的service方法是这样的: 用户发送请求,无论是什么请求方式,都会统一的执行service方法, 我们无法很好的区别是哪一种请求方式
2. 需求: 我们如果想确切的知道是哪一种请求方式,必须要先了解HttpServletRequest
3. 解决: 自己封装了一个MyHttpServlet -> 开发包 HttpServlet
① 编写前端html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="http://localhost:8080/day04-servlet/HahaServlet">HahaServlet</a>
<form action="http://localhost:8080/day04-servlet/HahaServlet" method="post">
<input type="submit">
</form>
</body>
</html>
② 编写普通java类,继承HttpServlet抽象类
package com.itheima04.http;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/*
HttpServlet是GenericServlet的子类
1. HttpServlet重写了service方法
2. 在service方法中,根据请求方式(http协议)的不同,将service拆分成不同的方法
1). 有两种常用的请求方式
get
post
2). 用户发送请求时(用户在浏览器中访问servlet的地址)
service方法就会执行 (接着就会判断)
get请求方式 -> doGet
post请求方式 -> doPost
*/
public class HahaServlet extends HttpServlet {
//这是post请求方式的service方法
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("post请求方式");
}
//基本上请求方式默认都是get
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("get请求方式");
}
}
③ 配置web.xml
<servlet>
<servlet-name>HahaServlet</servlet-name>
<servlet-class>com.itheima04.http.HahaServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HahaServlet</servlet-name>
<url-pattern>/HahaServlet</url-pattern>
</servlet-mapping>
4.3 经验值分享
① 响应状态码405
请求方法没有重写.....
/*
注意: 如果我们不重写doGet/doPost方法, 那么父类的doGet/doPost方法会执行(继承)
给浏览器响应一个错误: 状态码405 (http1.1)
*/
② 响应状态码500
java代码写错了...
1
五 Servlet路径
5.1 url-pattern
作用:将一个请求网络地址和servlet类建立一个映射关系
1
5.1.1 Servlet映射多个url
1
5.1.2 url映射模式【了解】
配置 url地址取值可以是:
1. 精确匹配(掌握)
/servletDemo3
2. 目录匹配
/aa/*
3. 后缀匹配
*.xxx 例如:*.do
<servlet-mapping>
<servlet-name>PathServlet</servlet-name>
<!--
Servlet的路径(虚拟路径)
1. 一个Servlet可以配置多个虚拟路径 -> 了解 (在Filter中有用)
2. 一个Servlet的路径有三种写法
2.1 精确匹配(掌握)
/servletDemo3
2.2 目录匹配
/aa/*
2.3 后缀匹配
*.xxx 例如:*.do
-->
<url-pattern>/bbb/ccc</url-pattern>
<url-pattern>/aa/*</url-pattern>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>PathServlet</servlet-name>
<url-pattern>/pathServlet03</url-pattern>
</servlet-mapping>
5.2 相对/绝对路径
● 现阶段我们访问资源的方式越来越多,请求路径在编写时难免出现混淆
- 浏览器的地址栏 (输入服务器某个资源地址,敲回车会发送请求)
- a标签的href属性 (超链接被点击的时候会发送请求)
- form表单的action属性 (form中的submit按钮被点击的时候,发送请求)
- js的loation.href属性 (只要设置, 触发相应的)
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="http://www.baidu.com">超链接</a> <br>
<form action="http://www.baidu.com">
<input type="text" name="username"> <br>
<input type="submit">
</form>
<input type="button" value="按钮" id="myid">
<script>
//js
document.getElementById("myid").onclick = function () {
//bom对象: window,location地址栏
location.href = "http://www.baidu.com"
}
</script>
</body>
</html>
这里我们复习下路径规则:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--
html页面中,难免书写url
1. 绝对路径
a. http://localhost:8080/day01-servlet/PathServlet
b. /day01-servlet/PathServlet (省略了三要素,前提: 当前页面和所访问的资源必须在同一服务器上)
内部资源, 推荐!!!
2. 相对路径
1) ../ 是上一级
2) ./ 是平级,可以省略
-->
<a href="http://www.baidu.com">百度</a> <br>
<a href="http://localhost:8080/day01-servlet/PathServlet">我的PathServlet</a> <br>
<a href="/day01-servlet/PathServlet">我的PathServlet2</a> <br>
<a href="http://localhost:8080/day01-servlet/doc/aaa.html">aaa.html绝对路径写法</a>
<a href="doc/aaa.html">aaa.html相对写法</a>
</body>
</html>
六 Servlet3.0
● 通过注解配置Servlet,简化web.xml配置Servlet复杂性,提高开发效率,几乎所有的框架都在使用注解
① 创建web工程【注解】
1
② 编写普通java类,继承HttpServlet
public class QuickServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("QuickServlet....3.0");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("QuickServlet....3.0");
}
}
// @WebServlet(name = "QuickServlet",urlPatterns = "/quickServlet")
// @WebServlet(urlPatterns = "/quickServlet")
// @WebServlet(value = "/quickServlet")
@WebServlet("/quickServlet") // 注解中有且仅有一个属性,名为value时,属性名可以省略...
public class QuickServlet extends HttpServlet {
}
idea创建web模块的规律
tomcat可以同时运行多个web模块,但是现在一般只运行一个模块
注意: project structure中要设置这两项