servlet
Servlet(Server Applet),全稱Java Servlet,暫無中文譯文。是用Java編寫的服務(wù)器端程序。其主要功能在于交互式地瀏覽和修改數(shù)據(jù),生成動態(tài)Web內(nèi)容。狹義的Servlet是指Java語言實(shí)現(xiàn)的一個接口,廣義的Servlet是指任何實(shí)現(xiàn)了這個Servlet接口的類,一般情況下,人們將Servlet理解為后者。
Servlet運(yùn)行于支持Java的應(yīng)用服務(wù)器中。從原理上講,Servlet可以響應(yīng)任何類型的請求,但絕大多數(shù)情況下Servlet只用來擴(kuò)展基于HTTP協(xié)議的Web服務(wù)器。
最早支持Servlet標(biāo)準(zhǔn)的是JavaSoft的Java Web Server,此后,一些其它的基于Java的Web服務(wù)器開始支持標(biāo)準(zhǔn)的Servlet。
servlet入門小實(shí)例
src下創(chuàng)建com.webtest.servlet.HelloServlet.java
package com.webtest.servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* Created by elijahliu on 2017/2/19.
*/
public class HelloServlet extends javax.servlet.http.HttpServlet {
protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
}
@Override
public void init(ServletConfig config) throws ServletException {
System.out.println("==========init with parameter=============");
super.init(config);
}
@Override
public void init() throws ServletException {
System.out.println("================init without parameter");
super.init();
}
@Override
public void destroy() {
System.out.println("========destroy============");
super.destroy();
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("=============service===============");
PrintWriter pw = resp.getWriter();//這三行用于將字符輸出到瀏覽器,PrintWriter是一個字符輸出流
pw.println("Hellowworld");
pw.close();//關(guān)閉輸出流對象
}
protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
}
}
這里繼承了 httpservlet ,使用PrintWriter輸出流輸出到頁面。
相應(yīng)的修改web.xml配置入口url
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.webtest.servlet.HelloServlet</servlet-class><!--servelt-class用于連接完全限定名,也就是name對應(yīng)的類的路徑-->
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/Hello</url-pattern><!--servlet mapping 通過name與servlet相連接,然后通過下面的url-pattern,當(dāng)瀏覽器路徑是這個的時(shí)候,訪問這個路徑,就會調(diào)用對應(yīng)的servlet來處理-->
</servlet-mapping>
servelt-class用于連接完全限定名,也就是name對應(yīng)的類的路徑
servlet mapping 通過name與servlet相連接,然后通過下面的url-pattern,當(dāng)瀏覽器路徑是這個的時(shí)候,訪問這個路徑,就會調(diào)用對應(yīng)的servlet來處理
servlet處理流程分析

處理流程:客戶端發(fā)送request請求,到Tomcat webserver服務(wù)器,然后http服務(wù)器再再servlet容器中創(chuàng)建運(yùn)行servlet,也就是說,在沒有訪問的請求發(fā)起時(shí),servlet是不創(chuàng)建對象的。servlet的通過requset response對象來處理數(shù)據(jù),結(jié)束后,可以再調(diào)用其他servlet,或最后直接將數(shù)據(jù)傳輸?shù)綖g覽器返回響應(yīng)。
servlet執(zhí)行流程

在創(chuàng)建servlet實(shí)例時(shí),會調(diào)用init()方法來進(jìn)行初始化,初始化后,servlet才會處于服務(wù)狀態(tài)。整個servlet生命周期中,只能進(jìn)行一次初始化。
service()方法可以多次調(diào)用,這個請求次數(shù)有關(guān),用來處理客戶端的請求。
destroy()方法,在servlet不再使用時(shí),容器會調(diào)用destroy()方法進(jìn)行銷毀servlet實(shí)例。、
servlet編程實(shí)例(1)

首先創(chuàng)建Login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>loginservlet</title>
</head>
<body>
<form action="<%=request.getContextPath()%>/LoginServlet" method="post">
<input type="text" name="uname"/>
<input type="password" name="upwd"/>
<input type="submit" value="submit">
</form>
</body>
</html>
其中的<%=request.getContextPath()%>
request.getContextPath() 返回站點(diǎn)的根目錄
request.getRealpath("/")得到的是實(shí)際的物理路徑,也就是你的項(xiàng)目所在服務(wù)器中的路徑
request.getScheme() 等到的是協(xié)議名稱,默認(rèn)是http
request.getServerName() 得到的是在服務(wù)器的配置文件中配置的服務(wù)器名稱 比如:localhost .baidu.com 等等
request.getServerPort() 得到的是服務(wù)器的配置文件中配置的端口號 比如 8080等等
再創(chuàng)建LoginServlet
package com.webtest.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Created by elijahliu on 2017/2/19.
*/
@WebServlet(name = "LoginServlet")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.service(req, resp);
String username = req.getParameter("uname");
String password = req.getParameter("upwd");
System.out.println(username);
System.out.println(password);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
最后在web.xml中更改servlet的路徑配置
<!--//loginservlet-->
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.webtest.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/LoginServlet</url-pattern>
</servlet-mapping>
Servlet編程實(shí)例(2)
使用doGet doPost方法來實(shí)現(xiàn)登錄邏輯.

將service的業(yè)務(wù)邏輯放到doPost中,在doGet中調(diào)用doPost。降低代碼的重復(fù)性,更符合邏輯。
package com.webtest.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Created by elijahliu on 2017/2/19.
*/
@WebServlet(name = "LoginServlet")
public class LoginServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.service(req, resp);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("uname");
String password = request.getParameter("upwd");
System.out.println(username);
System.out.println(password);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
servlet編程實(shí)例(3) 添加登錄后的處理流程

建立success.jsp文件
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>success</title>
</head>
<body>
success
用戶<%=request.getParameter("uname")%><br />
密碼<%=request.getParameter("upwd")%><br />
<a href="LoginServlet.jsp">back to login</a>
</body>
</html>
建立error.jsp頁面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>error</title>
</head>
<body>
error happened
用戶<%=request.getParameter("uname")%><br/>
密碼<%=request.getParameter("upwd")%><br/>
<a href="LoginServlet.jsp">back to login</a>
</body>
</html>
更改LoginServlet文件,修改業(yè)務(wù)邏輯,重定向
package com.webtest.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Created by elijahliu on 2017/2/19.
*/
@WebServlet(name = "LoginServlet")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("uname");
String password = request.getParameter("upwd");
System.out.println(username);
System.out.println(password);
if (username.equals("elijah") && password.equals("123456")) {//若用戶密碼相同,則重定向到相應(yīng)的頁面
response.sendRedirect(request.getContextPath() + "/Servletpage/success.jsp");
} else {
response.sendRedirect(request.getContextPath() + "/Servletpage/error.jsp");
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
Servlet編程實(shí)例(4)
這里是用了請求轉(zhuǎn)發(fā),只進(jìn)行一個請求響應(yīng)流程。請求對象,傳入servlet后,servlet將reques response對象轉(zhuǎn)發(fā)到相應(yīng)的成功失敗頁面。
package com.webtest.servlet;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Created by elijahliu on 2017/2/19.
*/
@WebServlet(name = "LoginServlet")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("uname");
String password = request.getParameter("upwd");
System.out.println(username);
System.out.println(password);
String forward = null;
if (username.equals("elijah") && password.equals("123456")) {//若用戶密碼相同,則重定向到相應(yīng)的頁面
forward = "/Servletpage/success.jsp";
RequestDispatcher rd = request.getRequestDispatcher(forward);//requestDispatcher是一個請求轉(zhuǎn)發(fā)對象
//getRequestDispatcher獲取一個Dispatcher對象,forward為轉(zhuǎn)發(fā)的地址
rd.forward(request, response);//執(zhí)行請求轉(zhuǎn)發(fā),轉(zhuǎn)發(fā)當(dāng)前的額request 和response對象
//請求重定向
//response.sendRedirect(request.getContextPath() + "/Servletpage/success.jsp");
} else {
forward = "/Servletpage/error.jsp";
RequestDispatcher rd = request.getRequestDispatcher(forward);//requestDispatcher是一個請求轉(zhuǎn)發(fā)對象
//getRequestDispatcher獲取一個Dispatcher對象,forward為轉(zhuǎn)發(fā)的地址
rd.forward(request, response);//執(zhí)行請求轉(zhuǎn)發(fā),轉(zhuǎn)發(fā)當(dāng)前的額request 和response對象
//請求重定向
//response.sendRedirect(request.getContextPath() + "/Servletpage/error.jsp");
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
requestDispatcher是一個請求轉(zhuǎn)發(fā)對象
getRequestDispatcher獲取一個Dispatcher對象,forward為轉(zhuǎn)發(fā)的地址
PS:需要注意一點(diǎn)的是,RequestDispatcher方法不能轉(zhuǎn)發(fā)到不同的應(yīng)用地址,如 轉(zhuǎn)發(fā)地址為 www.google.com這是不可以的。但是response.sendRedirect重定向方法是可以的。
Servlet編程實(shí)例(5)
添加了 JBDC 數(shù)據(jù)庫校驗(yàn),完成校驗(yàn)用戶的Service層的編寫
在DAO層添加實(shí)現(xiàn)獲取用戶的方法,返回結(jié)果集
UserDao.java
package com.webtest.dao;
import com.webtest.entity.User;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* Created by elijahliu on 2017/2/18.
*/
public interface UserDao {
public void save(Connection conn, User user) throws SQLException;
public void update(Connection conn,Long id,User user) throws SQLException;
public void delete(Connection conn, User user) throws SQLException;
//需要編寫相應(yīng)的實(shí)現(xiàn),這是典型的面向接口的編程,接口只定義外觀和行為
//獲取用戶信息
public ResultSet get(Connection conn, User user)throws SQLException;
}
在UserDaoimpl中實(shí)現(xiàn)get方法
@Override
public ResultSet get(Connection conn, User user) throws SQLException {
PreparedStatement ps = conn.prepareStatement("SELECT * FROM tbl_user WHERE name=? AND password=?");
ps.setString(1, user.getName());
ps.setString(2,user.getPassword());
return ps.executeQuery();
}
創(chuàng)建service層的包,com.webtest.service.
package com.webtest.service;
import com.webtest.dao.UserDao;
import com.webtest.dao.impl.UserDaoimpl;
import com.webtest.entity.User;
import com.webtest.util.ConnectionFactory;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* Created by elijahliu on 2017/2/19.
*/
public class CheckuserService {
private UserDao userDao= new UserDaoimpl();//上轉(zhuǎn)型建立一個持久層類
public boolean check(User user){
Connection conn = null;
conn = ConnectionFactory.getInstance().makeConnection();//獲取一個連接工廠類的單例連接
try {
conn.setAutoCommit(false);//設(shè)置不自動提交
ResultSet rs = userDao.get(conn, user);//獲取查詢結(jié)果集
while (rs.next()) {//不為空,則存在,那么就返回true
return true;
}
} catch (SQLException e) {
try {
conn.rollback();//錯誤發(fā)生則回滾
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}finally {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return false;
}
}
Servlet編程實(shí)例(6)
完成控制層的業(yè)務(wù)邏輯編寫。在com.webtest.servlet下創(chuàng)建CheckServlet.java
在這個servlet中調(diào)用service層的CheckServlet中的check()方法,完成用戶的校驗(yàn),與成功或失敗頁面的跳轉(zhuǎn)。在web.xml中,完成servlet的路徑配置。CheckServlet相當(dāng)于控制層。
CheckServlet.java
package com.webtest.servlet;
import com.webtest.entity.User;
import com.webtest.service.CheckuserService;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Created by elijahliu on 2017/2/19.
*/
@WebServlet(name = "CheckServlet")
public class CheckServlet extends HttpServlet {
CheckuserService cku = new CheckuserService();//創(chuàng)建service 業(yè)務(wù)邏輯對象
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String uname = request.getParameter("uname");
String passwd = request.getParameter("upwd");
RequestDispatcher rd = null;
String forward = null;
if (uname == null && passwd == null) {//如果用戶名或密碼為空,則轉(zhuǎn)發(fā)到錯誤頁面
request.setAttribute("msg", "用戶名或密碼為空");
rd = request.getRequestDispatcher("/Servletpage/error.jsp");
rd.forward(request,response);
} else {
User user = new User();//創(chuàng)建用戶對象,使用service層的check方法 判斷是否存在該用戶
user.setName(uname);
user.setPassword(passwd);
boolean bool = cku.check(user);//檢查用戶是否在數(shù)據(jù)庫中存在
if (bool) {
forward = "/Servletpage/success.jsp";
}else{
request.setAttribute("msg","用戶名或密碼錯誤,重新輸入");
forward = "/Servletpage/error.jsp";
}
rd = request.getRequestDispatcher(forward);//根據(jù)查出是否存在該用戶,從而來確定執(zhí)行轉(zhuǎn)發(fā)的路徑
rd.forward(request,response);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
web.xml
<!--checkservlet-->
<servlet>
<servlet-name>CheckServlet</servlet-name>
<servlet-class>com.webtest.servlet.CheckServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CheckServlet</servlet-name>
<url-pattern>/CheckServlet</url-pattern>
</servlet-mapping>
Servlet編程實(shí)例(7)
完成了前端頁面的編寫,運(yùn)行了登錄實(shí)例程序。登陸頁面在finalservlet包中。
對頁面做一個最基礎(chǔ)的頁面美化。
創(chuàng)建finalservlet目錄 存放三個前端頁面
login.jsp
<%--
Created by IntelliJ IDEA.
User: elijahliu
Date: 2017/2/19
Time: 20:28
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>login</title>
<style type="text/css">
body {
color: #000;
font-size: 14px;
margin: 20px auto;
}
</style>
<script type = "text/javascript">
function check(form){
if(document.forms.loginForm.uname.value == "") {
alert("請輸入用戶名!");
document.forms.loginForm.uname.focus();
return false;
}
if(document.forms.loginForm.upwd.value == "") {
alert("請輸入密碼!");
document.forms.loginForm.upwd.focus();
return false;
}
}
</script>
</head>
<body>
<form action="<%=request.getContextPath()%>/CheckServlet" method="post" name="loginForm">
<table border="1" cellpadding="0" cellpdding="5" bordercolor="silver" align="center">
<tr>
<td colspan="2" align="center" bgcolor="#E8E8E8">用戶登錄</td>
</tr>
<tr>
<td>用戶名:</td>
<td>
<input type="text" name="uname"/>
</td>
</tr>
<tr>
<td>密碼:</td>
<td>
<input type="password" name="upwd"/>
</td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" name="submit" onclick="return check(this);"/><%--添加了一個onclik方法,觸發(fā)時(shí)會調(diào)用check函數(shù)--%>
</td>
</tr>
</table>
</form>
</body>
</html>
error.jsp
<%--
Created by IntelliJ IDEA.
User: elijahliu
Date: 2017/2/19
Time: 16:16
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>error</title>
<style type="text/css">
body {
color: #000;
font-size: 14px;
margin: 20px auto;
}
#message{
test-align:center;
}
</style>
</head>
<body>
<div id="message">
error happened
<%
Object obj = request.getAttribute("msg");
if (obj != null) {
out.println(obj.toString());
} else {
out.println("none");
}
%>
用戶<%=request.getParameter("uname")%>
<br/>
密碼<%=request.getParameter("upwd")%><br/>
<a href="<%=request.getContextPath()%>/finalservlet/Login.jsp">back to login</a>
</div>
</body>
</html>
success.jsp
<%--
Created by IntelliJ IDEA.
User: elijahliu
Date: 2017/2/19
Time: 16:14
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>success</title>
<style type="text/css">
body {
color: #000;
font-size: 14px;
margin: 20px auto;
}
#message {
test-align: center;
}
</style>
</head>
<body>
<div id="message">
success
用戶<%=request.getParameter("uname")%><br/>
密碼<%=request.getParameter("upwd")%><br/>
<a href="<%=request.getContextPath()%>/finalservlet/Login.jsp">back to login</a>
</div>
</body>
</html>