终于开始触摸servlet了,刚开始心里还有些小激动,但是看了一堆资料之后整个人是懵逼的,云里雾里,在请教了Java同事之后再加上自己的理解,我可能大致搞清了servlet是个什么东东,好吧,可能我比较愚钝吧。
servlet简介
servlet是由sun公司研发的运行Web服务器中的小型java程序。
它是干什么的呢?它是个中间层,它一头用来接收客户端(浏览器/移动端)的Http请求,另一头连接服务器的数据。
- 读取客户端发送来的数据;
- 处理客户端发送来的数据并对数据进行处理,这个过程可能会访问数据库;
- 将处理结果发送给客户端。
我们来举个有意思的例子,Servlet就是数据的大管家,当吃瓜群众(客户端)想了解一些事情时,就会将问题提给Servlet,比如小明说我想看某某类型的片片,他将想法告诉了Servlet,Servlet听到后会意一笑立马就去茫茫数据库帮小明找片片去了,不一会Servlet从数据库中拿到了片片,然后Servlet把片片给了等候已久的小明,小明迫不及待打开了片片然后兴致勃勃地看起了喜洋洋。
那么下面来先来了解一下Servlet的生命周期。
servlet生命周期
Servlet从创建到销毁是这样的:
- init(),进行初始化;
- service(),处理客户端的请求;
- destroy(),终止;
- Servlet 是由 JVM 的垃圾回收器进行垃圾回收的。
下面来详细地讨论一下生命周期的各个方法吧。
1. init()方法
一次性方法,它只有在Servlet被创建的时候被调用一次,往后再有请求来临时不会再被调用。
public void init() throws ServletException {
// 初始化代码...
}
2. service()方法
是请求来临执行的主要方法,Web服务器会调用service()来处理客户端的请求,并把响应返回给客户端。
每次服务器接收到一个Servlet请求时,服务器会产生一个新的线程并调用服务,service()检查HTTP请求的类型(get,post,put,delete等),并在适当的时候调用对应的doGet(),doPost(),doPut(),doDelete()方法。
serive()由Web服务调用,所以我们不需要对service()进行任何处理,只需要根据需要重写doGet(),doPost()等方法即可。
public void service(ServletRequest request,
ServletResponse response)
throws ServletException, IOException{
}
3. doGet()方法
GET 请求来自于一个 URL 的正常请求,或者来自于一个未指定 METHOD 的 HTML 表单,它由 doGet() 方法处理。
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
// Servlet 代码
}
4. doPost()方法
POST 请求来自于一个特别指定了 METHOD 为 POST 的 HTML 表单,它由 doPost() 方法处理。
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
// Servlet 代码
}
5. destory()方法
destroy() 方法只会被调用一次,在 Servlet 生命周期结束时被调用。destroy() 方法可以让您的 Servlet 关闭数据库连接、停止后台线程、把 Cookie 列表或点击计数器写入到磁盘,并执行其他类似的清理活动。
在调用 destroy() 方法之后,servlet 对象被标记为垃圾回收。
public void destroy() {
// 终止化代码...
}
servlet简单实例
通过上面的了解,我们对Servlet有了一定的认识,那么,接下来就来创建一个简单Servlet,这个HelloServlet类的作用就是将客户端传递的参数打印出来。
Servlet的步骤:
- 新建Servlet类;
- 修改web.xml配置;
- 将该类部署到Tomcat上。
1. 新建HelloServlet
public class HelloServlet extends HttpServlet {
@Override
public void init() throws ServletException {
super.init();
System.out.println("init()");
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
super.service(req, resp);
System.out.println("service()");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
System.out.println("doGet()");
System.out.println(req.getParameter("name"));
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
System.out.println("doPost()");
}
@Override
public void destroy() {
System.out.println("destroy()");
}
}
2. web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name></display-name>
<!-- 用来声明servlet -->
<!-- servlet-name声明一个别名 -->
<!-- servlset-class对应的servlet类路径 -->
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.servlet.HelloServlet</servlet-class>
</servlet>
<!-- 声明servlet的url地址 -->
<!-- servlet-name别名,就是servlet声明中的别名 -->
<!-- url-pattern如何通过url访问 -->
<!-- url: ip:端口号/项目名称/url-pattern -->
<!-- url: localhost:8080/MyServlet/servlet/HelloServlet -->
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/servlet/HelloServlet</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
web是用来干嘛的?其实我们可以将其理解为一个注册文件,将我们所创建的servlet在此处声明。具体如何声明去看上面的代码注释。
3. Tomcat
如何配置自行百度,重启成功后,我们在浏览器
localhost:8080/MyServlet/servlet/HelloServlet?name=戚继光
此时在控制台输出:戚继光。
我在这中间遇到了中文乱码的问题,该如何解决呢?参照一下步骤吧。
1.在web.xml中增设全局设置。
<context-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</context-param>
2.在tomcat的安装目录下找到”/conf/server.xml”修改。
// 修改前
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
// 修改后
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
URIEncoding="UTF-8" />
重启tomcat就发现中文不在乱码了。
Servlet的实现方式
常见的三种方式:
- 实现Servlet接口;
- 继承GenericServlet类;
- 继承HttpServlet类;
1. 实现Servlet接口
该方式下,需要根据业务实现Servlet接口提供的方法,尤其是service( )方法。
2. 继承GenericServlet
GenericServlet实现了Servlet接口和ServletConfig接口。GenericServlet提供了生命周期方法init()和destroy()以及ServletConfig接口中的方法的简单版本,所以它使编写 Servlet变得更容易。故,若继承GenericServlet一般情况下我们只需重写service()方法即可。
3. 继承HttpServlet
HttpServlet继承自GenericServlet且实现了Servlet接口和ServletConfig接口。HttpServlet在实现Servlet接口时,覆写了service()方法,该方法会自动判断用户的请求方式,若为GET请求则调用HttpServlet的doGet()方法,若为Post请求则调用doPost()方法,诸如此类。
因此,开发人员在编写Servlet时,通常只需要覆写doGet()或doPost()方法而不用覆写service方法()。故,在实际开发中编写Servlet时,通常情况下,应继承HttpServlet而避免直接去实现Servlet接口。
一些细节:
- 同一个Servlet可以被映射到多个路径上,即多个<servlet-mapping>元素的<servlet-name>的设置值可以是同一个Servlet的注册名。
- 可用.扩展名的形式配置url-pattern,其中表示任意字符串;比如配置<url-pattern>*.do</url-pattern>时可用任意字符串.do组成的url访问该Servlet;
- 可用/配置url-pattern,其中表示任意字符串;比如配置<url-pattern>/*</url-pattern>时可用/任意字符串组成的url访问该Servlet。
ServletConfig
在Servlet的配置文件web.xml中可使用<init-param>为Servlet配置初始化参数。
当servlet配置了初始化参数后Web容器在创建Servlet实例对象时会自动将这些初始化参数封装到ServletConfig对象中并在调用servlet的init()方法时将ServletConfig对象传递给servlet。
所以,可通过ServletConfig对象得到当前Servlet的初始化参数信息。
在web.xml中设置了encoding属性。
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.servlet.HelloServlet</servlet-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</servlet>
在HelloServlet.class中获取属性
public void init(ServletConfig servletConfig) throws ServletException {
String encoding=servletConfig.getInitParameter("encoding");
System.out.println("---> encoding="+encoding);
}
ServletContext
Web容器在启动时,它会为每个Web应用程序都创建一个对应的ServletContext对象,它代表当前web应用。在此介绍ServletContext几种常用的应用。
1. 不同Servlet间共享数据
// 保存数据
public void setAttribute(String name, Object object);
// 获取数据
public Object getAttribute(String name);
// 删除数据
public void removeAttribute(String name);
2. 获取全局配置信息
我们在web.xml中设置全局的编码格式。
// 配置属性
<context-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</context-param>
// 获取属性
ServletContext servletContext=mServletConfig.getServletContext();
String encoding=servletContext.getInitParameter("encoding");
3. ServletContext获取资源路径
可使用ServletContext的getRealPath(path)方法获取到当前应用任何位置的任何资源,其中参数path路径一般以/WEB-INF开头,斜杠/就表示了当前应用。为什么斜杠/后就是WEB-INF呢?其实之前我们也提到了:应用部署后所有的东西都在WEB-INF路径下。我们也可以打开……tomcat\webapps\应用名\WEB-INF\即可看到与应用有关的所有资源。
现在我们在src的根目录下建立test.properties文件,在该文件中只写入一行简单的测试数据:username=戚继光;
现在,我们在Servlet中获取该username,如下所示:
import java.util.Properties;
mServletConfig=servletConfig;
ServletContext servletContext=mServletConfig.getServletContext();
String path=servletContext.getRealPath("/WEB-INF/classes/test.properties");
Properties properties=new Properties();
properties.load(new FileInputStream(path));
String name=(String) properties.getProperty("username");
在此,再次提醒:src中的代码编译后的class文件存放于……tomcat\webapps\应用名\WEB-INF\classes文件夹中。
4. 实现Servlet的转发
简单的例子,后续会继续探讨。
mServletConfig=servletConfig;
ServletContext servletContext=mServletConfig.getServletContext();
RequestDispatcher requestDispatcher=servletContext.getRequestDispatcher(path);
requestDispatcher.forward(request, response);