文章目錄
一、Servlet介紹Servlet本身只是普通的Java類,只有當容器為他建立了ServletConfig和ServletContext時才成為了一個Servlet;
Servlet簡單的說就是一個Java程式,目的和Javabean差不多,為了使得JSP頁面中代碼簡潔、清晰;
JavaBean不需要配置,只需要放在WEB-INF/classes中即可;
Servlet也是放在 WEB-INF/classes/中,並在web.xml中配置如下形式:
<servlet><servlet-name></servlet-name><servlet-class></servlet-class></servlet><servlet-mapping><servlet-name></servlet-name><url-pattern></url-pattern></servlet-mapping>
如果需要設定配置資訊,則需要形式如下:
<servlet><servlet-name></servlet-name><servlet-class></servlet-class><init-param><param-name></param-name><param-value></param-value></init-param></servlet><servlet-mapping><servlet-name></servlet-name><url-pattern></url-pattern></servlet-mapping>
注意:在url-pattern中,主目錄為:"/",而不是"\"!
Servlet可以處理用戶端傳來的請求,即request,並且可以返回給用戶端回應,即response,這個操作通過
(1)public void service(ServletRequest req,ServletResponse resp)throws ServletExeption,IOException{}
(2)public void doGet(HttpServletRequest req,HttpServletResponse resp)throws ServletExeption,IOException{}
(3)public void doPost(HttpServletRequest req,HttpServletResponse resp)throws ServletExeption,IOException{}
完成;
這裡需要注意的是service的參數只是ServletRequest,而其他兩個函數的參數是HttpServletRequest;
一般如果我們要自訂Servlet,則需要繼承HttpServlet類,並覆蓋相應的方法即可;
二、Servlet的結構 注意:(1)
一個Servlet類只有一個執行個體;(2)一個Servlet類只會調用一次init()方法;(3)Servlet的一生都是由Web容器所控制,即Web容器調用Servlet類的方法;(4)Servlet如果沒有Web容器,就是一個普通的Java類;
Servlet生命週期為:載入-->初始化--->服務--->銷毀--->卸載;
載入:web容器載入Servlet,即建立一個Servlet執行個體;
初始化:調用servlet的init方法,為了完成一些預備動作;
當請求到來時,
服務:建立一個request、response對象,並建立一個線程,調用類service方法;
銷毀:調用destroy()方法;當一個Servlet對象長時間不使用或web容器(tomcat)關閉時調用;
卸載:即退出;
繼承HttpServlet後,可以覆寫以下方法:
1.public void init(ServletConfig config)throws ServletException{} //初始化Servlet,(1)當需要使用Servlet時調用;(2)如果在web.xml中配置,則可以web容器啟動時自動載入;配置如下:
<serlvet><serlvet-name></servlet-name><servlet-class></servlet-class><load-on-startup>1</load-on-startup></servlet>
2.public void init(ServletConfig config)throws ServletExeption{} //初始化Servlet,可以得到配置資訊
3.public void doGet(HttpServletRequest req,HttpServletResponse resp)throws ServletExeption,IOException{} 當get方式傳遞,則調用此方法
4.public void doPost(HttpServletRequest req,HttpServletResponse resp)throws ServletExeption,IOException{}當post方法傳遞,則調用此方法
5.public void service(HttpServletRequest req,HttpServletResponse resp)throws ServletExeption,IOException{}
6.public void destroy(){} //銷毀時調用
注意:
1. 當1,2同時出現時,2有較高優先順序;
2. 當3或4和5同時出現時,5具有較高優先順序;
3 .PrintWriter writer = resp.getWriter();可以獲得輸出資料流;
注意:writer輸出時需要輸出HTML結構;
三、Servlet常見問題
1.在init方法中,通過config.getInitParameter()方法取得配置資訊;
2.req.getSession():取得Session對象;
3.super.getServletContext();取得application對象;因為GenericServlet中有getServletContext方法;
4.resp.getWriter()返回一個PrintWriter用以輸出文本資料、resp.getOutputStream()輸出位元據,並且兩者不能同時調用;
5.在init(ServletConfig config)方法中需要調用super.init(config);
6. 在service()方法中getServletConfig()返回 ServletConfig;
四、Servlet跳轉
1.用戶端跳轉:resp.sendRedirect("1.jsp") ; //類似於內建對象中的跳轉;
2.伺服器跳轉:req.getRequestDispatcher("/hello.jsp").forward(req,resp);能夠跳轉到hello.jsp中;
注意:用戶端跳轉和伺服器端跳轉的區別;
注意:這裡的getRequestDispatcher中的網頁一定要加“ / ”
五、MVC設計模式JAVA WEB中,有兩種設計模式:(1)MODE 1: DAO;(2)MODE 2: MVC;
在之前我們講過JSP+JAVABEAN的DAO開發模式,這個適用於小型開發;
MVC最早是由SmallTalk提出的;
Controller: Servlet 負責接收客戶請求並轉寄給Model;
Model :JavaBean 負責真正處理商務邏輯;
View:JSP 負責輸出結果;
EJB(Enterprise JavaBean);
MVC(Model View Control)是一種以Servlet為核心的開發模式,流程如下:
步驟如下:
1.用戶端發送請求給Servlet;
2.Servlet接收請求後處理,並可以調用JavaBean(即進行資料庫操作,並返回結果);
3.Servlet返回結果給JSP顯示;(通過設定request屬性後調用RequestDispatcher方法跳轉,並在JSP頁面中接收request屬性);
因此JSP只是用於顯示,而JavaBean只和Servlet通訊;
注意:在MVC中,使用requestDispatcher的機會很多,我們都是通過這個類進行伺服器跳轉的;
六、MVC執行個體
功能:登入功能
1.JavaBean部分
User.java
package org.vo;public class User{private String id;private String name;private String password;public String getId(){return id;}public void setId(String id){this.id = id;}public String getName(){return name;}public void setName(String name){this.name = name;}public void setPassword(String password){this.password = password;}public String getPassword(){return password;}}
IUserDAO.java
package org.dao;import org.vo.*;public interface IUserDAO{public boolean findLogin(User user)throws Exception;}
UserDAOImpl.java
package org.dao.impl;import java.sql.*;import org.vo.*;import org.dao.*;public class UserDAOImpl implements IUserDAO{private Connection con;public UserDAOImpl(Connection con){this.con = con;}public boolean findLogin(User user)throws Exception{boolean flag = false;String sql = "SELECT name FROM user WHERE id=? AND password=?";PreparedStatement stat = con.prepareStatement(sql);stat.setString(1,user.getId());stat.setString(2,user.getPassword());ResultSet rs = stat.executeQuery();if(rs.next()){user.setName(rs.getString(1));flag = true;}return flag;}}
UserDAOProxy.java
package org.dao.proxy;import org.dao.*;import org.vo.*;import org.dao.impl.*;import org.dbc.*;public class UserDAOProxy implements IUserDAO{private DatabaseConnection dbc;private IUserDAO idao;public UserDAOProxy(){dbc = new DatabaseConnection();idao = new UserDAOImpl(dbc.getConnection());}public boolean findLogin(User user)throws Exception{if(user==null){return false;}boolean flag = idao.findLogin(user);dbc.close();return flag;}}
DatabaseConnection.java
package org.dbc;import java.sql.*;public class DatabaseConnection{public static final String DRIVER = "com.mysql.jdbc.Driver";public static final String URL = "jdbc:mysql://localhost:3306/mldn";public static final String USER = "root";public static final String PASS = "123456";private Connection con;public DatabaseConnection(){try{Class.forName(DRIVER);con = DriverManager.getConnection(URL,USER,PASS);}catch(Exception e){}}public Connection getConnection(){return con;}public void close(){try{if(con!=null){con.close();}}catch(Exception e){}}}
DAOFactory.java
package org.factory;import org.dao.*;import org.dao.proxy.*;public class DAOFactory{public static IUserDAO getInstance(){return new UserDAOProxy();}}
以上代碼是JavaBean部分;MVC的特點是用Servlet調用JavaBean,而不是JSP調用JavaBean;
2.Servlet部分
以下是Servlet部分:Servlet是接收用戶端請求,並調用JavaBean進行資料庫操作;並把結果通過設定request屬性傳給JSP進行顯示;(貫穿核心)
LoginServlet.java
package org.servlet;import java.util.*;import javax.servlet.*;import javax.servlet.http.*;import org.factory.*;import org.vo.*;import java.io.*;public class LoginServlet extends HttpServlet{public void doGet(HttpServletRequest req,HttpServletResponse resp)throws ServletException,IOException{String path = "login.jsp";String id = req.getParameter("id");String pass = req.getParameter("pass");List<String> info = new ArrayList<String>();if(id==null||"".equals(id)){info.add("id不可為空");}if(pass==null||"".equals(pass)){info.add("密碼不可為空");}if(info.size()==0){User user = new User();user.setId(id);user.setPassword(pass);try{if(DAOFactory.getInstance().findLogin(user)==true){info.add("歡迎光臨");}else{info.add("錯誤的使用者名稱和密碼");}}catch(Exception e){}}req.setAttribute("info",info);req.getRequestDispatcher(path).forward(req,resp);}public void doPost(HttpServletRequest req,HttpServletResponse resp)throws ServletException,IOException{this.doGet(req,resp);}}
Login.jsp
<%@page contentType="text/html" pageEncoding="GBK" import="java.util.*"%><html><head><title>A</title></head><script language="Javascript">function validate(f){if(!(/^\w{5,15}$/.test(f.id.value))){alert("id長度不對");f.id.focus();return false;}if(!(/^\w{5,15}$/.test(f.pass.value))){alert("密碼長度不對");f.pass.focus();return false;}return true;}</script><body><h2>使用者登入程式</h2><%request.setCharacterEncoding("GBK");List<String> info = (List<String>)request.getAttribute("info");if(info!=null){Iterator<String>iter = info.iterator();while(iter.hasNext()){%><h4><%=iter.next()%></h4><%}}%><form action="LoginServlet" method="post" onSubmit="return validate(this)">使用者ID:<input type="text" name="id"/><br />密碼:<input type="password" name="pass"/><br /><input type="submit" value="提交"/></form></body></html>
資料庫指令碼:
CREATE TABLE user(idvarchar(30)PRIMARY KEY,namevarchar(30),passwordvarchar(30));INSERT INTO user VALUES('XIAZDONG','xiazdong','12345');
因此最後再強調一下Mode1和Mode2的區別:
Mode1是通過JSP調用JavaBean;Mode2是通過Servlet調用JavaBean;
Mode1在JSP中仍然有處理的部分,而Mode2中JSP只負責顯示;
補充:Servlet調用過程順序圖
ServletContext介紹
ServletContext對象在web伺服器啟動時建立,即在伺服器啟動時,為每個web應用建立一個ServletContext;1.獲得途徑: this.getServletContext() 可以取得 ServletContext 對象;2.獲得web應用的初始化參數: context.getInitParameter("...");在web.xml中通過類似:
<context-param> <param-name></param-name> <param-value></param-value> </context-param>
配置;
3.轉寄
context.getRequestDispatcher("/1.html").forward(request,response);
4.擷取資源檔資料:
InputStream in = context.getResourceAsStream("*.properties");Properties props = new Properties();props.load(in); 補充:web開發中地址書寫問題
地址書寫時常用到“/”開頭,而“/”有兩個宗旨:
1.面向瀏覽器,則"/"表示http://localhost:8080/
2.面向伺服器,則"/"表示當前web應用;
面向瀏覽器的意思是:是否會讓瀏覽器地址欄改變;其餘的都是面向伺服器;
在Servlet開發中會在以下幾種情況下存在地址書寫問題:1. request.getRequestDispatcher("地址A");
2.response.sendRedirect("地址B");3.this.getServletContext().getRealPath("地址C");4.this.getServletContext().getResourceAsStream("地址D");5.<a href="地址E">6.<form action="地址F"> 地址A:轉寄不會使瀏覽器地址欄改變,因此是面向伺服器的,“/”表示當前web應用;地址B:重新導向會使瀏覽器地址欄改變,因此是面向瀏覽器的;同樣分析,得出結果:A、C、D屬於面向伺服器;B、E、F屬於面向瀏覽器;
補充:在提供客戶發出請求之前的過程
1.從web.xml中讀出Servlet初始化參數和上下文初始化參數;
2.建立一個ServletConfig對象和ServletContext對象;
3.將Servlet初始化參數的引用賦給ServletConfig對象,把上下文初始化參數賦值給ServletContext對象;
4.建立ServletContextListener監聽器執行個體;
5.調用contextInitialized()方法;
6.建立這個Servlet執行個體;
7.調用init方法;
注意:
(1)在Servlet建構函式中還沒有ServletConfig對象,雖然能夠調用getServletConfig()方法;
(2)ServletConfig對象在Servlet執行個體建立之前就已經建立;
(3)web.xml的初始化參數只會讀一次,如果需要更新,則需要重新部署;
上下文初始化參數:整個web應用都能夠訪問的初始化參數;
<context-param>
<param-name>name</param-name>
<param-value>value</param-value>
</context-param>
getServletContext().getInitParameter("name")即可;
每個Servlet有一個ServletConfig,每個web應用有一個ServletContext;
如果web應用時分布式的,則每個JVM都有一個ServletContext;
注意:getAttribute()返回的是Object;
Person p = getServletContext().getAttribute("person");是錯誤的!!!!!!!!!!!!!!!!!!!!!
Person p = (Person)getServletContext().getAttribute("person");是正確的;