java第三十天(ServletContext、HTTPServletReaues、HTTPServletResponse、中文亂碼問題)

Servlet配置方式

1. 全路徑匹配

以 / 開始 /a /aa/bbhtml

localhost:8080/項目名稱/aa/bbjava

2. 路徑匹配 , 前半段匹配

以 / 開始 , 可是以 * 結束 /a/* /*mysql

  • 實際上是一個通配符,匹配任意文字

localhost:8080/項目名稱/aa/bbweb

3. 以擴展名匹配

寫法: 沒有/ 以 * 開始 *.擴展名 *.aa *.bbsql

ServletContext

Servlet 上下文數據庫

每一個web工程都只有一個ServletContext對象。 說白了也就是無論在哪一個servlet裏面,獲取到的這個類的對象都是同一個。apache

//1. 獲取對象
	ServletContext context = getServletContext();

做用數組

  1. 獲取全局配置參數
  2. 獲取web工程中的資源
  3. 存取數據,servlet間共享數據 域對象

能夠獲取全局配置參數

獲取全局參數瀏覽器

能夠獲取Web應用中的資源

1. 獲取資源在tomcat裏面的絕對路徑

	先獲得路徑,而後本身new InpuStream

		context.getRealPath("") //這裏獲得的是項目在tomcat裏面的根目錄。

		D:\tomcat\apache-tomcat-7.0.52\apache-tomcat-7.0.52\wtpwebapps\Demo03\
	
	 	String path = context.getRealPath("file/config.properties");

		D:\tomcat\apache-tomcat-7.0.52\apache-tomcat-7.0.52\wtpwebapps\Demo03\file\config.properties


2. getResourceAsStream 獲取資源 流對象

	直接給相對的路徑,而後獲取流對象。

經過classloader去獲取web工程下的資源

使用ServletContext存取數據。

  1. 定義一個登錄的html頁面, 定義一個form表單

  1. 定義一個Servlet,名爲LoginServlet
if (load==true) {
	int count=0;
	Object totalcount = getServletContext().getAttribute("count");
	if (totalcount!=null) {
		count=(int) totalcount;
	}
	getServletContext().setAttribute("count", count+1);
	System.out.println("登錄成功的次數是"+count+"次");
	//設置狀態碼從新定位
	response.setStatus(302);
	response.setHeader("Location", "load.html");//此處爲相對路徑
}
if (load==false) {
	response.getWriter().write("登錄失敗...");
}
  1. 針對成功或者失敗,進行判斷,而後跳轉到不同的網頁

細節:tomcat

<!-- 	
	A路徑: Servlet的路徑
		http://localhost:8080/Demo4/login
	
	B路徑: 當前這個html的路徑:
		http://localhost:8080/Demo4/login.html -->
	
	
	<form action="Login" method="get">
		帳號:<input type="text" name="username"/><br>
		密碼:<input type="text" name="password"/><br>
		<input type="submit" value="登陸"/>
	</form>

ServletContext 生命週期

服務器啓動的時候,會爲託管的每個web應用程序,建立一個ServletContext對象

從服務器移除託管,或者是關閉服務器。

  • ServletContext 的做用範圍

只要在這個項目裏面,均可以取。 只要同一個項目。 A項目 存, 在B項目取,是取不到的? ServletContext對象不一樣。

HttpServletRequest

這個對象封裝了客戶端提交過來的一切數據。

1. 能夠獲取客戶端請求頭信息

//獲得一個枚舉集合  
	Enumeration<String> headerNames = request.getHeaderNames();
	while (headerNames.hasMoreElements()) {
		String name = (String) headerNames.nextElement();
		String value = request.getHeader(name);
		System.out.println(name+"="+value);
		
	}

2. 獲取客戶端提交過來的數據

String name = request.getParameter("name");
	String address = request.getParameter("address");
	System.out.println("name="+name);
	System.out.println("address="+address);

	-------------------------------------------------

	//name=zhangsan&name=lisi&name=wangwu 一個key能夠對應多個值。

	Map<String, String[]> map = request.getParameterMap();
	
	Set<String> keySet = map.keySet();
	Iterator<String> iterator = keySet.iterator();
	while (iterator.hasNext()) {
		String key = (String) iterator.next();
		System.out.println("key="+key + "--的值總數有:"+map.get(key).length);
		String value = map.get(key)[0];
		String value1 = map.get(key)[1];
		String value2 = map.get(key)[2];
		
		System.out.println(key+" ======= "+ value + "=" + value1 + "="+ value2);
	}

3. 獲取中文數據

客戶端提交數據給服務器端,若是數據中帶有中文的話,有可能會出現亂碼狀況,那麼能夠參照如下方法解決。

* 若是是GET方式

1. 代碼轉碼
		String username = request.getParameter("username");
		String password = request.getParameter("password");
		
		System.out.println("userName="+username+"==password="+password);
		
		//get請求過來的數據,在url地址欄上就已經通過編碼了,因此咱們取到的就是亂碼,
		//tomcat收到了這批數據,getParameter 默認使用ISO-8859-1去解碼
		
		//先讓文字回到ISO-8859-1對應的字節數組 , 而後再按utf-8組拼字符串
		username = new String(username.getBytes("ISO-8859-1") , "UTF-8");
		System.out.println("userName="+username+"==password="+password);
	
		直接在tomcat裏面作配置,之後get請求過來的數據永遠都是用UTF-8編碼。 


2. 能夠在tomcat裏面作設置處理 conf/server.xml 加上URIEncoding="utf-8"

	   <Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" URIEncoding="UTF-8"/>

* 若是是POST方式

這個說的是設置請求體裏面的文字編碼。  get方式,用這行,有用嗎? ---> 沒用
	request.setCharacterEncoding("UTF-8");

	這行設置必定要寫在getParameter以前。

HttpServletResponse

負責返回數據給客戶端。

* 輸出數據到頁面上

//以字符流的方式寫數據	
	//response.getWriter().write("<h1>hello response...</h1>");
	
	//以字節流的方式寫數據 
	response.getOutputStream().write("hello response2222...".getBytes());

響應的數據中有中文,那麼有可能出現中文亂碼

* 以字符流輸出

response.getWriter()

//1. 指定輸出到客戶端的時候,這些文字使用UTF-8編碼
	response.setCharacterEncoding("UTF-8");
	
	//2. 直接規定瀏覽器看這份數據的時候,使用什麼編碼來看。
	response.setHeader("Content-Type", "text/html; charset=UTF-8");
	
	response.getWriter().write("我愛黑馬訓練營...");

* 以字節流輸出

response.getOutputStream()

//1. 指定瀏覽器看這份數據使用的碼錶
	response.setHeader("Content-Type", "text/html;charset=UTF-8");
	
	//2. 指定輸出的中文用的碼錶
	response.getOutputStream().write("我愛深圳黑馬訓練營..".getBytes("UTF-8"));


	--------------------------------------------

不論是字節流仍是字符流,直接使用一行代碼就能夠了。

response.setContentType("text/html;charset=UTF-8");

而後在寫數據便可。

演練下載資源。

1. 直接以超連接的方式下載,不寫任何代碼。 也可以下載東西下來。

讓tomcat的默認servlet去提供下載:<br>
	<a href="download/aa.jpg">aa.jpg</a><br>
	<a href="download/bb.txt">bb.txt</a><br>
	<a href="download/cc.rar">cc.rar</a><br>

緣由是tomcat裏面有一個默認的Servlet -- DefaultServlet 。這個DefaultServlet 專門用於處理放在tomcat服務器上的靜態資源。

2. 手寫代碼提供下載

html中代碼

<h3>手寫代碼提供下載</h3>
<a href="Load?filename=aa.txt">aa.txt</a><br/>
<a href="Load?filename=bb.jpg">bb.jpg</a><br/>
<a href="Load?filename=cc.zip">cc.zip</a><br/>

建立一個servlet命名爲Load,代碼

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class Load
 */
public class Load extends HttpServlet {
	
	@SuppressWarnings("resource")
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//得到要下載的文件名
		String filename = request.getParameter("filename");
		//得到這個文件在tomcat中的絕對路徑
		String realPath = getServletContext().getRealPath("download/"+filename);
		//讓瀏覽器收到這個資源的時候,以加載的方式提醒用戶而不是直接展現
		response.setHeader("Content-Disposition", "attachment;filename="+filename);
		
		response.setContentType("text/html;charset=UTF-8");
		
		InputStream fileInputStream = new FileInputStream(realPath);
		OutputStream fileOutputStream=response.getOutputStream();
		byte[] bt=new byte[1024];
		int len=0;
		while ((len=fileInputStream.read(bt)) > -1) {
			fileOutputStream.write(bt,0,len);			
		}
		fileInputStream.close();
		fileOutputStream.close();
		
	}

	/**
	 * @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);
	}

}

總結

  1. Servlet註冊方式

  2. ServletContext【重點】

    做用:
    
     	1. 獲取全局參數
    
     	2. 獲取工程裏面的資源。
    
     	3. 資源共享。  ServletContext 域對象
    
     有幾個 一個 
    
     何時建立 ? 何時銷燬
    
     服務器啓動的時候給每個應用都建立一個ServletContext對象, 服務器關閉的時候銷燬

    簡單登陸

  3. HttpServletRequest【重點】

    1. 獲取請求頭
    
     2. 獲取提交過來的數據
  4. HttpServletResponse【重點】

    負責輸出數據到客戶端,其實就是對以前的請求做出響應
  5. 中文亂碼問題。【重點】

  6. 下載

做業:

1. 完成註冊 

2. 完成登陸


V1.1 最好配合上數據庫,完成註冊和登陸的功能。

做業步驟分析:

先建立一個數據庫

建立表格存儲用戶信息,能夠規定字符格式之類的,配置JDBC驅動,拷貝JDBC驅動的jar包放在WebContent下的我web-inf下的lib裏面右鍵build path

分析:

第一步須要一個註冊界面

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<!-- 這裏action="Login",對應的是servlet配置中的url-pattern -->
	<form action="Login" method="get">
	姓名:<input type="text" name="username">
	密碼:<input type="password" name="password">
	<input type="submit" value="註冊">
	</form>
</body>
</html>

第二建立一個servlet命名爲Login,當註冊內容不爲空的時候將數據存儲到數據庫的表格中,若是存儲成功跳轉登錄界面,失敗的話直接輸出註冊失敗;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import s20190712.Dao.impl.UserImpl;


/**
 * Servlet implementation class Login
 */
public class Login extends HttpServlet {
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//得到客戶端的信息
		String username= request.getParameter("username");
		String password= request.getParameter("password");
		
		username=new String(username.getBytes("ISO-8859-1"),"UTF-8");
		password=new String(password.getBytes("ISO-8859-1"),"UTF-8");
		
		System.out.println("用戶名:"+username+"密碼:"+password);
		
		response.setContentType("text/html;charset=UTF-8");
		//校驗
	    if (!username.isEmpty()||!password.isEmpty()) {	
	    	UserImpl user=new UserImpl();
	    	int insert = user.insert(username, password);	
	    	if(insert>0) {
	    		//設置狀態碼從新定位
		    	response.setStatus(302);
		    	response.setHeader("Location", "config.html");//此處爲相對路徑	
	    	}    		
			
		}else {
			System.out.println("註冊失敗");
			response.getWriter().write("註冊失敗...");
		}
	}

	/**
	 * @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);
	}

}

第三須要一個登錄界面;

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h1>您已經成功註冊!</h1>
	<form action="Config" method="post">
		姓名:<input type="text" name="username">
		密碼:<input type="password" name="password">
		<input type="submit" value="登錄">
	</form>
</body>
</html>

第四建立一個servlet命名爲Config,登錄信息不爲空的時候,將信息在數據庫中按條件查詢,能夠匹配上跳轉登錄成功,失敗直接跳轉登錄失敗;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import s20190712.Dao.impl.UserImpl;


/**
 * Servlet implementation class Config
 */
public class Config extends HttpServlet {
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
			
		//得到客戶端的信息
		        request.setCharacterEncoding("utf-8");
				String username= request.getParameter("username");
				String password= request.getParameter("password");
				
				response.setContentType("text/html;charset=UTF-8");
				//校驗
			    if (!username.isEmpty()||!password.isEmpty()) {	
			    	UserImpl user=new UserImpl();
			    	boolean load = user.load(username, password);
			    	if (load==true) {
				    	int count=0;
						Object totalcount = getServletContext().getAttribute("count");
						
						if (totalcount!=null) {
							count=(int) totalcount;
						}
						getServletContext().setAttribute("count", count+1);
						System.out.println("登錄成功的次數是"+count+"次");
				    	//設置狀態碼從新定位
				    	response.setStatus(302);
				    	response.setHeader("Location", "load.html");//此處爲相對路徑		
					}
					if (load==false) {
						response.getWriter().write("登錄失敗...");
					}
					
				}else {

					response.getWriter().write("請返回頁面輸入登錄信息");
				}
	}

	/**
	 * @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);
	}

}

第五須要一個登錄成功界面,顯示下載資源連接;

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h3>這裏有資源能夠下載tomcat默認的servlet去提供下載</h3>
<a href="download/aa.txt">aa.txt</a><br/>
<a href="download/bb.jpg">bb.jpg</a><br/>
<a href="download/cc.zip">cc.zip</a><br/>

<h3>手寫代碼提供下載</h3>
<a href="Load?filename=aa.txt">aa.txt</a><br/>
<a href="Load?filename=bb.jpg">bb.jpg</a><br/>
<a href="Load?filename=cc.zip">cc.zip</a><br/>
</body>
</html>

第六建立一個servlet命名爲Load,獲取tomcat中提供下載的資源以字節流的方式讀取而且讀出,注意中文亂碼的問題

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class Load
 */
public class Load extends HttpServlet {
	
	@SuppressWarnings("resource")
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//得到要下載的文件名
		String filename = request.getParameter("filename");
		filename=new String(filename.getBytes("ISO-8859-1"),"UTF-8");//注意這裏若是文件名是中文須要對其進行編碼處理
		//得到這個文件在tomcat中的絕對路徑
		String realPath = getServletContext().getRealPath("download/"+filename);
		//讓瀏覽器收到這個資源的時候,以加載的方式提醒用戶而不是直接展現
		response.setHeader("Content-Disposition", "attachment;filename="+filename);
		
		response.setContentType("text/html;charset=UTF-8");
		
		InputStream fileInputStream = new FileInputStream(realPath);
		OutputStream fileOutputStream=response.getOutputStream();
		byte[] bt=new byte[1024];
		int len=0;
		while ((len=fileInputStream.read(bt)) > -1) {
			fileOutputStream.write(bt,0,len);			
		}
		fileInputStream.close();
		fileOutputStream.close();
		
	}

	/**
	 * @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);
	}

}

第七完善數據庫鏈接和註冊插入數據、登錄查詢數據的方法

在src下建立file,JDBC.properties
url=jdbc:mysql://localhost:3306/user
username=root
password=321
driverClass=com.mysql.jdbc.Driver
工具類

注意若是出現報錯JDBC驅動找不到的狀況,兩種方法,第一種在Java\jre1.8.0_151\lib\ext中配置JDBC驅動,就沒必要在工程目錄裏面配置了;第二種,註冊一下驅動,DriverManager或者Class.forName()均可以

import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

import com.mysql.jdbc.Driver;


public class JDBCUtil {
	
	static String driverClass =null;
	static String url =null;
	static String username =null;
	static String password =null;
	
	static {
		try {
			Properties prop=new Properties();
			InputStream is=JDBCUtil.class.getClassLoader().getResourceAsStream("JDBC.properties");
			prop.load(is);
			driverClass = prop.getProperty("driverClass");
			url = prop.getProperty("url");
			username = prop.getProperty("username");
			password = prop.getProperty("password");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
		   public static Connection getConn() {
			   Connection conn=null;
				try {
					//Class.forName(driverClass);
					conn = DriverManager.getConnection(url,username,password);
				} catch (Exception e) {
					e.printStackTrace();
				}
				return conn;
			}
    	public static void release(Connection conn,Statement st,ResultSet rs) {
			closeConn(conn);
			closeRs(rs);
			closeSt(st);
		}	
    	public static void release(Connection conn,Statement st) {
			closeConn(conn);
			closeSt(st);
		}	
	private static void closeConn(Connection conn) {	
			try {
				if (conn!=null) {
					conn.close();
				}
				
			} catch (SQLException e) {
				
				e.printStackTrace();
			}finally{
				conn=null;
			}	
		
	}
	
	private static void closeSt(Statement st) {	
		try {
			if (st!=null) {
				st.close();
			}
			
		} catch (SQLException e) {
			
			e.printStackTrace();
		}finally{
			st=null;
		}	
	
	}
	
	private static void closeRs(ResultSet rs) {	
		try {
			if (rs!=null) {
				rs.close();
			}
			
		} catch (SQLException e) {
			
			e.printStackTrace();
		}finally{
			rs=null;
		}	
	
	}
}
接口和實現類不在一個包中,有返回值
public interface UserDao {
	int insert(String username, String password);
	
	boolean load(String username, String password);
}
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import com.mysql.jdbc.Statement;

import s20190712.jdbc.dao.UserDao;
import s20190712.jdbc.util.JDBCUtil;

public class UserImpl implements UserDao{

	@Override
	public int insert(String username, String password) {
			Connection conn=null;
			PreparedStatement ps=null;
			int rs =0;
			try {
				//1.建立鏈接對象
				conn=JDBCUtil.getConn();
				
				//2.建立preparestatement對象,預處理sql語句
				String sql="insert into m_user values(null,?,?)";
				ps = conn.prepareStatement(sql);//注意導包import java.sql.PreparedStatement;
				//3.給佔位符賦值
				ps.setString(1,username);
				ps.setString(2,password);
				//4.執行sql語句
				rs = ps.executeUpdate();
				if(rs>0){
					System.out.println("更新成功");
				}else{
					System.out.println("更新失敗");
				}
			
			} catch (Exception e) {
				e.printStackTrace();
			}finally {
				//5.釋放資源
				JDBCUtil.release(conn,ps);	
				return rs;
			}					
		}
	@Override
	public boolean load(String username, String password) {
		boolean b=false;
		Connection conn=null;
		Statement st=null;
		ResultSet rs=null;
		try {
			//1.建立鏈接對象
			conn=JDBCUtil.getConn();
			
			//2.建立preparestatement對象,預處理sql語句
			String sql="select * from m_user where username = ? and password = ?";
			PreparedStatement ps = conn.prepareStatement(sql);//注意導包import java.sql.PreparedStatement;
			//3.給佔位符賦值
			ps.setString(1,username);
			ps.setString(2,password);
			//4.執行sql語句
			rs = ps.executeQuery();
			if(rs.next()){
				b=true;
			}else{
				b=false;
			}
		
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			//5.釋放資源
			JDBCUtil.release(conn,st,rs);
			return b;
		}		
	}
}
相關文章
相關標籤/搜索