Servlet開發基礎及MVC設計模式

一、Servlet介紹


Servlet本身只是普通的Java類,只有當容器爲他創建了ServletConfig和ServletContext時才成爲了一個Servlet;

Servlet簡單的說就是一個Java程序,目的和Javabean差不多,爲了使得JSP頁面中代碼簡潔、清晰;

JavaBean不需要配置,只需要放在WEB-INF/classes中即可;

Servlet也是放在 WEB-INF/classes/中,並在web.xml中配置如下形式:


[html] view plaincopy
  1. <servlet>  
  2. <servlet-name></servlet-name>  
  3. <servlet-class></servlet-class>  
  4. </servlet>  
  5. <servlet-mapping>  
  6. <servlet-name></servlet-name>  
  7. <url-pattern></url-pattern>  
  8. </servlet-mapping>  

如果需要設置配置信息,則需要形式如下:

[html] view plaincopy
  1. <servlet>  
  2. <servlet-name></servlet-name>  
  3. <servlet-class></servlet-class>  
  4. <init-param>  
  5. <param-name></param-name>  
  6. <param-value></param-value>  
  7. </init-param>  
  8.   
  9. </servlet>  
  10. <servlet-mapping>  
  11. <servlet-name></servlet-name>  
  12. <url-pattern></url-pattern>  
  13. </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容器啓動時自動加載;配置如下:

[html] view plaincopy
  1. <serlvet>  
  2.     <serlvet-name></servlet-name>  
  3.     <servlet-class></servlet-class>  
  4.     <load-on-startup>1</load-on-startup>  
  5. </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

[java] view plaincopy
  1. package org.vo;  
  2. public class User{  
  3.     private String id;  
  4.     private String name;  
  5.     private String password;  
  6.     public String getId(){  
  7.         return id;  
  8.     }  
  9.     public void setId(String id){  
  10.         this.id = id;  
  11.     }  
  12.     public String getName(){  
  13.         return name;  
  14.     }  
  15.     public void setName(String name){  
  16.         this.name = name;  
  17.     }  
  18.     public void setPassword(String password){  
  19.         this.password = password;  
  20.     }  
  21.     public String getPassword(){  
  22.         return password;  
  23.     }  
  24. }  

IUserDAO.java

[java] view plaincopy
  1. package org.dao;  
  2. import org.vo.*;  
  3. public interface IUserDAO{  
  4.     public boolean findLogin(User user)throws Exception;  
  5. }  


UserDAOImpl.java
[java] view plaincopy
  1. package org.dao.impl;  
  2. import java.sql.*;  
  3. import org.vo.*;  
  4. import org.dao.*;  
  5. public class UserDAOImpl implements IUserDAO{  
  6.     private Connection con;  
  7.     public UserDAOImpl(Connection con){  
  8.         this.con = con;  
  9.     }  
  10.     public boolean findLogin(User user)throws Exception{  
  11.         boolean flag = false;  
  12.         String sql = "SELECT name FROM user WHERE id=? AND password=?";  
  13.         PreparedStatement stat = con.prepareStatement(sql);  
  14.         stat.setString(1,user.getId());  
  15.         stat.setString(2,user.getPassword());  
  16.         ResultSet rs = stat.executeQuery();  
  17.         if(rs.next()){  
  18.             user.setName(rs.getString(1));  
  19.             flag = true;  
  20.         }  
  21.         return flag;  
  22.     }  
  23. }  

UserDAOProxy.java

[java] view plaincopy
  1. package org.dao.proxy;  
  2. import org.dao.*;  
  3. import org.vo.*;  
  4. import org.dao.impl.*;  
  5. import org.dbc.*;  
  6. public class UserDAOProxy implements IUserDAO{  
  7.     private DatabaseConnection dbc;  
  8.     private IUserDAO idao;  
  9.     public UserDAOProxy(){  
  10.         dbc = new DatabaseConnection();  
  11.         idao = new UserDAOImpl(dbc.getConnection());  
  12.     }  
  13.     public boolean findLogin(User user)throws Exception{  
  14.         if(user==null){  
  15.             return false;  
  16.         }  
  17.         boolean flag = idao.findLogin(user);  
  18.         dbc.close();  
  19.         return flag;  
  20.     }  
  21. }  

DatabaseConnection.java

[java] view plaincopy
  1. package org.dbc;  
  2. import java.sql.*;  
  3. public class DatabaseConnection{  
  4.     public static final String DRIVER = "com.mysql.jdbc.Driver";  
  5.     public static final String URL = "jdbc:mysql://localhost:3306/mldn";  
  6.     public static final String USER = "root";  
  7.     public static final String PASS = "123456";  
  8.     private Connection con;  
  9.     public DatabaseConnection(){  
  10.         try{  
  11.             Class.forName(DRIVER);  
  12.             con = DriverManager.getConnection(URL,USER,PASS);  
  13.         }  
  14.         catch(Exception e){}  
  15.     }  
  16.     public Connection getConnection(){  
  17.         return con;  
  18.     }  
  19.     public void close(){  
  20.         try{  
  21.             if(con!=null){  
  22.                 con.close();  
  23.             }  
  24.         }  
  25.         catch(Exception e){}  
  26.     }  
  27. }  

DAOFactory.java

[java] view plaincopy
  1. package org.factory;  
  2. import org.dao.*;  
  3. import org.dao.proxy.*;  
  4. public class DAOFactory{  
  5.     public static IUserDAO getInstance(){  
  6.         return new UserDAOProxy();  
  7.     }  
  8. }  

以上代碼是JavaBean部分;MVC的特點是用Servlet調用JavaBean,而不是JSP調用JavaBean;


2.Servlet部分


以下是Servlet部分:Servlet是接收客戶端請求,並調用JavaBean進行數據庫操作;並把結果通過設置request屬性傳給JSP進行顯示;(貫穿核心)

LoginServlet.java

[java] view plaincopy
  1. package org.servlet;  
  2. import java.util.*;  
  3. import javax.servlet.*;  
  4. import javax.servlet.http.*;  
  5. import org.factory.*;  
  6. import org.vo.*;  
  7. import java.io.*;  
  8. public class LoginServlet extends HttpServlet{  
  9.     public void doGet(HttpServletRequest req,HttpServletResponse resp)throws ServletException,IOException{  
  10.         String path = "login.jsp";  
  11.         String id = req.getParameter("id");  
  12.         String pass = req.getParameter("pass");  
  13.         List<String> info = new ArrayList<String>();  
  14.         if(id==null||"".equals(id)){  
  15.             info.add("id不能爲空");  
  16.         }  
  17.         if(pass==null||"".equals(pass)){  
  18.             info.add("密碼不能爲空");  
  19.         }  
  20.         if(info.size()==0){  
  21.             User user = new User();  
  22.             user.setId(id);  
  23.             user.setPassword(pass);  
  24.             try{  
  25.                 if(DAOFactory.getInstance().findLogin(user)==true){  
  26.                     info.add("歡迎光臨");  
  27.                 }  
  28.                 else{  
  29.                     info.add("錯誤的用戶名和密碼");  
  30.                 }  
  31.             }  
  32.             catch(Exception e){}  
  33.         }  
  34.         req.setAttribute("info",info);  
  35.         req.getRequestDispatcher(path).forward(req,resp);  
  36.     }  
  37.     public void doPost(HttpServletRequest req,HttpServletResponse resp)throws ServletException,IOException{  
  38.         this.doGet(req,resp);  
  39.     }  
  40. }  

Login.jsp

[java] view plaincopy
  1. <%@page contentType="text/html" pageEncoding="GBK" import="java.util.*"%>  
  2. <html>  
  3.     <head>  
  4.         <title>A</title>  
  5.     </head>  
  6.     <script language="Javascript">  
  7.         function validate(f){  
  8.             if(!(/^\w{5,15}$/.test(f.id.value))){  
  9.                 alert("id長度不對");  
  10.                 f.id.focus();  
  11.                 return false;  
  12.             }  
  13.             if(!(/^\w{5,15}$/.test(f.pass.value))){  
  14.                 alert("密碼長度不對");  
  15.                 f.pass.focus();  
  16.                 return false;  
  17.             }  
  18.             return true;  
  19.         }  
  20.     </script>  
  21.     <body>  
  22.         <h2>用戶登錄程序</h2>  
  23.         <%  
  24.             request.setCharacterEncoding("GBK");  
  25.             List<String> info = (List<String>)request.getAttribute("info");  
  26.             if(info!=null){  
  27.                 Iterator<String>iter = info.iterator();  
  28.                 while(iter.hasNext()){  
  29.         %>  
  30.                     <h4><%=iter.next()%></h4>  
  31.         <%  
  32.                 }  
  33.             }  
  34.         %>  
  35.         <form action="LoginServlet" method="post" onSubmit="return validate(this)">  
  36.         用戶ID:<input type="text" name="id"/><br />  
  37.         密碼:<input type="password" name="pass"/><br />  
  38.         <input type="submit" value="提交"/>  
  39.         </form>  
  40.     </body>  
  41. </html>  

數據庫腳本:

[java] view plaincopy
  1. CREATE TABLE user(  
  2.     id      varchar(30) PRIMARY KEY,  
  3.     name        varchar(30) ,  
  4.     password    varchar(30)  
  5. );  
  6. 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中通過類似:
[html] view plaincopy
  1. <context-param>  
  2.     <param-name></param-name>  
  3.     <param-value></param-value>  
  4.   </context-param>  
配置;
3.轉發
[java] view plaincopy
  1. context.getRequestDispatcher("/1.html").forward(request,response);  

4.獲取資源文件數據: 
[java] view plaincopy
  1. InputStream in = context.getResourceAsStream("*.properties");  
  2. Properties props = new Properties();  
  3. 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");是正確的;


轉載自:http://blog.csdn.net/xiazdong/article/details/6898774

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章