开发Web应用程序技术学习
1. HTTP协议 概念:超文本传输协议(HyperText Transfer Protocol)
作用:规范服务器和客户端数据交互格式
建立在TCP/IP 基础上,HTTP协议使用可靠的TCP连接,端口80
特点:
无连接 ,限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,断开连接,节省传输时间
无状态 ,HTTP协议对于事务处理没有记忆功能,缺少状态意味着如果后续处理需要前面的信息,必须重传,可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答较快。
HTTP/1.1 支持可持续连接
交互流程:
客户端和服务端建立连接
客户端向服务端请求数据,发送http协议
服务器处理请求的http协议,发送响应数据给客户端
客户端接受响应数据,渲染到浏览器
1.1. 请求方式 HTTP/1.0 定义三种请求方法:
HTTP/1.1 新增
OPTIONS 允许客户端查看服务器性能
PUT 从客户端向服务端传送的数据取代指定文档的内容
DELETE 请求服务器删除指定页面
TRACE 回退服务器收到的请求,主要用于测试或诊断
CONNECT HTTP/1.1协议预留给能够将连接改为管道方式的代理服务器
1 2 3 4 5 6 7 8 9 10 11 12 方法_/统一资源标识符_/协议/版本\r\n 请求标头\r\n \r\n 实体主体(post请求才有) POST /examples/default.jsp HTTP/1.1 Accept : text/plain; test/html Accept-Language : en-gb Connection : Keep-alive Host : localhost user =wt&&pwd=123
Connection: Keep-alive 持久连接,使用同一个连接来下载所有资源
1.2. 响应方式 Response
1 2 3 4 5 6 7 8 9 10 11 12 13 14 协议 状态码 描述\r\n 响应标头\r\n \r\n 实体主体 HTTP/1.1 200 OK Server : Apache-Coyote/1.1 Content-Type : text/html Content-Length :112 <html> <head></head> <body></body> </html>
状态码
200 OK 请求成功
400 Bad Request 请求有语法错误
404 Unauthorized 请求未经授权,和www-Authenticate一起使用
403 Forbidden 服务器收到请求,拒绝提供服务
404 Not Found 资源不存在
500 Internal Server Error 服务器错误,异常
servlet类class路径拼写错误
servlet类方法体代码有错误
503 Server Unavailable 服务器当前不能处理客户端请求
e.g.
HTTP基于TCP/IP
TCP用ServerSocket类实现
接收客户端 accpet() –> Socket类
接收 getInputStream()
发送 getOutputStream()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.OutputStreamWriter;import java.net.InetAddress;import java.net.ServerSocket;import java.net.Socket;public class Main { private void service () { try { ServerSocket server = new ServerSocket (8888 ,1 , InetAddress.getByName("localhost" )); Socket client = server.accept(); OutputStream out = client.getOutputStream(); InputStream in = client.getInputStream(); BufferedReader br = new BufferedReader (new InputStreamReader (in,"UTF-8" )); BufferedWriter bf = new BufferedWriter (new OutputStreamWriter (out,"UTF-8" )); StringBuilder string=new StringBuilder (); string.append("HTTP/1.1 200 OK\r\n" ); string.append("Content-type: text/html; charset=UTF-8\r\n" ); string.append("Connection: keep-alive\r\n" ); string.append("\r\n" ); string.append("<html><head></head><title>return</title>" ); string.append("<body>Hello World" +br.readLine()); string.append("</body></html>" ); bf.write(string.toString()); bf.flush(); } catch (IOException e) { e.printStackTrace(); } } public static void main (String[] args) { Main main = new Main (); main.service(); } } Socket client = new Socket (6666 );client.getOutputStream(new File ("" ));
2. Tomcat 代码编写的可以根据用户请求实时调用执行对应逻辑代码的容器。
目录:
bin 可执行文件
conf 配置文件
lib 存放库文件
logs 日志
temp 临时文件
webapps web应用
work jsp转换后的servlet文件
运行
1 2 3 $ cd bin$ sudo ./startup.sh $ sudo ./shutdown.sh
3. Servlet 狭义的servlet指java语言实现的一个接口,广义的servlet指任何实现了这个servlet接口的类。servlet运行于支持java的应用服务器中,用来扩展基于http协议的web服务器
3.1. 第一个servlet服务 继承HttpServlet,重写service方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import java.io.IOException;import java.io.PrintWriter;import javax.servlet.ServletConfig;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class LoginServlet extends HttpServlet { @Override protected void service (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String username=request.getParameter("username" ); String password=request.getParameter("pwd" ); response.setContentType("text/html;charset=utf-8" ); PrintWriter out=response.getWriter(); out.write(username); out.write(password); out.flush(); } @Override public void init (ServletConfig config) throws ServletException { super .init(config); } }
映射
1 2 3 4 5 6 7 8 9 <servlet > <servlet-name > log</servlet-name > <servlet-class > com.runaccpeted.servlet.LoginServlet</servlet-class > </servlet > <servlet-mapping > <servlet-name > log</servlet-name > <url-pattern > /log</url-pattern > </servlet-mapping >
简单界面
1 2 3 4 5 <form action="./log" method="get" > 用户名:<input type="text" name="username" id="username" /><br/> 密码:<input type="password" name="pwd" id="pwd" /><br/> <input type="submit" value="登陆" /> </form>
流程:
url: http://localhost:8080/tomcat/log?username=wt&pwd=123
http://服务器地址:端口号/webapps下文件名/?请求数据/web.xml中配置的servlet的url-pattern?请求数据
3.2. URL,URI URI:Uniform Resource Indentifier 统一资源标识符,/tomcat/log?username=wt&pwd=123
URL:Uniform Resource Location 统一资源定位器 一种具体的URI
http://localhost:8080/tomcat/log?username=wt&pwd=123
URL.openStream() == InputStream 可用于抓取网络信息
3.3. 生命周期 Serlvet在整个tomcat中只有一个实例,第一次被调用,加载进内存init方法执行,到tomcat关闭destory方法执行。
1 2 3 4 5 <servlet > <servlet-name > log</servlet-name > <servlet-class > com.runaccpeted.servlet.LoginServlet</servlet-class > <load-on-startup > 1</load-on-startup > </servlet >
在web.xml中配置load-on-startup使servlet在tomcat启动时就被初始化,数字1表示加载顺序
3.4. doGet(),doPost(),service() doGet处理get请求
doPost处理post请求
service处理所有请求,存在service(),优先调用service
1 2 3 protected void service (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { super .service(request,response); }
调用父类的service方法时,它处理完本service后调用相应的doGet,doPost方法执行,不存在doGet,doPost方法时则出现405错误
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 protected void service (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String method = req.getMethod(); long lastModified; if (method.equals("GET" )) { lastModified = this .getLastModified(req); if (lastModified == -1L ) { this .doGet(req, resp); } else { long ifModifiedSince; try { ifModifiedSince = req.getDateHeader("If-Modified-Since" ); } catch (IllegalArgumentException var9) { ifModifiedSince = -1L ; } if (ifModifiedSince < lastModified / 1000L * 1000L ) { this .maybeSetLastModified(resp, lastModified); this .doGet(req, resp); } else { resp.setStatus(304 ); } } } else if (method.equals("HEAD" )) { lastModified = this .getLastModified(req); this .maybeSetLastModified(resp, lastModified); this .doHead(req, resp); } else if (method.equals("POST" )) { this .doPost(req, resp); } else if (method.equals("PUT" )) { this .doPut(req, resp); } else if (method.equals("DELETE" )) { this .doDelete(req, resp); } else if (method.equals("OPTIONS" )) { this .doOptions(req, resp); } else if (method.equals("TRACE" )) { this .doTrace(req, resp); } else { String errMsg = lStrings.getString("http.method_not_implemented" ); Object[] errArgs = new Object []{method}; errMsg = MessageFormat.format(errMsg, errArgs); resp.sendError(501 , errMsg); } }
父类doGet方法
直接响应405
1 2 3 4 5 6 7 8 9 10 protected void doGet (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String protocol = req.getProtocol(); String msg = lStrings.getString("http.method_get_not_supported" ); if (protocol.endsWith("1.1" )) { resp.sendError(405 , msg); } else { resp.sendError(400 , msg); } }
父类doPost方法
1 2 3 4 5 6 7 8 9 10 protected void doPost (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String protocol = req.getProtocol(); String msg = lStrings.getString("http.method_post_not_supported" ); if (protocol.endsWith("1.1" )) { resp.sendError(405 , msg); } else { resp.sendError(400 , msg); } }
接口中包括
void init(ServletConfig) 仅第一个请求Servlet时会调用
void service(ServletRequest request, ServletResponse response)
Void destory()
文件结构
webapps
——FirstProject
————WEB-INF
——————classes java文件的class文件放在这里
——————lib
3.5. 乱码 String 转换字符集
1 String str = new String (uname.getByte("iso8859-1" ),"utf-8" );
request编码格式 –POST请求方式下有效
1 request.setCharacterEncoding("utf-8" );
tomcat文件下conf/server.xml
useBodyEncodingForURI=”true”
1 2 3 <Connector port ="8080" protocol ="HTTP/1.1" connectionTimeout ="20000" redirectPort ="8443" URIEncoding ="utf-8" useBodyEncodingForURI ="true" />
3.6. 操作流程 数据流转流程:
浏览器发起请求到服务器
服务器接受浏览器请求进行解析,创建request对象存储请求数据
服务器调用对应的servlet进行请求处理,将response对象作为实参传递给servlet。
Servlet使用流程:
设置请求编码格式
设置响应编码格式
获取请求信息
处理请求信息
响应处理结果
3.7. 请求转发 实现多个servlet联动操作处理请求,让servlet职责更加明确
1 request.getRequestDispatcher("相对地址" ).forward(request, response);
一次请求,地址栏信息不变
3.8. 重定向 解决表单重复提交问题,当前servlet无法处理的请求问题
1 response.sendRedirect("" );
两次请求对象,地址栏信息改变
请求中有表单数据,数据不适合重复提交;
数据无法处理,需要重定向到特定资源处理
3.9. ServletRequest request对象封存当前请求的所有请求信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 request.setCharacterEncoding("utf-8" ); int length=request.getContentLength();String mime=request.getContentType(); String parameter=request.getContentParameter(name); String[] values= request.getParameterValues("hobbies" ); for (String str:values){ System.out.println(str); } String protocol=request.getContentProtocol(); String url=request.getRequestURL() String uri=request.getRequestURI(); String method=request.getMethod(); Enumeration<String> heads=request.getHeaderNames(); while (heads.hasMoreElements()) { String key=heads.nextElement(); String value=request.getHeader(key); System.out.println(key+" = " +value); }
3.10. ServletResponse response对象用来响应客户端
1 2 3 4 5 6 7 8 9 10 11 response.setHeader("Content-type" ,"text/html" ); response.addHeader("Content-type" ,"text/html" ); response.setContentType("text/html;charset=utf-8" ); response.sendError(404 ,"Resource Not Found" ); PrintWriter out = response.getWriter();
3.11. 登录练习 login.jsp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8" > <title>登录</title> </head> <body> <form action="log" method="post" > 用户名<input type="text" name="uname" /> 密码<input type="password" name="pwd" /> <input type="submit" value="提交" > </form> </body>
User.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 package com.runaccpeted.pojo;public class User { private String username; private String password; private int id; public String getUsername () { return username; } public void setUsername (String username) { this .username = username; } public String getPassword () { return password; } public void setPassword (String password) { this .password = password; } public int getId () { return id; } public void setId (int id) { this .id = id; } @Override public String toString () { return "User [username=" + username + ", password=" + password + ", id=" + id + "]" ; } }
LoginServlet.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 package com.runaccpeted.servlet;import java.io.IOException;import java.io.Writer;import java.sql.Connection;import java.sql.Driver;import java.sql.DriverManager;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import com.mysql.cj.protocol.Resultset;import com.runaccpeted.pojo.User;public class LoginServlet extends HttpServlet { Connection conn; PreparedStatement statement; @Override protected void service (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8" ); response.setContentType("text/html;charset=utf-8" ); String uname=request.getParameter("uname" ); String pwd=request.getParameter("pwd" ); Writer out = response.getWriter(); try { statement = conn.prepareStatement("select * from user where username=? and password=?" ); statement.setString(1 , uname); statement.setString(2 , pwd); ResultSet rs=statement.executeQuery(); User user=null ; while (rs.next()) { user =new User (); user.setId(rs.getInt(1 )); user.setUsername(rs.getString(2 )); user.setPassword(rs.getString(3 )); } System.out.println(user); if (user!=null ) { out.write("登录成功" ); }else { response.sendRedirect("login.jsp" ); } } catch (SQLException e) { e.printStackTrace(); } finally { try { statement.close(); } catch (SQLException e) { e.printStackTrace(); } } } @Override public void destroy () { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } @Override public void init () throws ServletException { try { Class.forName("com.mysql.cj.jdbc.Driver" ); conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/login?useSSL=false" , "root" , "mysql123//" ); } catch (Exception e) { e.printStackTrace(); } } }
3.12. 资源映射
web.xml
1 2 3 4 5 6 7 8 <servlet > <servlet-name > LoginSerlvet</servlet-name > <servlet-class > com.bjsxt.serlvet.LoginSerlvet</servlet-class > </servlet > <servlet-mapping > <servlet-name > LoginSerlvet</servlet-name > <url-pattern > /login</url-pattern > </servlet-mapping >
注解
1 2 @WebServlet(name="myServlet",urlPatterns={"/login"}) public class myServlet extends HttpServlet { }
4. Cookie javax.servlet.http.Cookie;
实现跨多个页面信息的传递,数据共享
对象声明在服务端,存储在客户端
临时存储:存储在客户端内存中,浏览器关闭则cookie失效
定时存储:存储在客户端硬盘中,有效期内符合路径要求的都存在cookie中 cookie.setMaxAge(时间秒);
默认请求中都会携带cookie信息。
cookie.setPath(“相对路径”);设置cookie有效路径
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 Cookie cookie = new Cookie ("username" ,request.getParameter("username" ));cookie.setMaxAge(10 ); response.addCookie(cookie); Cookie[] cookies=request.getCookies(); String recoder = null ;if (cookies!=null ){ for (Cookie cookie:cookies){ if (cookie.getName().equals("username" )){ recoder = cookie.getValue(); } } }
请求头中存有cookie请求头
1 Cookie: JSESSIONID=5071A23663A7EA118B8251498FD21944; uname=abc; Hm_lvt_59cd4bc54e9d484dff9357727e454c80=1578376259,1579197274
5. Session 一个用户的不同请求处理数据共享
用户第一次访问服务器,服务器会创建一个session给此用户,并将session对象的JSESSIONID技术存储到浏览器中,保证用户的其他请求能够获取到同一个session对象,保证不同请求能够获取到共享的数据。
存储在服务器端
有效范围为一次会话,在JSESSIONID和session对象不失效情况下存在于整个项目
依赖cookie技术实现,存储在cookie的临时存储空间中,浏览器关闭则失效,默认失效时间30分钟
5.1. 创建Session 1 HttpSession session=request.getSession();
请求中拥有session的标识符也就是JSESSIONID,则返回其对应的session队形
请求中没有session的标识符也就是JSESSIONID,则创建一个新的session对象,并将其JSESSIONID作为cooike数据存储在浏览器内存中
session失效则重新创建一个session对象,并将其JSESSIONID存储在浏览器内存中
1 2 3 4 5 HttpSession session=request.getSession(false ); System.out.println(session.getId());
5.2. Session失效 设置失效时间 5s
1 session.setMaxInactiveInterval(5 );
强制session过期
1 2 HttpSession session = request.getSession();session.invalidate();
所有项目 conf/web.xml
1 2 3 <session-config > <session-timeout > 30</session-timeout > </session-config >
5.3. Session使用 存值, value可以是任意实现了Serializable的Object
1 session.setAttribute(String name,Object value);
可用于存储登录的用户对象,解决登录重定向后的信息关联,不同请求的数据共享
所有key
1 java.util.Enumeration<String> getAttributeNames () ;
servlet容器会为每个HttpSession生成一个唯一标识符,并将标识符作为token JSESSIONID发送给浏览器,在后续请求中浏览器将token传回服务器使得服务器知道是哪个用户在发出请求。
6. ServletContext 实现不同用户的数据共享
ServletContext对象由服务器创建,一个项目只有一个对象
。
可用于统计网站访问量
6.1. 创建对象 1 2 3 4 5 6 ServletContext c1=request.getServletContext(); ServletContext c2 = this .getServletConfig().getServletContext();ServletContext c3 = request.getSession().getServletContext();
6.2. 存储数据 1 2 3 4 ServletContext c1=request.getServletContext(); c1.setAttribute(String key,Object value); Object = c1.getAttribute(value);
6.3. 应用场景 配置全局数据
1 2 3 4 <context-param > <param-name > key</param-name > <param-value > value</param-value > </context-param >
取值
1 2 3 4 5 6 7 ServletContext c1=request.getServletContext(); c1.getInitParameter("key" ); Enumeration<String> str =c1.getInitParameterNames();
获取项目根目录下资源的绝对路径
/Users/Learning/Resource/workspace/myEclipse/.metadata/.me_tcat85/webapps/tomcat/index.jsp
1 2 3 ServletContext c1=request.getServletContext(); c1.getRealPath("index.jsp" );
获取流对象
1 2 3 ServletContext c1=request.getServletContext(); InputStream in=c1.getResourceAsStream(String path);
7. ServletConfig 作为servlet的专属配置对象,每个servlet拥有一个ServletConfig对象,用来获取web.xml中的配置信息
1 2 3 4 5 6 <servlet > <init-param > <param-name > key</param-name > <param-value > value</param-value > </init-param > </servlet >
取
1 2 ServletConfig config = this .getServletConfig();String value = getInitParameter("key" );
8. server.xml Web容器按ServletContext->context-param-> listener-> filter-> servlet顺序加载组件,这些元素在web.xml文件中为任意位置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 <Server port ="8005" shutdown ="SHUTDOWN" > <Listener className ="org.apache.catalina.startup.VersionLoggerListener" /> <Listener className ="org.apache.catalina.core.AprLifecycleListener" SSLEngine ="on" /> <Listener className ="org.apache.catalina.core.JreMemoryLeakPreventionListener" /> <Listener className ="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" /> <Listener className ="org.apache.catalina.core.ThreadLocalLeakPreventionListener" /> <Service name ="Catalina" > <Connector port ="8080" protocol ="HTTP/1.1" connectionTimeout ="20000" redirectPort ="8443" URIEncoding ="utf-8" useBodyEncodingForURI ="true" /> <Connector port ="8009" protocol ="AJP/1.3" redirectPort ="8443" /> <Engine name ="Catalina" defaultHost ="localhost" > <Host name ="localhost" appBase ="webapps" unpackWARs ="true" autoDeploy ="true" > </Host > </Engine > </Service > </Server >
9. 热部署 写在Host标签中
在集成开发环境下修改项目代码,tomact自动再次加载项目
1 2 3 4 5 <Engine > <Host > <context path ="/项目别名" reloadable ="true" docBase ="项目绝对路径到项目名" /> </Host > </Engine >
10. JSP java服务器页面 Java Server page。 它本质还是一个servlet
配置项在tomcat的web.xml中
1 2 3 4 5 6 7 8 9 10 11 <servlet > <servlet-name > jsp</servlet-name > <servlet-class > org.apache.jasper.servlet.JspServlet</servlet-class > <load-on-startup > 3</load-on-startup > </servlet > <servlet-mapping > <servlet-name > jsp</servlet-name > <url-pattern > *.jsp</url-pattern > <url-pattern > *.jspx</url-pattern > </servlet-mapping >
编写index.jsp
在work/Catalina/localhost/project/org/apache/jsp下有
login_jsp.java
login_jsp.class
index_jsp.java源代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 package org.apache.jsp;import javax.servlet.*;import javax.servlet.http.*;import javax.servlet.jsp.*;public final class login_jsp extends org .apache.jasper.runtime.HttpJspBase implements org .apache.jasper.runtime.JspSourceDependent, org.apache.jasper.runtime.JspSourceImports { private static final javax.servlet.jsp.JspFactory _jspxFactory = javax.servlet.jsp.JspFactory.getDefaultFactory(); private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants; private static final java.util.Set<java.lang.String> _jspx_imports_packages; private static final java.util.Set<java.lang.String> _jspx_imports_classes; static { _jspx_imports_packages = new java .util.HashSet<>(); _jspx_imports_packages.add("javax.servlet" ); _jspx_imports_packages.add("javax.servlet.http" ); _jspx_imports_packages.add("javax.servlet.jsp" ); _jspx_imports_classes = null ; } private volatile javax.el.ExpressionFactory _el_expressionfactory; private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager; public java.util.Map<java.lang.String,java.lang.Long> getDependants() { return _jspx_dependants; } public java.util.Set<java.lang.String> getPackageImports() { return _jspx_imports_packages; } public java.util.Set<java.lang.String> getClassImports() { return _jspx_imports_classes; } public javax.el.ExpressionFactory _jsp_getExpressionFactory () { if (_el_expressionfactory == null ) { synchronized (this ) { if (_el_expressionfactory == null ) { _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory(); } } } return _el_expressionfactory; } public org.apache.tomcat.InstanceManager _jsp_getInstanceManager () { if (_jsp_instancemanager == null ) { synchronized (this ) { if (_jsp_instancemanager == null ) { _jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig()); } } } return _jsp_instancemanager; } public void _jspInit () { } public void _jspDestroy () { } public void _jspService (final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response) throws java.io.IOException, javax.servlet.ServletException { final java.lang.String _jspx_method = request.getMethod(); if (!"GET" .equals(_jspx_method) && !"POST" .equals(_jspx_method) && !"HEAD" .equals(_jspx_method) && !javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) { response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSPs only permit GET POST or HEAD" ); return ; } final javax.servlet.jsp.PageContext pageContext; javax.servlet.http.HttpSession session = null ; final javax.servlet.ServletContext application; final javax.servlet.ServletConfig config; javax.servlet.jsp.JspWriter out = null ; final java.lang.Object page = this ; javax.servlet.jsp.JspWriter _jspx_out = null ; javax.servlet.jsp.PageContext _jspx_page_context = null ; try { response.setContentType("text/html; charset=UTF-8" ); pageContext = _jspxFactory.getPageContext(this , request, response, null , true , 8192 , true ); _jspx_page_context = pageContext; application = pageContext.getServletContext(); config = pageContext.getServletConfig(); session = pageContext.getSession(); out = pageContext.getOut(); _jspx_out = out; out.write("\n" ); out.write("<!DOCTYPE html>\n" ); out.write("<html>\n" ); out.write("<head>\n" ); out.write("<meta charset=\"UTF-8\">\n" ); out.write("<title>登录</title>\n" ); out.write("</head>\n" ); out.write("<body>\n" ); out.write("<form action=\"log\" method=\"post\">\n" ); out.write("用户名<input type=\"text\" name=\"uname\"/>\n" ); out.write("密码<input type=\"password\" name=\"pwd\"/>\n" ); out.write("<input type=\"submit\" value=\"提交\">\n" ); out.write("</form>\n" ); out.write("</body>\n" ); out.write("</html>" ); } catch (java.lang.Throwable t) { if (!(t instanceof javax.servlet.jsp.SkipPageException)){ out = _jspx_out; if (out != null && out.getBufferSize() != 0 ) try { if (response.isCommitted()) { out.flush(); } else { out.clearBuffer(); } } catch (java.io.IOException e) {} if (_jspx_page_context != null ) _jspx_page_context.handlePageException(t); else throw new ServletException (t); } } finally { _jspxFactory.releasePageContext(_jspx_page_context); } } }
10.1. 注释 前端注释 会被转译,也会被发送,但不会被浏览器执行
java注释 会被转译,不会被servlet执行
jsp注释 不会被转译
10.2. jsp存在的隐式参数
对象
类型
request
javax.servlet.HttpServletRequest
response
javax.servlet.HttpServletResponse
out
javax.servlet.jsp.JspWriter
session
javax.servlet.http.httpSession
application
javax.servlet.ServletContext
config
javax.servlet.ServletConfig
pageContext
javax.servlet.jsp.PageContext 页面上下文,封存了其他内置对象。封存了当前jsp的运行信息
page
javax.servlet.jsp.HttpJspPage
exception
java.lang.Throwable – <%@page isErrorPage=true %>
PageContext可以设定存取范围
page 当前页
request 当前ServletRequest
session 当前HttpSession
application ServletContext
e.g.
1 2 3 <% pageContext.setAttribute("username" ,user,PageContext.REQUEST_SCOPE); %>
10.3. page指令 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <%@page language="java"%> <%@page import="java.util.Date,java.util.List" %> <%@page session=false %> <%@page buffer=8 %> <%@page autoFlush=true %> <%@page info=“ %> <%@page errorPage="error.html" %> <%@page isErrorPage=true %> <%@page contentType="text/html; charset=UTF-8" %> <%@page pageEncoding="UTF-8" %> <%@page isELIgnored=true %> <%@page language="java" %>
10.4. 脚本 10.4.1. 局部代码块 <% %>
局部代码块中的java代码会被原样转译到对应的servlet文件的_JspService方法中,进行逻辑判断时书写麻烦,阅读困难。
1 <% System.out.println("index"); %>
10.4.2. 表达式 <%= %>
结果会嵌入out.write() 中
不需要使用分号
10.4.3. 全局代码块 <%! %>
1 2 3 4 5 6 7 <%! public Date getDate(){ return new Date(); } %> <%=getDate()%>
10.4.4. 动作 10.4.4.1. 创建对象 1 2 <jsp:useBean id = "today" class ="java.util.Date" > <%=today%>
10.4.4.2. 创建属性 1 2 <jsp:setProperty name ="username" property ="name" value ="abc" /> <jsp:getProperty name ="username" property ="name" />
10.5. 引入 降低代码的冗余,便于代码维护
10.5.1. 静态引入 被引入的jsp不会被编译
1 <%@include file="/copyrigth.jsp" %>
合并转译成一个java文件访问,故文件中不能同时存在同名变量。
10.5.2. 动态引入 会单独生成jsp对应的java文件,引用java文件中的方法
1 2 3 <jsp:include page ="menu.jsp" > <jsp:param name ="text" value ="How are you?" /> </jsp:include >
include指令发生在页面转换时,include动作发生在请求时
include指令处理的可以是静态页面,include动作处理的是jsp页面
10.6. 跳转 一次请求,地址栏网址改变
1 2 3 <jsp:forward page ="/login.jsp" > <jsp:param name ="aaa" value ="str" /> </jsp:forward >
Servlet中对应代码
1 2 3 4 if (true ){ _jspx_page_context.forward("/login.jsp" +"?" +org.apache.jasper.runtime.JspRuntimeLibrary.URLEncode("aaa" ,request.getCharacterEncoding())+"=" +org.apache.jasper.runtime.JspRuntimeLibrary.URLEncode("str" ,request.getCharacterEncoding())); return ; }
10.7. 资源路径 1 2 3 4 5 6 7 8 <% String path = request.getContextPath(); %> <% String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE html > <html > <head > <base href ="<%=basePath %>>" > </head > </html >
11. ajax 实现异步访问
ajax.onreadystatechange 会调用4次
未调用open方法时
调用open方法时
调用send方法时
返回结果时
ajax.readyState返回第几次
ajax.status 返回响应状态码 200 404 500
send() 用于post请求中,输入参数
还要添加 setRequestHeader 以键值对的方式传递数据
1 2 3 ajax.open ("post" ,"ajax" ,true ); ajax.setRequestHeader ("Content-Type" , "application/x-www-form-urlencoded" ); ajax.send ("name=w&&age=3" );
ajax.open(“post”,”ajax”,true);
ajax.open(method,urlPattern,async);
async - true 异步; - false 同步
应用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 <head> <style type="text/css" > #showdiv{ width:500px; height:100px; border:1px #000 solid; } </style> <script type="text/javascript" > function getData () { var ajax; if (window.XMLHttpRequest){ ajax=new XMLHttpRequest (); }else if (window.ActiveXObject){ ajax=new ActiveXObject ("Msxml2.XMLHTTP" ); } ajax.onreadystatechange = function(){ if (ajax.readyState==4 ){ var result=ajax.responseText; var showdiv = document.getElementById("showdiv" ); showdiv.innerHTML=result; } } ajax.open("get" , "ajax" , true ); ajax.send(null ); } </script> </head> <input type="button" value="搜索" onclick="getData()" /> <div id="showdiv" ></div>
11.1. JSON 获取json对象
gson-2.8.0.jar
1 2 3 import com.google.gson.Gson;response.getWriter().write(new Gson ().toJson(user));
aja响应数据
1 2 var result = ajax.responseText ();eval ("var u=" +result);
12. EL Experssion Language
${ } 运算结果强制为String
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <% (User)request.getAttribute("user").getName();%> ${user[name]} ${user.name} <% request.getParameter("uname")%> ${param.uname} <% request.getParameterValues("hobbies");%> ${paramValues.hobbies} ${header} ${header["键名"]} ${headerValues["accpet-language"][0]} ${cookie} ${cookie.JSESSIONID} ${cookie.JSESSIONID.name} ${cookie.JSESSIONID.value}
12.1. 隐式对象
对象
描述
pageContext
当前页面javax.servlet.jsp.PageContext (9大隐式对象)${pageContext.session.id}
initParam
所有context初始化参数并以参数名称为键的map
param
所有请求参数并以参数名称为键的map ${param.user}
paramValues
所有请求参数并以参数名称为键的map 返回的是数组
header
所有请求标头并以标头名称为键的map ${header[“accept-language”]}
cookie
当前请求对象中所有Cookie对象的map
applicationScope
ServletContext对象中所有属性并以属性名称为键的map
sessionScope
httpSession对象中所有属性并以属性名称为键的map
12.2. el查找顺序 作用域从小到大
pageContext –> request –> session –> application
指定作用域
pageScope –> requestScope –> sessionScope –> applicationScope
12.3. 逻辑运算 1 2 3 4 ${1 +2 } ==3 ${sex==1 ?'男' :'女' } ${1 +"2" } ==3 ${4 ==4 } true
12.4. empty判空
13. JSTL JavaServer Pages Standard Tag Library标准标签类库
对EL表达式的扩展
提升jsp页面编码效率
13.1. 声明 1 <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
Can not find the tag library descriptor for “http://java.sun.com/jsp/jstl/ core”
web工程中导入
jstl.jar
standard.jar
13.2. 通用标签 1 2 3 4 5 6 7 8 <c:out value="${}" default ="" > </c:out> <c:set var ="变量" value="值" scope="page/request/session/application" /> <c:set target="${address}" property="city" value="Tokyo" /> <c:remove var ="删除变量" scope="page/request/session/application" >
13.3. 条件 1 2 3 4 5 6 7 8 9 10 11 12 13 <c:if test="${测试语句}" scope="page/request/session/application" > 成功时输出 </c:if > <c:if test="!测试语句" scope="page/request/session/application" > 条件取反时输出 </c:if > <c:choose> <c:when test="${测试语句}" > </c:when> <c:when test="${测试语句}" > </c:when> <c:otherwise> </c:otherwise> </c:choose>
13.4. 迭代 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <c:forEach var ="x" begin="1" end="5" > <c:out value="${x}" /> </c:forEach> <c:forEach var ="x" items="${param.info}" step="2" varStatus="status" > <c:if test="${status.count%2==0}" > javax.servlet.jsp.jstl.LoopTagStatus接口,返回当前迭代次数 1 ,2 ,3. .. </c:if > <c:out value="${x}" /> </c:forEach> <c:forTokens var ="x" items="a,b,c" delims="," varStatus="status" > ${x} </c:forTokens>
14. 监听器 监听作用域对象request,session,application的创建,销毁和内容的改变
监听器级别:ServletContext,HttpSession,ServletRequest
监听器的注册
1 注解配置
1 2 @WebListener public class AppListener implements ServletContextListener
2 添加到web.xml
1 2 3 <listener > <listener-class > </listener-class > </listener >
14.1. ServletContextListener javax.servlet.*;
ServletContextListener
对ServletContext的初始化和解构作出响应
1 2 3 4 5 6 7 8 9 10 11 12 public class AppListener implements ServletContextListener { public void contextInitialized (ServletContextEvent e) { ServletContext application=e.getServletContext(); application.setAttribute("test" ,"1" ); } public void contextDestroyed (ServletContextEvent e) { } }
ServletContextAttributeListener
ServletContext添加,删除,替换属性时会收到通知
1 2 3 4 5 6 7 8 9 public class AppListener implements ServletContextAttributeListener { public void attributeAdded (ServletContextAttributeEvent e) { e.getName(); e.getValue(); } public void attributeRemoved (ServletContextAttributeEvent e) {} public void attributeReplaced (ServletContextAttributeEvent e) {} }
14.2. HttpSessionListener javax.servlet.http.*;
HttpSessionListener
HttpSession创建或销毁,会调用所有注册的HttpSessionListener。
1 2 3 4 5 6 7 8 public class AppListener implements HttpSessionListener { public void sessionCreated (HttpSessionEvent e) { HttpSession session = e.getSession(); } public void sessionDestroyed (HttpSessionEvent e) {} }
HttpSessionAttributeListener
1 2 3 4 5 6 7 8 public class AppListener implements HttpSessionAttributeListener { public void attributeAdded (HttpSessionBindingEvent e) {} public void attributeRemoved (HttpSessionBindingEvent e) {} public void attributeReplaced (HttpSessionBindingEvent e) {} }
HttpSessionActivationListener
为了节省内存将访问量少的session序列化迁移到存储设备中
1 2 3 4 5 6 7 public class AppListener implements HttpSessionActivationListener { public void sessionDidActivate (HttpSessionEvent e) { e.getSession(); } public void sessionWillPassivate (HttpSessionEvent e) {} }
HttpSessionBindingListener
绑定HttpSession或者取消绑定时触发
类实现HttpSessionBindingListener接口,保存HttpSession时,对象值会自动更新
1 2 3 4 5 6 7 8 9 10 11 12 public class User implements HttpSessionBindingListener { private String name; public String getName () { return name; } public void valueBound (HttpSessionBindingEvent e) { String name = e.getName(); } public void valueUnbound (HttpSessionBindingEvent e) {} }
14.3. ServletRequestListener ServletRequestListener
对ServletRequest的创建和销毁作出响应
1 2 3 4 5 6 7 8 9 public class AppListener implements ServletRequestListener { public void requestDestroyed (ServletRequestEvent e) {} public void requestInitialized (ServletRequestEvent e) { ServletRequest request=e.getServletRequest(); ServletContext context=e.getServletContext(); } }
ServletRequestAttributeListener
1 2 3 4 5 6 7 8 public class AppListener implements ServletRequestAttributeListener { public void attributeAdded (ServletRequestAttributeEvent e) {} public void attributeRemoved (ServletRequestAttributeEvent e) {} public void attributeReplaced (ServletRequestAttributeEvent e) {} }
AsyncListener
1 2 3 4 5 6 7 8 9 10 11 public class AppListener implements AsyncListener { public void onComplete (AsyncEvent e) throws IOException {} public void onError (AsyncEvent e) throws IOException {} public void onStartAsync (AsyncEvent e) throws IOException {} public void onTimeout (AsyncEvent e) throws IOException {} }
15. 过滤器 权限管理,session管理,统一编码
15.1. 注册 /* 全拦截
/log 特定拦截
注解方式
1 @WebFilter(filterName="",urlPatterns={"/*"})
xml方式
1 2 3 4 5 6 7 8 9 <filter > <filter-name > log</filter-name > <filter-class > com.runaccpeted.filter.LoginFilter</filter-class > </filter > <filter-mappring > <filter-name > log</filter-name > <url-pattern > /*</url-pattern > </filter-mappring >
使用
init 服务器启动则启动
doFilter 核心方法 需要手动放行 chain.doFilter(request, response);
destroy 服务器关闭则关闭
1 2 3 4 5 6 7 8 9 10 11 public class LoginFilter implements Filter { public void destroy () {} public void doFilter (ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest)ServletRequest; HttpServletResponse response = (HttpServletResponse)ServletResponse; chain.doFilter(request, response); } public void init (FilterConfig config) throws ServletException {} }
16. 文件上传下载 1 2 3 4 <form action ="fileUp" enctype ="multipart/form-data" method ="post" > <input type ="file" name ="filename" /> <input type ="submit" > </form >
Servlet
MultipartConfig限制:
maxFileSize文件容量
maxRequestSize 许多部分HTTP请求最大容量
location文件保存到磁盘指定位置
fileSizeThreshold溢出则写入磁盘
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @WebServlet(urlPatterns="/file") @MultipartConfig public class file extends HttpServlet { public void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Part part = request.getPart("filename" ); String file = part.getHeader("content-disposition" ); String[] element=file.split(";" ); for (String str:element) { if (str.trim().startsWith("filename" )){ String temp=str.substring(str.indexOf("=" )+1 ); part.write(System.getProperty("user.dir" )+"/WebRoot/" +temp); } } } }
多文件
1 2 3 4 5 6 7 8 9 public void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Collection<Part> parts = request.getParts(); for (Part path:paths) { if (path.getContentType()!=null ){ } } }
Related Issues not found
Please contact @WTlumos to initialize the comment