前言
之前有過flask赖阻,django的小玩具的開發(fā)經(jīng)驗(yàn),由于覺得只了解一門語言好像不太有用柒竞。因?yàn)樽罱芙拥降膯巫釉絹碓蕉嗟男枰猨ava方向的內(nèi)容政供。比如在寫python爬蟲的時(shí)候經(jīng)常需要逆向app播聪,雖然現(xiàn)在很多app都采用了JNI的方法來保護(hù)源代碼朽基,但還是有一部分app是沒有采用的。因此熟悉java很有必要离陶。
之前已經(jīng)花了一段時(shí)間來學(xué)習(xí)過java的基礎(chǔ)語法稼虎,只是學(xué)習(xí)到j(luò)ava的io流部分≌信伲看來看去還是覺得沒有實(shí)際寫出來有用的代碼霎俩,是記不住經(jīng)常使用的語法什么的。于是便開始學(xué)習(xí)servlet這個(gè)后端框架沉眶。
在這里只寫出個(gè)人理解的部分打却,不代表servlet真實(shí)的思想...
servlet
每個(gè)servlet請求都會(huì)開啟一個(gè)線程來處理
生命周期
- init()
在客戶端第一次發(fā)起請求的時(shí)候會(huì)初始化servlet
然后調(diào)用這個(gè)方法內(nèi)的邏輯
可以用來做些變量的初始化之類的放到內(nèi)存之中
避免多次重復(fù)初始化 - service()
檢查客戶端響應(yīng)的類型
根據(jù)類型調(diào)用 servlet容器內(nèi)的doGet(),doPost()....之類的http method - destory()
在servlet銷毀的時(shí)候會(huì)調(diào)用這個(gè)鉤子函數(shù)。
可以用來做些內(nèi)存的釋放或者其他操作
Http method
如果servlet中存在service()方法會(huì)直接調(diào)用service方法而不會(huì)去調(diào)用doGet谎倔,doPost方法柳击,若還需要調(diào)用可以直接使用父類的service()方法,例如 super.service(req,resp)
- GET
在servlet中會(huì)使用doGet方法進(jìn)行處理 - POST
在servlet中會(huì)使用doPost方法進(jìn)行處理
表單數(shù)據(jù)
http://localhost:8080/MyForm?name=monster&age=18
- request.getParameter() 方法來獲取表單參數(shù)的值,這個(gè)方法需要一個(gè)字符串的參數(shù)來獲取值
request.getParameter("name") - request.getParameterValues() 如果參數(shù)出現(xiàn)一次以上,則調(diào)用該方法片习,并返回多個(gè)值捌肴,例如復(fù)選框.
http://localhost:8080/MyForm?name=monster&age=18&age=58
request.getParameter("name") - request.getParameterNames() 獲取請求來的所有參數(shù)名
請求頭
http請求中會(huì)包含客戶端的請求頭
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Enumeration<String> header_name = request.getHeaderNames();
while (true){
if(header_name.hasMoreElements()){
String header_iter = header_name.nextElement();
System.out.println(header_iter+ " : "+request.getHeader(header_iter));
}else {
break;
}
}
}
這段示例代碼可以在控制臺(tái)輸出當(dāng)前http請求的所有請求頭.
可以通過請求頭來簡單的防止初級(jí)爬蟲
響應(yīng)頭
可以在響應(yīng)頭中寫入cookie或者其他自己需要的信息
可以在響應(yīng)頭中寫入各種各樣的信息,客戶端可以解析響應(yīng)頭
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setCharacterEncoding("utf-8");
response.setContentType("text/html");
response.setIntHeader("refresh",5);
Date now = new Date();
SimpleDateFormat s = new SimpleDateFormat ("E yyyy.MM.dd 'at' hh:mm:ss a zzz");
PrintWriter out = response.getWriter();
out.println("<h1>wsw</h1>");
out.println("<p>"+s.format(now)+"</p>");
}
這個(gè)示例代碼在響應(yīng)頭中寫入了值為5的refresh,客戶端會(huì)根據(jù)這個(gè)響應(yīng)頭每5s刷新一次頁面
Http狀態(tài)碼
在服務(wù)運(yùn)行過程中可能會(huì)出現(xiàn)各種各樣的錯(cuò)誤,
此時(shí)返回Http狀態(tài)碼能夠更快的通過Http狀態(tài)碼找到相應(yīng)出錯(cuò)的地方,前提是需要返回正確的狀態(tài)碼.
public class HttpCode extends HttpServlet {
private String my_parameter;
public void init() throws ServletException {
my_parameter = "monster";
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Enumeration<String> names = request.getParameterNames();
boolean flag = false;
while (true){
if(names.hasMoreElements()){
if(my_parameter.equals(names.nextElement())){
flag = true;
break;
}
}else {
break;
}
}
if(flag){
response.sendError(400,"<h1>parameter True!</h1>");
}else {
response.sendError(404,"<h1>Error!!!!!!</h1>");
}
}
}
這段程序先初始化了一個(gè)自定義的字符串為monster
如果客戶端發(fā)來的請求沒有monster這個(gè)參數(shù),則返回404狀態(tài)碼,否則返回400
這里的狀態(tài)碼是隨便寫的,沒有實(shí)際意義...
過濾器
使用過濾器可以實(shí)現(xiàn)身份驗(yàn)證,數(shù)據(jù)壓縮,日志等等功能
Servlet 過濾器是可用于 Servlet 編程的 Java 類,可以實(shí)現(xiàn)以下目的:
- 在客戶端的請求訪問后端資源之前藕咏,攔截這些請求状知。
- 在服務(wù)器的響應(yīng)發(fā)送回客戶端之前,處理這些響應(yīng)孽查。
@WebFilter(filterName = "MyFilter",urlPatterns = "/*")
public class MyFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
System.out.println("myfilter doing....");
chain.doFilter(req, resp);
}
public void init(FilterConfig config) throws ServletException {
}
}
之前都是在web.xml中配置servlet,其實(shí)也可以通過使用注解方式來實(shí)現(xiàn)url映射
使用@WebServlet,@WebFilter 就能夠輕松配置url
但是個(gè)人感覺這樣寫好像不方便修改,需要進(jìn)入到每個(gè)類內(nèi)去尋找相應(yīng)的路由.
不如在web.xml中寫的來得簡潔明了
這個(gè)程序在每個(gè)Http請求到來之后都會(huì)先通過Myfilter類的doFilter的邏輯
可以在這里實(shí)現(xiàn)各種身份驗(yàn)證或者其他功能的邏輯
如果通過了這些邏輯判斷,
需要進(jìn)行對get,post,或者其他方法的處理就可以調(diào)用chain.doFilter(req, resp)來進(jìn)行下一步.
如果沒有通過就可以在這里對resp進(jìn)行寫操作 返回錯(cuò)誤內(nèi)容
Cookie
Http是一種無狀態(tài)的請求,所以需要通過攜帶其他信息提交給服務(wù)器來判斷是否登錄是哪個(gè)用戶等等功能
其中最常用的就是通過cookie判斷
@WebServlet(name = "MyCookie",urlPatterns = "/cook")
public class MyCookie extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cookie[] cookies = request.getCookies();
for(Cookie c : cookies){
System.out.println(c.getName() + " : " + c.getValue());
}
Cookie usermsg = new Cookie("hello","monster");
response.addCookie(usermsg);
}
}
打印cookie和設(shè)置cookie