什麼是ServletContext對象
ServletContext代表是一個web應用的環境(上下文)對象,ServletContext對象內部封裝是該web應用的信息ServletContext對象一個web應用只有一個,一個web應用可以有多個servlet對象,但卻只有一個servletConetext的對象
servletContext的生命週期
創建:該web應用被加載服務器啟動或發佈web應用,前提是服務器啟動狀態
銷燬:web應用被卸載(服務器關閉,移除該web應用)
獲取servletContext對象
方式一ServletContext servletContext = config.getServletContext();
方式二ServletContext servletContext = this.getServletContext();
方式二可以省略this,在httpServlet的doget和dopost下
其實方式二的內部隱藏操作就是方式一
ServletContext的作用
1獲得web應用全局的初始化參數(web.xml中配置初始化參數)
代碼為:
2獲得web應用中任何資源的絕對路徑
上面有三個文件a.txt,b.txt,c.txt,d.txt這四個配置文件中其中a.txt在WebContent下,b.txt在WebContent>web-inf下,c.txt在src下,d.txt在web13這個總應用下,configContext能夠通過自身方法獲取這些文件在磁盤的絕對路徑
在演示之前,要說明一下,web13發佈運行之後,在tomcat下找到這個應用內部只有webContent內的東西,還有src下的東西全部到了webapps\WWW\WEB-INF\classes的這個classes下,剩下的其它位置的東西不會i在webapps中了,比如上面的d.txt這個文件,因為他沒有在上面兩個位置,所以它不會到webapps中了,所以我們第一通過瀏覽器訪問不到它,第二通過ServletContext的獲取絕對路徑的方式也獲取不到,也就是說像d.txt寫在這樣位置,基本在web應用中沒有意義
我們使用context.getRealPath("文件相對路徑")的方式獲取文件絕對路徑,這個文件相對路徑是相對webContent來說的,這點很重要,至於開頭用不用/開頭都行,因為類加載器不用,所以這裡也不用,以免混亂
獲得a.txt
String realPath_A = context.getRealPath("a.txt");
System.out.println(realPath_A);
文件相對路徑a.txt指的是應用webContent下的a。txt
獲得b.txt
String realPath_B = context.getRealPath("WEB-INF/b.txt");
System.out.println(realPath_B);
WEB-INF/b.txt指的是webContent下的WEB-INF/b.txt
獲得c.txt
String realPath_C = context.getRealPath("WEB-INF/classes/c.txt");
System.out.println(realPath_C);
因為這個在src下,那麼src下的c。txt在web應用運行之後它會到WEB-INF/classes下,所以路徑就是WEB-INF/classes/c.txt
獲得d.txt----獲取不到,這個寫的路徑沒有意義
在讀取src(classes) 下的資源可以使用類加載的方式來完成,這也是常用方式,只能是src(classes) 下
getResource() 參數是一個相對地址相對classes,這個不是相對webContent來說的來說的
String path = ContextServlet.class.getClassLoader().getResource("c.txt").getPath();
System.out.println(path);
c.txt在classses下所以路徑是c.txt
代碼
結果
可以看出類加載器和使用ServletContext所獲取到的東西是一樣的
ServletContext是一個域對象
它可以存儲數據,所以可以說它是域對象
ServletContext域對象的作用範圍:整個web應用
所有的web資源都可以隨意向 servletcontext域中存取數據,數據可以共享,它可以作為所有web資源的橋樑,通過他互相傳遞數據
域對象的通用的方法:所有域對象都有這三個方法
setAtrribute(String name,Object obj);
getAttribute(String name);
removeAttribute(String name);
因為它可以存儲數據共享數據所以應用很多地方
案例記錄用戶登陸次數
package com.itheima.login;
import java.io.IOException;
import java.sql.SQLException;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import com.itheima.domain.User;
import com.itheima.utils.DataSourceUtils;
public class LoginServlet extends HttpServlet {
@Override
public void init() throws ServletException {
//在Seveltcontext域中存一個數據count
int count = 0;
this.getServletContext().setAttribute("count", count);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
String sql = "select * from user where username=? and password=?";
User user = null;
try {
user = runner.query(sql, new BeanHandler
(User.class), username,password); } catch (SQLException e) {
e.printStackTrace();
}
if(user!=null){
ServletContext context = this.getServletContext();
Integer count = (Integer) context.getAttribute("count");
count++;
response.getWriter().write(user.toString()+"---you are success login person :"+count);
context.setAttribute("count", count);
}else{
response.getWriter().write("sorry your username or password is wrong");
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
這個代碼的意思就是說應用運行的時候先運行init方法,這個方法內部創建一個servletContext,然後方法內部是將count存入,因為init只運行一次所以起到了初始化的效果,之後dopost方法中只要表單提交數據就運行這個方法,這個只要用戶密碼輸入正確,就從servletContext從出count++,顯示然後在存入
這裡有一個問題,初始話,不是先運行init(ServletConfig)嗎,那為什麼這裡沒有參數的先運行,其實在httpservlet的父類的父類有init(ServletConfig)方法的,那個確實是入口的,但是它的內部調用的是init(),這個無參的,也就是說init(參數)調用init(),只要我們寫init()這個無參的也基本能起到先運行
閱讀更多 幻風的編程日記 的文章