1.Servlet簡介
(1)Java Servlet是和平臺無關的服務器端組件,它運行在Servlet容器中。Servlet容器負責Servlet和 客戶的通信以及調用Servlet的方法,Servlet和客戶的通信採用“請求/響應”的模式。
(2)Servlet可完成如下功能:創建並返回基於客戶請求的動態HTML頁面;創建可嵌入到現有HTML 頁面中的部分HTML 頁面(HTML 片段);與其它服務器資源(如數據庫或基於Java的應用程序)進行通信。
2.Servlet的helloworld實現
首先,需要創建一個實現Servlet接口的實現類:public class HelloWorld implements Servlet
package com.zhaoliang.javaweb;
import java.io.IOException;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
/*
* 如何創建Servlet?
*/
public class HelloServlet implements Servlet{
@Override
public void destroy() {
System.out.println("destroy");
}
@Override
public ServletConfig getServletConfig() {
System.out.println("servlet config");
return null;
}
@Override
public String getServletInfo() {
System.out.println("servlet info");
return null;
}
@Override
public void init(ServletConfig arg0) throws ServletException {
System.out.println("init");
}
@Override
public void service(ServletRequest arg0, ServletResponse arg1)
throws ServletException, IOException {
System.out.println("service");
}
public HelloServlet(){
System.out.println("HelloServlet's constructor");
}
}
創建完成Servlet之後,我們需要在web.xml文件中配置和映射Servlet
<pre name="code" class="html"><?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<!-- 配置Servlet -->
<servlet>
<!-- Servlet的註冊名 -->
<servlet-name>helloServlet</servlet-name>
<!-- Servlet的全類名 -->
<servlet-class>com.zhaoliang.javaweb.HelloServlet</servlet-class>
</servlet>
<!-- 映射Servlet -->
<servlet-mapping>
<!-- 與某一個Servlet的註冊名一致 -->
<servlet-name>helloServlet</servlet-name>
<!-- 映射具體的訪問路徑:/代表當前項目的根目錄 -->
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
這樣我們就可以在服務上運行Servlet了。
注:
1.Servlet容器:運行Servlet,JSP,Filter等軟件環境
1)可以用來創建Servlet,並調用Servlet相關生命週期方法
2)JSP,Filter,Listener,Tag......
2.Servlet的生命週期方法:以下方法都是由Servlet容器進行調用
1)構造器(constructor):只被調用一次。只有第一次請求Servlet時,創建Servlet實例,調用構造器。這說明Servlet是單實例的(存在線程安全問題,不應創建全局變量)
2)init:只被調用一次。創建好實例後立即被調用,用於初始化Servlet。
3)service:被多次調用。每次請求都會調用service方法。實際用於響應請求。
4)destroy:只被調用一次。當前Servlet所在的WEB應用被卸載前調用,用於釋放當前Servlet所佔用的資源。
5)Servlet方法調用的過程:
(1)Servlet引擎檢查是否已經裝載並創建了該Servlet的實例對象。如果是,則直接執行第④步,否則,執行第②步。
(2)裝載並創建該Servlet的一個實例對象:調用該 Servlet 的構造器
(3)調用Servlet實例對象的init()方法。
(4)創建一個用於封裝請求的ServletRequest對象和一個代表響應消息的ServletResponse對象,然後調用Servlet的service()方法並將請求和響應對象作爲參數傳遞進去。
(5)WEB應用程序被停止或重新啓動之前,Servlet引擎將卸載Servlet,並在卸載之前調用Servlet的destroy()方法。
3.load-on-startup參數
1)配置在<Servlet></Servlet>節點中
<servlet>
<!-- Servlet的註冊名 -->
<servlet-name>helloServlet</servlet-name>
<!-- Servlet的全類名 -->
<servlet-class>com.zhaoliang.javaweb.HelloServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
2)作用:load-on-startup可以指定Servlet被創建的時機。若爲負數,則在第一次請求時被創建。若爲0或正數,則在當前WEB應用被Servlet容器加載時創建實例,且數值越小越早被創建。
4.<servlet-mapping></servlet-mapping>
1)同一個Servlet可以被映射到多個URL上,即多個<servlet-mapping>元素的<servlet-name>子元素的設置值可以是同一個Servlet的註冊名。
2)在Servlet映射到的URL中也可以使用 * 通配符,但是只能有兩種固定的格式:一種格式是“*.擴展名”,另一種格式是以正斜槓(/)開頭並以“/*”結尾。
<!-- 映射Servlet -->
<servlet-mapping>
<!-- 與某一個Servlet的註冊名一致 -->
<servlet-name>helloServlet</servlet-name>
<!-- 映射具體的訪問路徑:/代表當前項目的根目錄 -->
<url-pattern>/*</url-pattern>
</servlet-mapping>
或者
<!-- 映射Servlet -->
<servlet-mapping>
<!-- 與某一個Servlet的註冊名一致 -->
<servlet-name>helloServlet</servlet-name>
<!-- 映射具體的訪問路徑:/代表當前項目的根目錄 -->
<url-pattern>*.html</url-pattern>
</servlet-mapping>
5.ServletConfig:封裝了Servlet配置信息,獲取ServletContext對象(init方法中的參數)
1)配置Servlet初始化參數
<!-- 配置Servlet -->
<servlet>
<!-- Servlet的註冊名 -->
<servlet-name>helloServlet</servlet-name>
<!-- Servlet的全類名 -->
<servlet-class>com.zhaoliang.javaweb.HelloServlet</servlet-class>
<!-- 配置Servlet初始化參數,該節點必須放在loa-on-startup節點之前 -->
<init-param>
<!-- 參數名 -->
<param-name>user</param-name>
<!-- 參數值 -->
<param-value>root</param-value>
</init-param>
<init-param>
<param-name>password</param-name>
<param-value>1230</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
2)獲取初始化參數
>getInitParameter(String name):返回String,獲取指定參數名的初始化參數
>getInitParameterNames():返回
Enumeration
,返回參數名。
@Override
public void init(ServletConfig arg0) throws ServletException {
System.out.println("init");
String user = arg0.getInitParameter("user");
System.out.println("user:" + user);
System.out.println("========");
Enumeration names = arg0.getInitParameterNames();
while(names.hasMoreElements()){
String name = (String) names.nextElement();
System.out.println("name:" + name);
}
String servletName = arg0.getServletName();
System.out.println("========");
System.out.println("servletname : " + servletName);
}
3)ServletContext對象
(1)可以有 ServletConfig 的 getServletContext 方法獲得
(2)該對象代表當前WEB應用,可以認爲ServletContext是WEB應用的一個大管家,可以獲取當前WEB應用的各個信息。
①獲取當前WEB應用的初始化參數
首先,需要設置WEB應用的初始化參數(注意:<context-param>與<init-param>的區別:<context-param>是全局的初始化參數,所有的Servlet都可以訪問獲取,而<init-param>是局部的初始化參數,只有特定的(HelloServlet)可以獲取
<!-- 配置當前WEB應用初始化參數(全局的,所有的Servlet都可以獲取 -->
<context-param>
<param-name>driver</param-name>
<param-value>com.mysql.jdbc.driver</param-value>
</context-param>
<context-param>
<param-name>jdbcURL</param-name>
<param-value>jdbc:mysql///zhaoliang</param-value>
</context-param>
方法:
>getInitParameter(String name):返回String,獲取指定參數名的初始化參數
>getInitParameterNames():返回
Enumeration
,返回參數名。
@Override
public void init(ServletConfig arg0) throws ServletException {
System.out.println("init");
ServletContext servletContext = arg0.getServletContext();
String driver = servletContext.getInitParameter("driver");
System.out.println("driver : " + driver);
System.out.println("=============");
Enumeration<String> names = servletContext.getInitParameterNames();
while(names.hasMoreElements()){
String name = names.nextElement();
String value = servletContext.getInitParameter(name);
System.out.println("name :" + name + "--> value : " + value);
}
}
②獲取當前 WEB 應用的某一個文件在服務器上的絕對路徑(必須是在webContent文件夾下),而不是部署前的路徑
getRealPath(String path)
③獲取當前 WEB 應用的名稱
getContentPath()
getResourceAsStream(String path) : path / 相對於當前應用的根目錄
⑤和Attribute相關的四個方法
getAttribute(String name) ,getAttributeNames(),removeAttribute(String name),setAttribute(String name,Object object)
@Override
public void init(ServletConfig arg0) throws ServletException {
System.out.println("init");
ServletContext servletContext = arg0.getServletContext();
String realPath = servletContext.getRealPath("hello.jsp");
System.out.println("realPath :" + realPath);
String contextPath = servletContext.getContextPath();
System.out.println("contextPath :" + contextPath);
InputStream is = servletContext.getResourceAsStream("/hello.jsp");
System.out.println("stream :" + is);
}
3.GET 和POST
1.使用 GET 方式傳遞參數
1)在瀏覽器地址欄中輸入某個URL地址或單擊網頁上的一個超鏈接時,瀏覽器發出的HTTP請求消息的請求方式爲GET。
2)如果網頁中的<form>表單元素的method屬性被設置爲了“GET”,瀏覽器提交這個FORM表單時生成的HTTP請求消息的請求方式也爲GET。
3)使用GET請求方式給WEB服務器傳遞參數的格式:
http://www.lampbrother.net/counter.jsp?name=lc&password=123
4)使用GET方式傳送的數據量一般限制在1KB以下。
2.使用 POST 方式傳遞參數
1)POST請求方式主要用於向WEB服務器端程序提交FORM表單中的數據。 form 表單的 method 設置爲 POST
2)POST方式將各個表單字段元素及其數據作爲HTTP消息的實體內容發送給WEB服務器,傳送的數據量要比使用GET方式傳送的數據量大得多。
3)POST請求消息的格式:
POST /counter.jsp HTTP/1.1
referer: http://localhost:8080/Register.html
content-type: application/x-www-form-urlencoded
host: localhost:8080
content-length: 43
name=zhangsan&password=123
3.如何在Servlet中獲取請求參數
1)Servlet的 service() 用於應答請求,每次請求都會調用 service() 方法
public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException
>ServletRequest:封裝了請求信息,從中可以獲取任何請求信息
>ServletResponse:封裝了響應信息,如果想給用戶什麼響應,可以通過ServletResponse的相關方法實現。
這兩個接口的實現類都是服務器給予實現的,並在服務器調用 service 方法時傳入
2)ServletRequest:封裝了請求信息,從中可以獲取任何請求信息
(1)獲取請求參數
>String getParameter(String name):根據請求參數的名字,返回參數值
>String[] getParameterValues(String name):根據請求參數名字,返回一組參數值(多選checkbox)
>Enumeration getParameterNames():類似於ServletConfig(ServletContext)的 getInitParameterNames()
>Map getParameterMap():返回請求參數的鍵/值對,鍵-->參數名 值-->String數組類型
頁面信息(login.html)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="LoginServlet" method="post">
user:<input type="text" name="user"/>
password:<input type="password" name="password"/>
<br><br>
interesting:
<input type="checkbox" name="interesting" value="reading"/>reading
<input type="checkbox" name="interesting" value="watchingTV"/>watchingTV
<input type="checkbox" name="interesting" value="sport"/>sport
<input type="checkbox" name="interesting" value="game"/>game
<br><br>
<input type="submit" value="submit"/>
</form>
</body>
</html>
Servlet信息(LoginServlet)
import java.io.IOException;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Map;
import java.util.Map.Entry;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class LoginServlet implements Servlet {
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public ServletConfig getServletConfig() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getServletInfo() {
// TODO Auto-generated method stub
return null;
}
@Override
public void init(ServletConfig arg0) throws ServletException {
// TODO Auto-generated method stub
}
@Override
public void service(ServletRequest request, ServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
System.out.println("請求來了...");
System.out.println();
String user = request.getParameter("user");
String password = request.getParameter("password");
System.out.println("!!!" + user + "," + password);
System.out.println();
String[] interestings = request.getParameterValues("interesting");
for(String interest:interestings){
System.out.println("@@@" + interest);
}
System.out.println();
Enumeration<String> names = request.getParameterNames();
while(names.hasMoreElements()){
String name = names.nextElement();
String value = request.getParameter(name);
System.out.println("###" + name + "," + value);
}
System.out.println();
Map<String,String[]> paraMap = request.getParameterMap();
for(Map.Entry<String, String[]> entry :paraMap.entrySet()){
System.out.println("$$$" + entry.getKey() + ":" + Arrays.asList(entry.getValue()));
}
}
}
(2)HttpServletRequest:是ServletRequest的子接口,針對HTTP所定義,裏面包含了大量獲取HTTP請求信息的相關方法。
> HttpServletRequest httpServletRequest = (HttpServletRequest) request;
> getRequestURI():獲取請求URL
> getMethod():獲取請求方法
>getQueryString():獲取GET請求 ? 後的字符串
>getServletPath():獲取Servlet的映射路徑
>和Attribute相關的方法:
3)ServletResponse:封裝了響應信息,如果想給用戶什麼響應,可以通過ServletResponse的相關方法實現
(1)getWriter():返回 PrintWriter 對象,調用該對象的 print() 方法,將print()中的內容直接打印到客戶的瀏覽器上。
(2)getContentType(String contentTypeNmae):設置響應內容類型
(3)getOutputStream():返回OutputStream對象,下載圖片,word文檔時可以用到
(4)void sendRedirect(String location):請求重定向。此方法爲HttpServletResponse中定義(HttpServletResponse httpServletResponse = (HttpServletResponse) response;
綜合練習:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<!--
在web.xml文件中設置兩個WEB應用初始化參數:user,password。
定義一個login.html,裏邊定義兩個請求字段:user,password,發送請求到loginServlet
創建LoginServlet,在其中獲取請求參數user,password,對比web.xml中的參數是否一致
若一致,輸出hello XXX;若不一致,輸出 sorry XXX
-->
<form action="loginServlet" method="post">
user:<input type="text" name="user"/>
password:<input type="password" name="password"/>
<input type="submit" value="submit"/>
</form>
</body>
</html>
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>day_02</display-name>
<context-param>
<param-name>user</param-name>
<param-value>Tom</param-value>
</context-param>
<context-param>
<param-name>password</param-name>
<param-value>123456</param-value>
</context-param>
<servlet>
<servlet-name>loginServlet</servlet-name>
<servlet-class>com.zhaoliang.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>loginServlet</servlet-name>
<url-pattern>/loginServlet</url-pattern>
</servlet-mapping>
</web-app>
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class LoginServlet implements Servlet {
private ServletContext servletContext = null;
@Override
public void service(ServletRequest request, ServletResponse response)
throws ServletException, IOException {
String userClient = request.getParameter("user");
String passwordClient = request.getParameter("password");
String userService = null;
String passwordService = null;
if(servletContext != null){
userService = servletContext.getInitParameter("user");
passwordService = servletContext.getInitParameter("password");
}
PrintWriter printWriter = response.getWriter();
if(userService.equals(userClient) && passwordService.equals(passwordClient)){
printWriter.println("hello: " + userService);
}else{
printWriter.println("sory: " + userClient);
}
}
@Override
public void destroy() {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void init(ServletConfig servletConfig) throws ServletException {
servletContext = servletConfig.getServletContext();
}
}
4.GenericServlet
1)是一個Servlet,是Servlet接口和ServletConfig接口的實現類,但是一個抽象類,其中service方法爲抽象方法
2)如果新建的Servlet程序直接繼承GenericServlet,會使開發變得很簡潔
3)具體實現
(1)在 GenericServlet 中,定義一個ServletConfig類型的對象,並在init(ServletConfig arg0)中爲其初始化
(2)利用ServletConfig 成員變量的方法實現了ServletConfig接口的方法
(3)還定義了一個init()方法,在init(ServletConfig)方法中對其進行調用,子類可以直接覆蓋init()方法,在其中實現對Servlet的初始化
(4)不建議直接覆蓋init(ServletConfig),如果忘記編寫super(ServletConfig),而且還用了ServletConfig接口方法,會出現空指針異常。
(5)init()不是Servlet的生命週期方法,而init(ServletConfig)纔是生命週期方法
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public abstract class MyGenericServlet implements Servlet,ServletConfig {
/*
* Servlet接口的方法實現
*/
@Override
public void destroy() {}
@Override
public ServletConfig getServletConfig() {
return servletConfig;
}
@Override
public String getServletInfo() {
return null;
}
private ServletConfig servletConfig;
@Override
public void init(ServletConfig arg0) throws ServletException {
this.servletConfig = arg0;
init();
}
//重載初始化方法,用戶可以自行初始化,而沒有空指針錯誤
public void init() throws ServletException {}
@Override
public abstract void service(ServletRequest arg0, ServletResponse arg1)
throws ServletException, IOException;
/*
* ServletConfig接口方法的實現
*/
@Override
public String getInitParameter(String arg0) {
return servletConfig.getInitParameter(arg0);
}
@Override
public Enumeration getInitParameterNames() {
return servletConfig.getInitParameterNames();
}
@Override
public ServletContext getServletContext() {
return servletConfig.getServletContext();
}
@Override
public String getServletName() {
return servletConfig.getServletName();
}
}
5.HttpServlet
1)是一個Servlet,繼承自GenericServlet,針對於HTTP協議定製
2)在service方法中直接把ServletRequest和ServletResponse轉爲HttpServletRequest和HttpServletResponse,並調用了重載的service(HttpServletRequest,HttpServletResponse)。在service(HttpServletRequest,HttpServletResponse)中獲取了請求方式 request.getMethod(),根據請求方式創建了doXXX(xxx爲具體的請求方式,比如GET,POST)方法。
3)實際開發中,直接繼承HttpServlet,根據請求方式調用doXXX方法
4)直接有針性的覆蓋doXXX方法,直接使用HttpServletRequest和HttpServletResponse對象不需要強轉。
5)Servlet的關係圖
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import sun.awt.HToolkit;
public class MyHttpServlet extends MyGenericServlet {
@Override
public void service(ServletRequest arg0, ServletResponse arg1)
throws ServletException, IOException {
HttpServletRequest request;
HttpServletResponse response;
try {
request = (HttpServletRequest) arg0;
response = (HttpServletResponse) arg1;
} catch (ClassCastException e) {
throw new ServletException("non-Http request or response");
}
service(request, response);
}
public void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1.獲取請求方式
String method = request.getMethod();
//2.根據請求方式在創建對應的處理方法
if("GET".equalsIgnoreCase(method)){
doGet(request,response);
}
if("POST".equalsIgnoreCase(method)){
doPost(request,response);
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException{
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException{
}
}
6.綜合練習
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<!--
在web.xml文件中設置兩個WEB應用初始化參數:user,password。
定義一個login.html,裏邊定義兩個請求字段:user,password,發送請求到loginServlet
創建LoginServlet,在其中獲取請求參數user,password,對比web.xml中的參數是否一致
若一致,輸出hello XXX;若不一致,輸出 sorry XXX
-->
<form action="loginServlet" method="post">
user:<input type="text" name="user"/>
password:<input type="password" name="password"/>
<input type="submit" value="submit"/>
</form>
</body>
</html>
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>day_02</display-name>
<servlet>
<servlet-name>loginServlet</servlet-name>
<servlet-class>com.zhaoliang.servlet.LoginServlet3</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>loginServlet</servlet-name>
<url-pattern>/loginServlet</url-pattern>
</servlet-mapping>
</web-app>
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.Format;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.ws.Response;
public class LoginServlet3 extends HttpServlet {
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String username = req.getParameter("user");
String password = req.getParameter("password");
Connection connection = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
String sql = "select count(id) from test_users where name = ?"
+ "and password = ?";
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql:///zhaoliang";
String user = "root";
String password2 = "123456";
connection = DriverManager.getConnection(url, user, password2);
ps = connection.prepareStatement(sql);
ps.setString(1, username);
ps.setString(2, password);
rs = ps.executeQuery();
PrintWriter pWriter = resp.getWriter();
if(rs.next()){
int count = rs.getInt(1);
pWriter.println(count);
if(count > 0){
pWriter.println("hello : " + username);
}else{
pWriter.println("sorry : " + username);
}
}
} catch (Exception e) {
e.printStackTrace();
}finally{
if(rs != null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(ps != null){
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(connection != null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}