看視訊自學Servlet
阿新 • • 發佈:2019-01-29
(一)如何建立一個Servlet
1.繼承 GenericServlet
程式碼:
public class ServletDemo1 extends GenericServlet{
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
res.getOutputStream().write("Hello servlet!".getBytes());
}
}
web.xml中配置
<servlet>
<servlet-name>ServletDemo1</servlet-name>
<servlet-class>com.boom.servlet.ServletDemo1</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>ServletDemo1</servlet-name>
<url-pattern>/ServletDemo1</url-pattern>
</servlet-mapping>
2.繼承 HttpServlet
程式碼:
public class ServletDemo2 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getOutputStream().write("Hello HttpServlet!".getBytes());
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
web.xml
<servlet>
<description></description>
<display-name>ServletDemo2</display-name>
<servlet-name>ServletDemo2</servlet-name>
<servlet-class>com.boom.servlet.ServletDemo2</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletDemo2</servlet-name>
<url-pattern>/ServletDemo2</url-pattern>
</servlet-mapping>
(二)用new 鍵 新建Servlet 包含(init方法,destory方法),web.xml檔案就不需要配置了
程式碼:
public class ServletDemo3 extends HttpServlet {
//servlet 方法只 呼叫一次
@Override
public void init() throws ServletException {
// TODO Auto-generated method stub
super.init();
System.out.println("init");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getOutputStream().write("Hello HttpServlet!".getBytes());
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
@Override
public void destroy() {
System.out.println("destroy");
}
}
web.xml不用配置了
(三)執行緒安全問題1.靜態變數的使用導致執行緒安全問題,靜態變數儘量少使用
程式碼:
/**
* 執行緒安全出現在多個執行緒操作同一資源上,就是靜態的使用要慎重
* @author Boom
*
*/
public class Person {
//如果不是靜態變數的時候,當多個執行緒使用時用到的age是不同的,不會有執行緒安全
public int age;
//如果是靜態變數,因為靜態變數在類載入的時候都會建立,每個執行緒都是用到同一個物件,當同一個物件被多個執行緒使用時,就會產生執行緒併發事件
// public static int age;
//在開發中,用靜態要小心,可能會造成記憶體奔潰
public List list = new ArrayList();
//public static List list = new ArrayList();
}
/**
* 執行緒安全
* @author Boom
*
*/
public class Demo {
//假設100個執行緒跑這個方法,看age的狀態
public static void main(String[] args) {
Person person = new Person();
person.age++;
//person.list.add("aaa");
System.out.println(person.age);
}
}
2.實現SingleThreadModel介面解決執行緒安全問題
程式碼:
/**
* 在web開發中,我們不用同步程式碼塊去解決併發事件,而是通過實現一個介面SingleThreadModel(不太建議),就是打個標記
* 這種介面叫做標記介面,同理的有序列化介面,就是標記這個類有特權
* @author Boom
* Servlet就像一個網頁,當出錯了,我們就要抓起來
*/
public class ServletDemo5 extends HttpServlet implements SingleThreadModel {
/**
* 執行緒安全問題
*/
//在這裡初始化資料會出現併發事件
int i=0;
//子類在覆蓋父類的方法,不能丟擲比父類更多的異常 (子類要比父類強,形象的說就是父親做東西丟擲了異常,子類又要比父類強我們就不能在子類拋更多的異常)
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
i++;
try {
Thread.sleep(1000*4);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//String.getBytes(); 把字串輸入到位元組流中
response.getOutputStream().write((i+"").getBytes());
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
3.用同步程式碼塊synchronized(this){}解決執行緒安全問題
程式碼:
public class ServletDemo4 extends HttpServlet {
/**
* 執行緒安全問題
*/
int i=0;
//在這裡初始化資料會出現併發事件
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//假設100個人同時操作這個dOGet()方法 ,會不會出現併發問題
//在方法內部定義初始化不會出現執行緒併發事件
//int i=0;
//同步程式碼塊,單執行緒執行
//用執行緒鎖解決執行緒併發問題,但是這種方法不行,如果一個執行緒正在訪問一個資源,而另一個也要等第一個執行緒訪問完才執行獲取資源
synchronized(this){
i++;
try {
Thread.sleep(1000*4);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//String.getBytes(); 把字串輸入到位元組流中
response.getOutputStream().write((i+"").getBytes());
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
(四)ServletConfig
/**
* ServletConfig
* 在配置檔案中定義資料,在java中獲取(使用情況:在實際開發中,有些資料不適合在servlet中寫死,這類資料就可以通過配置方式配置給servlet,
* 例如:servlet採用哪個碼錶,servlet連線哪個庫,servlet就配置哪個配置檔案)
* @author Boom
* 其實,struts就是一個特殊的servlet
*/
public class ServletDemo6 extends HttpServlet {
//方法一
/* private ServletConfig servletConfig;
@Override
public void init(ServletConfig config) throws ServletException {
this.servletConfig=config;
String value = servletConfig.getInitParameter("data");
System.out.println(value);
}*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//String value = servletConfig.getInitParameter("data"); 方法一
//方法二
String value = this.getServletConfig().getInitParameter("data");//得到指定的
Enumeration em = this.getServletConfig().getInitParameterNames();
while (em.hasMoreElements()) {
String name = (String) em.nextElement();
String value1 = this.getServletConfig().getInitParameter(name);
System.out.println(name+"="+value);
}
System.out.println(value);
response.getOutputStream().write("Hello HttpServlet!".getBytes());
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
(五)ServletContext
/**
* ServletContext 以及ServletDemo8 多個servlet之間傳值(相當於聊天室)示例
* @author Boom
* ServletContext說的就是整個應用程式的範圍 在多個servlet中共享資料
*/
public class ServletDemo7 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//得到ServletContext的方式一:
ServletContext context = this.getServletConfig().getServletContext();
//得到ServletContext的方式二:
//ServletContext context1 = this.getServletContext();
String data="aaa";
context.setAttribute("data",data);
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
(六)使用ServletContext 多個servlet之間傳值
/**
* 多個servlet之間傳值(相當於聊天室)
* @author Boom
*
*/
public class ServletDemo8 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//應用場景 之前給每個servlet都配置資料連線,我們可以直接通過context域配置資料庫連線
String value1 =this.getServletContext().getInitParameter("data1");
String value = (String) this.getServletContext().getAttribute("data");
System.out.println(value);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
(七)Servlet中不適合對資料進行輸出,我們要應用Servlet的轉發
/**
* Servlet中不適合對資料進行輸出,我們要應用Servlet的轉發
* @author Boom
* ServletDemo9和ServletDemo10
*/
public class ServletDemo9 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String value =this.getServletContext().getInitParameter("data1");
//Servlet資料輸出比較麻煩,我們通過轉發來實現 讓jsp實現
// servlet的重定向是讓他自己去做
// Servlet的轉發是讓我來幫他找人做
response.getOutputStream().write(("<font color='red'>"+value+"</font>").getBytes());
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
(八)同過servletcontext實現請求轉發,每個web應用都有一個servletcontext
/**
* 同過servletcontext實現請求轉發,每個web應用都有一個servletcontext
* Servlet的轉發 ServletDemo9和ServletDemo10
* @author Boom
* 轉發物件 RequestDispatcher
*/
public class ServletDemo10 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String data="aaaaa";
this.getServletContext().setAttribute("dt", data); //不能放在context域中,為什麼呢?(涉及多執行緒問題,就是用的是同一物件,會覆蓋資料)
//把資料放到context域物件中,並轉發給jsp去實現介面
RequestDispatcher rd= this.getServletContext().getRequestDispatcher("/1.jsp");
rd.forward(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
(九)讀取資原始檔
1.通過ServletContext訪問資原始檔 db.propertis
/**
* 讀取資原始檔 通過ServletContext訪問資原始檔 db.propertis
*
* @author Boom
*
*/
public class ServletDemo11 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
test5();
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
//在專案的相對路徑src下新建db.properties檔案
public void test1() throws IOException {
InputStream in = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
// 固定套路 (把流輸出到properties中)
Properties properties = new Properties();
properties.load(in);
String url = properties.getProperty("url");
String username = properties.getProperty("username");
String password = properties.getProperty("password");
System.out.println(url);
System.out.println(username);
System.out.println(password);
}
//在com.boom.thread包下新建db.properties檔案
public void test2() throws IOException {
InputStream in = this.getServletContext().getResourceAsStream("/WEB-INF/classes/com/boom/thread/db.properties");
// 固定套路 (把流輸出到properties中)
Properties properties = new Properties();
properties.load(in);
String url = properties.getProperty("url");
String username = properties.getProperty("username");
String password = properties.getProperty("password");
System.out.println(url);
System.out.println(username);
System.out.println(password);
}
//在WEB-INF下新建db.properties檔案
public void test3() throws IOException {
InputStream in = this.getServletContext().getResourceAsStream("/db.properties");
// 固定套路 (把流輸出到properties中)
Properties properties = new Properties();
properties.load(in);
String url = properties.getProperty("url");
String username = properties.getProperty("username");
String password = properties.getProperty("password");
System.out.println(url);
System.out.println(username);
System.out.println(password);
}
//讀取資原始檔需要注意的問題(但是我們得在tomcat的bin檔案考入檔案db.properties,才能實現) 最好採用servletcontext來讀取資原始檔
public void test4() throws IOException {
FileInputStream in = new FileInputStream("classes/db.properties");
// 固定套路 (把流輸出到properties中)
Properties properties = new Properties(); //map
properties.load(in);
String url = properties.getProperty("url");
String username = properties.getProperty("username");
String password = properties.getProperty("password");
System.out.println(url);
System.out.println(username);
System.out.println(password);
}
public void test5() throws IOException{
String path = this.getServletContext().getRealPath("/WEB-INF/classes/db.properties");
String filename=path.substring(path.lastIndexOf("\\")+1);
System.out.println(filename);
FileInputStream in=new FileInputStream(path);
// 固定套路 (把流輸出到properties中)
Properties properties = new Properties(); //map
properties.load(in);
String url = properties.getProperty("url");
String username = properties.getProperty("username");
String password = properties.getProperty("password");
System.out.println(url);
System.out.println(username);
System.out.println(password);
}
}
2.如果讀取資原始檔的程式不是servlet的話,就只能通過類載入器去讀了
程式碼:
新建一個UserDao
/**
* 類裝載器
* 如果讀取資原始檔的程式不是servlet的話,就只能通過類裝載器去讀了
* @author Boom
*
*/
public class UserDao {
//把東西放到預編譯中,在類載入時就生成了,而且只有一次
private static Properties dbconfig = new Properties();
static{
try {
//針對如果修改了配置檔案中的資料,檢視執行後的輸出 方案一:無論檔案中怎麼改還是原來的
//以下程式碼雖然可以讀取資原始檔的資料,但是無法獲取更新後的資料
InputStream in = UserDao.class.getClassLoader().getResourceAsStream("db.properties");
//方案二:修改後,資料也跟著修改了
//String path = UserDao.class.getClassLoader().getResource("db.properties").getPath();
//FileInputStream inputStream = new FileInputStream(path);
//獲取檔案中的東西
dbconfig.load(in);
} catch (IOException e) {
//拋一個初始化錯誤
throw new ExceptionInInitializerError(e);
}
}
//不能傳入一個servletcontext物件,避免耦合
public void update() throws IOException {
System.out.println(dbconfig.getProperty("url"));
System.out.println(dbconfig.getProperty("username"));
System.out.println(dbconfig.getProperty("password"));
}
public void find(){
}
public void delete(){
}
/**
* 總結:讀取資原始檔
* 1.在servlet中,我們可以通過servletcontext去讀取資原始檔的資料
* 2.在其他類中,我們需要通過類載入器去讀取資原始檔的資料
*
*/
}
新建測試類
/**
* 如果讀取資原始檔的程式不是servlet的話,就只能通過類載入器去讀了
* @author Boom
*
*/
public class ServletDemo12 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
UserDao userdao =new UserDao();
userdao.update();
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}