1 什么是Servlet
A servlet is a small Java program that runs within a Web server. Servlets receive and respond to requests from Web clients, usually across HTTP, the HyperText Transfer Protocol
servlet 是运行在 Web 服务器中的小型 Java 程序(即:服务器端的小应用程序)。servlet 通常通过 HTTP(超文本传输协议)接收和响应来自 Web 客户端的请求。
查看Servlet源码:
假如没有导入源码,就导入源码
2 Hello Servlet 的开发步骤
1 新建web工程
2 写个类HelloServlet实现Servlet接口
import java.io.IOException;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class HelloServlet implements Servlet{
@Override
public void init(ServletConfig config) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
//响应文本到浏览器
res.getWriter().write("hello Servlet");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
3 在service里面响应文本到浏览器
在web.xml里面配置servlet
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.etc.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
5 访问这个servlet
1 再eclipse跑web的项目
eclipse tomcat的默认部署位置
修改eclipse tomcat的默认部署位置
要满足可以修改的条件:移除所有的项目
访问:http://localhost:8080/5HelloServlet/hello
3 Servlet的执行流程
1 通过http://localhost:8080/5HelloServlet/hello 去访问服务器
2 通过/5HelloServlet在server.xml找到对应web工程
4 Tomcat创建Servlet的对象并且调用init的方法
5 再调用service方法之后会响应给浏览器
6 停止tomcat时候,会调用destroy
4 Servlet的生命周期
实例化--->init--->service--->destroy
import java.io.IOException;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class HelloServlet implements Servlet{
public HelloServlet() {
System.out.println("HelloServlet");
}
@Override
public void init(ServletConfig config) throws ServletException {
System.out.println("init");
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
System.out.println("service");
//响应文本到浏览器
res.getWriter().write("hello Servlet");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
System.out.println("destroy");
}
}
5 Servlet的三种创建方式
1 实现Servlet(参考HelloServlet)
2 继承GenericServlet
模拟写一个适配器Servlet
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
public abstract class MServlet implements Servlet{
// 重写这个方法,只有一个不重写(service)
@Override
public void init(ServletConfig config) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class HelloServlet1 extends MServlet{
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
res.getWriter().write("hello Servlet1");
}
}
import java.io.IOException;
import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class HelloServlet1 extends GenericServlet{
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
res.getWriter().write("hello Servlet1");
}
}
<servlet>
<servlet-name>hello1</servlet-name>
<servlet-class>com.etc.servlet.HelloServlet1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello1</servlet-name>
<url-pattern>/hello1</url-pattern>
</servlet-mapping>
3 继承HttpServlet
分析HttpServlet的service方法:
开发步骤:
1 继承HttpSerlvet
2 重写doGet和doPost
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class HelloServlet2 extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
System.out.println("doGet");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
System.out.println("doPost");
}
}
3 web.xml 配置
<servlet>
<servlet-name>hello2</servlet-name>
<servlet-class>com.etc.servlet.HelloServlet2</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello2</servlet-name>
<url-pattern>/hello2</url-pattern>
</servlet-mapping>
post请求的测试:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="/5HelloServlet/hello2" method="post">
<input type="submit" value="提交">
</form>
</body>
</html>
4 创建Servlet快捷的形式
创建好之后,会自动创建Servlet,xml的配置
6 Servlet的细节
1 映射细节-配置多个映射路径
<servlet-mapping>
<servlet-name>hello5</servlet-name>
<url-pattern>/hello5</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>hello5</servlet-name>
<url-pattern>/hello567</url-pattern>
</servlet-mapping>
2 映射细节-通配符*(代表任意字符串)
1 *.do
<servlet>
<servlet-name>hello2</servlet-name>
<servlet-class>com.etc.servlet.HelloServlet2</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello2</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
2 /*
<servlet>
<servlet-name>hello2</servlet-name>
<servlet-class>com.etc.servlet.HelloServlet2</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello2</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
3 /action/*
2 匹配规则细节(优先级)
优先级:从高到低
绝对匹配-->/开头匹配 --> 扩展名方式匹配
/hello /* *.do
3 load-on-startup
servlet在服务器启动时就创建
<servlet>
<description></description>
<display-name>hello5</display-name>
<servlet-name>hello5</servlet-name>
<servlet-class>com.etc.servlet.HelloSerlvet5</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
7 Servlet的线程安全
Servlet单实例,多线程访问存在线程安全的问题。
解决方案:
1 尽量避免使用成员变量,改用局部变量
2 在某些代码块synchronized
8 ServletConfig
A servlet configuration object used by a servlet container to pass
information to a servlet during initialization.
总结:主要用配置(servlet初始化的时候)
1 常见的方法
public String getServletName();//获取servlet的名字
public ServletContext getServletContext();//获得上下文对象
public String getInitParameter(String name);//根据名字获取servlet的初始化参数
public Enumeration<String> getInitParameterNames();//获取servlet的初始化参数名字的集合
2 开发步骤
1 获取ServletConfig对象
private ServletConfig config;
@Override
public void init(ServletConfig config) throws ServletException {
// TODO Auto-generated method stub
super.init(config);
this.config=config;
}
getServletConfig()
2 在doGet方法测试方法
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1 获取Servlet的名字
String servletName = config.getServletName();
System.out.println("servletName:"+servletName);
//2 根据名字获得参数信息
String param = config.getInitParameter("Encoding");
System.out.println(param);
System.out.println("-------------------------------------");
//3 获取参数名字的集合,再通过这些名字获取参数
Enumeration<String> names = config.getInitParameterNames();
while(names.hasMoreElements()) {
String name=names.nextElement();
String value=config.getInitParameter(name);
System.out.println("name:"+name+";"+"value:"+value);
}
response.getWriter().append("Served at: ").append(request.getContextPath());
}
3 配置文件
<servlet>
<description></description>
<display-name>hello6</display-name>
<servlet-name>hello6</servlet-name>
<servlet-class>com.etc.servlet.HelloServlet6</servlet-class>
<init-param>
<param-name>Encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>age</param-name>
<param-value>20</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>hello6</servlet-name>
<url-pattern>/hello6</url-pattern>
</servlet-mapping>
测试结果:
9 ServletContext(上下文)
Defines a set of methods that a servlet uses to communicate with its servlet container.
总结:上下文看成是web应用,定义一系列方法,操作这个应用
1 获取ServletContext对象
1 config.getServletContext()
2 servlet:getServletContext()
2 常见的方法:
public String getContextPath();// 获取上下文路径,Servlet 2.5
public String getServletContextName();//获取上下文名字
public String getServerInfo();//获取服务器的信息(使用服务器,服务器版本号)
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1 获取上下文
// getServletConfig().getServletContext();
ServletContext context=getServletContext();
//2 获取上下文路径,获取上下文名字,获取服务器的信息
String contextPath = context.getContextPath();
String servletContextName = context.getServletContextName();
String serverInfo=context.getServerInfo();
System.out.println(contextPath);
System.out.println(servletContextName);
System.out.println(serverInfo);
response.getWriter().append("Served at: ").append(request.getContextPath());
}
public String getRealPath(String path);//根据相对路径获取绝对路径
public String getMimeType(String file);//传递一个文件路径获取MIME类型
public InputStream getResourceAsStream(String path);//根据路径(相对路径)获取文件输入流
//3 根据相对路径获取绝对路径,传递一个文件路径获取MIME类型,根据路径(相对路径)获取文件输入流
String path="/WEB-INF/web.xml";
// 根据相对路径获取绝对路径
String absolutePath=context.getRealPath(path);
String path2=context.getRealPath("/hello.json");
System.out.println(absolutePath);
//传递一个文件路径获取MIME类型
String mimeType = context.getMimeType(absolutePath);
String mimeType2 = context.getMimeType(path2);
System.out.println(mimeType);//application/xml
System.out.println(mimeType2);//application/json
InputStream is = context.getResourceAsStream(path);// 而且这个路径是相对路径,传绝对路径的返回null
IOUtils.copy(is, System.out);
public String getInitParameter(String name);//获取初始化参数,全局
public Enumeration<String> getInitParameterNames();//获取初始化名字的集合,全局
String contextParam = context.getInitParameter("bookName");
System.out.println(contextParam);
Enumeration<String> paramNames = context.getInitParameterNames();
while(paramNames.hasMoreElements()) {
String name=paramNames.nextElement();
String value=context.getInitParameter(name);
System.out.println(name+":"+value);
}
<context-param>
<param-name>bookName</param-name>
<param-value>Java in thinking</param-value>
</context-param>
<context-param>
<param-name>test</param-name>
<param-value>helloworld</param-value>
</context-param>
结果:
public RequestDispatcher(String path);//获取请求转换器
public Object getAttribute(String name);// 更加名字获取属性的值
public void setAttribute(String name, Object object);
public void removeAttribute(String name);
public Enumeration<String> getAttributeNames();
在Servlet1:
//1设置在Servlet1某个属性
context.setAttribute("age", 20);
//2 Servlet1 转发跳转Servlet2
context.getRequestDispatcher("/hello8").forward(request, response);
在Servlet2 :
ServletContext context = getServletContext();
//3 在Servlet2获取这个属性
int age = (int) context.getAttribute("age");
System.out.println("age:"+age);
response.getWriter().append("age:"+age);
10 Servlet3.0版本
1 @WebServlet
String name() default "";// servlet-name
String[] value() default {};//url-pattern的简单写法
String[] urlPatterns() default {};//url-pattern的写法
int loadOnStartup() default -1;// tomcat启动时候,实例化Servlet并且调用init
WebInitParam[] initParams() default {};//配置初始化参数
2 @WebInitParam
String name();// 初始化参数的名字
String value();// 初始化参数的值
3 开发步骤
第一个测试:
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet(name="hello",value= {"/hello"})
public class HelloServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().append("Hello Servlet3.0");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
第二步测试:
@WebServlet(name="hello",urlPatterns= {"/hello"})
public class HelloServlet extends HttpServlet
第三步测试:
@WebServlet("/hello")
public class HelloServlet extends HttpServlet
第四步测试:
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet(name="hello",value= {"/hello"},loadOnStartup=1)
public class HelloServlet extends HttpServlet{
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
System.out.println("HelloServlet init 3.00000000");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().append("Hello Servlet3.0");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
第五步: