一、Servlet简介
JSP的本质就是Servlet,JSP页面部署到Web容器中后,Web容器会把JSP编译成对应的Servlet。
Servlet是服务器端小程序,用于处理及相应客户端的请求。
Servlet有四个方法doGet()、doPost()、doPut()、doDelete()分别用于处理客户端get、post、put、delete四种请求。
通常情况下,由于客户端只有post和get两种请求,所以只需重写doGet()和doPost()两种方法,或者可以只重写service()一个方法即可响应所有请求。
看下HttpServlet类的源码就知道
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String method = req.getMethod();
……
} else if (method.equals(METHOD_HEAD)) {
long lastModified = getLastModified(req);
maybeSetLastModified(resp, lastModified);
doHead(req, resp);
} else if (method.equals(METHOD_POST)) {
doPost(req, resp);
} else if (method.equals(METHOD_PUT)) {
doPut(req, resp);
} else if (method.equals(METHOD_DELETE)) {
doDelete(req, resp);
} else if (method.equals(METHOD_OPTIONS)) {
doOptions(req, resp);
} else if (method.equals(METHOD_TRACE)) {
doTrace(req, resp);
}
……
}
二、案例
来举一个登录的小栗子吧,因为比较懒,就没有连接数据库验证用户名密码是否存在且正确~~~
1.新建一个maven项目
在pom.xml文件里加入必要的依赖包
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
2.新建一个登陆界面login.jsp
<%@ page language="java" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>登录界面</title>
</head>
<body>
<form id="login" method="post" action="login">
用户名:<input type="text" name="username" value="Annie"/><br />
密码:<input type="password" name="pwd" value="123"/><br />
<input type="submit" value="登录"></input>
</form>
</body>
</html>
3.新建一个欢迎的跳转页面welcome.jsp
<%@ page language="java" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>欢迎界面</title>
</head>
<body>
亲爱的
<%=session.getAttribute("name") %>:你好!
欢迎登录!
</body>
</html>
4.新建一个Servlet类
package com.yolanda.fun.servlet;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class LoginServlet extends HttpServlet implements Servlet{
/**
*
*/
private static final long serialVersionUID = 1L;
public void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String username = request.getParameter("username");
String pwd = request.getParameter("pwd");
HttpSession session = request.getSession();
session.setAttribute("name", username);
// Servlet本身并不输出响应到客户端,因此必须将请求转发
RequestDispatcher rd = request.getRequestDispatcher("/welcome.jsp");
// 转发请求
rd.forward(request, response);
}
}
当然这个类还有一种写法
package com.yolanda.fun.servlet;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class LoginServlet extends HttpServlet implements Servlet{
/**
*
*/
private static final long serialVersionUID = 1L;
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String username = request.getParameter("username");
String pwd = request.getParameter("pwd");
HttpSession session = request.getSession();
session.setAttribute("name", username);
// Servlet本身并不输出响应到客户端,因此必须将请求转发
RequestDispatcher rd = request.getRequestDispatcher("/welcome.jsp");
// 转发请求
rd.forward(request, response);
}
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
doPost(req, resp);
}
}
两种都可以哒。
这个地方用了一个请求转发类,看下源码里的定义,转发request请求
5.将Servlet配置在Web应用中,以响应用户请求
在web.xml文件里面配置一下这个servlet就好啦
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>ServletDemo</display-name>
<servlet>
<servlet-name>loginServlet</servlet-name>
<servlet-class>com.yolanda.fun.servlet.LoginServlet</servlet-class>
<servlet-mapping>
<servlet-name>loginServlet</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
</web-app>
还有一种方式不用在web.xml里配置,直接用注释的方式来配置,那怎么写呢?
用@WebServlet这个注释,但是提示我没有这个注释,这是因为我用的
servlet-api的版本里没有这个类
到\apache-tomcat-8.0.24\lib里找到这个包servlet-api.jar
反编译看一下,有这个类
那把上面的那个pom文件里的jar包
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.4</version>
<scope>provided</scope>
</dependency>
删掉
外部引用包,替换成tomcat8里面的那个jar包
在刚才的Servlet类里加一行注释
@WebServlet(name="loginServlet", urlPatterns="/login")
web.xml里面的Servlet配置删掉。
效果嘛,就是这样,入口地址
http://localhost:8080/servletDemo/login.jsp
跳转以后的页面,网址变成了http://localhost:8080/servletDemo/login
其实上面直接在welcome.jsp里面用
<%=request.getParameter(“username”)%>
不用Servlet类,也可以达到上面的效果,用到Servlet类主要是想作为控制层, 来做一些复杂一点的操作,比如连接一下数据库,验证一下用户名密码,因为我懒嘛,就没有写了。如果要连接的话,也很简单
在web.xml文件里配置一下
<init-param>
<param-name>driver</param-name>
<param-value>oracle.jdbc.driver.OracleDriver</param-value>
</init-param>
<init-param>
<param-name>url</param-name>
<param-value>jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=
(ADDRESS=(PROTOCOL=TCP)(HOST = …)(PORT = 1521)))
(CONNECT_DATA=(SERVICE_NAME=…)(SERVER=DEDICATED)))</param-value>
</init-param>
<init-param>
<param-name>user</param-name>
<param-value>root</param-value>
</init-param>
<init-param>
<param-name>pwd</param-name>
<param-value>123</param-value>
</init-param>
或者在Servlet类的前面用注释配置也可以
@WebServlet(name="loginServlet"
, urlPatterns={"/login"}
, initParams={
@WebInitParam(name="driver", value="oracle.jdbc.driver.OracleDriver"),
@WebInitParam(name="url", value="
jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=
(ADDRESS=(PROTOCOL=TCP)(HOST = …)(PORT = 1521)))
(CONNECT_DATA=(SERVICE_NAME=…)(SERVER=DEDICATED)))
"),
@WebInitParam(name="user", value="root"),
@WebInitParam(name="pwd", value="123")})
接下来就是获取上述的配置啦,写在Servlet类里面就好了,通过ServletConfig对象来完成
String driver = config.getInitParameter("driver");
String url = config.getInitParameter("url");
String user = config.getInitParameter("user");
String pwd = config.getInitParameter("pwd");
后面的步骤就是注册驱动、获取连接等数据库连接的基本操作啦,懒得写啦~~
三、Servlet的生命周期
Servlet在Web容器中运行的时候,其实例的创建和销毁是由Web容器来控制的。
创建Servlet实例有两个时机,
(1)客户端第一次请求某个Servlet时,系统创建该Servlet的实例;
(2)Web应用启动时,立即创建Servlet实例,即load-on-startup Servlet。
每个Servlet运行都遵循以下生命周期
(1)创建Servlet实例;
(2)Web容器调用Servlet的init方法,对Servlet进行初始化;
(3)Servlet初始化后,将一直存在于容器中,用于响应客户端请求;
(4)Web容器先调用Servlet的destroy方法,通常在Web应用关闭时,销毁Servlet。
四、load-on-startup
Servlet配置这个属性后,将会在Web应用启动时,立即创建Servlet实例,其数值越小,优先级越高。
配置方法也是两种
1.在web.xml里配置,例如
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
2.就是直接在Servlet类前面的注释
@WebServlet(loadOnStartup=2)
就酱~