Updated on 2017-03-09
https://tomcat.apache.org/index.html
https://tomcat.apache.org/tomcat-9.0-doc/api/allclasses-noframe.html
https://tomcat.apache.org/tomcat-9.0-doc/jspapi/allclasses-noframe.html
https://tomcat.apache.org/tomcat-9.0-doc/servletapi/allclasses-noframe.html
Tomcat
环境变量
变量值 | 变量名 | |
---|---|---|
CATALINA_HOME | D:\Download\apache-tomcat-9.0.0 | 配置 Tomcat 安装路径 |
—————————— | ————————————————— | —————————— |
默认欢迎页
D:\Download\apache-tomcat-9.0.0\conf\web.xml
⇳
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
默认端口号
D:\Download\apache-tomcat-9.0.0\conf\server.xml
⇳
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
去掉空白行
全局
----
D:\Download\apache-tomcat-9.0.0\conf\web.xml
⇳
<init-param>
<param-name>trimSpaces</param-name>
<param-value>true</param-value>
</init-param>
单个页面
----
<%@ page trimDirectiveWhitespaces="true" %>
IDEA Deployment
C:\Users\Administrator\.IntelliJIdea2016.3\system\tomcat\
IDEA Dependence
Project Structure -> Modules -> Dependencies -> Add -> Library -> Tomcat
JSP
指令
page
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="java.util.Arrays" %>
<%@ page import="java.util.HashMap" %>
include
index.jsp
----
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
include 指令:
<%@ include file="date.jsp" %> 声明需要包含的页面
include 动作:
<jsp:include page="date.jsp" flush="false"/> 声明需要包含的页面(flush 是否刷新缓冲区)
</body>
</html>
date.jsp 被包含的页面
----
<%@ page import="java.text.SimpleDateFormat" %>
<%@ page import="java.util.Date" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
out.print(date);
%>
include 指令与 include 动作的对比
include 指令 | include 动作 | |
---|---|---|
静态包含 | 动态包含 | |
生成内容 | 文件内容 | 执行结果 |
生成 Servlet | 合并 | 独立 |
编译时间 | 较慢 | 较快(不解析资源) |
执行时间 | 较快(不解析资源) | 较慢 |
作用时间 | 编译期间 | 请求期间 |
适用页面 | 变化较少 | 经常变化 |
—————— | —————————— | —————————– |
taglib
注释
客户端可见注释:
<!-- HTML 注释 -->
客户端不可见注释:
<%-- JSP 注释 --%>
<%
// Java 单行注释
/*
* Java 多行注释
* */
%>
声明
<%! Servlet 中的成员(可声明为 static)
private String s = "ABC"; 属性
private int add(int x, int y) { 方法
return x + y;
}
%>
脚本
<% Servlet 中的 jspService() 的方法代码
System.out.println("你好"); 输出至控制台
out.println("你好"); 输出至页面(out 是内置对象,是 JspWriter 的实例化对象)
%>
表达式
<%=s%> 调用属性(注意表达式不加分号)
<br>
<%=add(1, 2)%> 调用方法
----
输出:
ABC
3
输出九九乘法表
----
<%! 声明方法
private String a() {
DecimalFormat format = new DecimalFormat("00");
StringBuilder s = new StringBuilder();
for (int i = 1; i <= 9; i++) {
for (int j = 1; j <= i; j++) {
s.append(i).append('*').append(j).append('=').append(format.format(i * j)).append(" "); 空格
}
s.append("<br>"); 换行
}
return s.toString();
}
%>
<%=a()%> 调用方法
生命周期
内置对象
out
request
index.jsp
----
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录页面</title>
</head>
<body>
<h1>登录页面</h1>
<hr>
<form action="doLogin.jsp" name="loginForm" method="post">
<table>
<tr>
<td>账号:</td>
<td><input type="text" name="account"></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" name="password"></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="登录"></td>
</tr>
</table>
</form>
</body>
</html>
doLogin.jsp
----
<%@ page contentType="text/html;charset=UTF-8" language="java" %> 指定输出字符集
<html>
<head>
<title>登录成功</title>
</head>
<body>
<%
request.setCharacterEncoding("UTF-8"); 指定输入字符集
request.setAttribute("str", "欢迎!");
%>
<h1>登录成功</h1>
<hr>
账号:<%=request.getParameter("account")%><br>
密码:<%=request.getParameter("password")%><br>
属性:<%=request.getAttribute("str")%><br>
协议类型:<%=request.getProtocol()%><br>
请求类型:<%=request.getContentType()%><br>
请求大小:<%=request.getContentLength()%> 字节<br>
虚拟路径:<%=request.getContextPath()%><br>
请求路径:<%=request.getServletPath()%><br>
真实路径:<%=request.getServletContext().getRealPath("doLogin.jsp")%><br>
主机名称:<%=request.getServerName()%><br>
主机端口:<%=request.getServerPort()%><br>
客户端 IP 地址:<%=request.getRemoteAddr()%><br>
服务端 IP 地址:<%=request.getLocalAddr()%><br>
</body>
</html>
----
输出:
账号:123456
密码:123456
属性:欢迎!
协议类型:HTTP/1.1
请求类型:application/x-www-form-urlencoded
请求大小:30 字节
虚拟路径:
请求路径:/doLogin.jsp
真实路径:C:\Users\Administrator\IdeaProjects\untitled1\out\artifacts\untitled1_war_exploded\doLogin.jsp
主机名称:localhost
主机端口:8080
客户端 IP 地址:0:0:0:0:0:0:0:1
服务端 IP 地址:0:0:0:0:0:0:0:1
Note:
真实路径:<%=request.getServletContext().getRealPath("doLogin.jsp")%><br>
等同于
真实路径:<%=request.getServletContext().getRealPath(request.getServletPath())%><br>
等同于
真实路径:<%=application.getRealPath(request.getServletPath())%><br>
response
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
response.setContentType("text/html;charset=UTF-8"); 与 page 指令中的 contentType 属性作用相同
response.sendRedirect("request.jsp"); 请求重定向(response)
request.getRequestDispatcher("request.jsp").forward(request, response); 请求转发(request)
等同于
<jsp:forward page="request.jsp"/> JSP 动作:forward
动作 forward 可添加参数:
<jsp:forward page="a.jsp">
<jsp:param name="age" value="25"/> 添加参数
<jsp:param name="sex" value="男"/>
</jsp:forward>
转发后的页面接收参数:
<%=request.getParameter("age")%><br>
%>
</body>
</html>
Note:
请求重定向(客户端行为)(共发起 2 次请求)(游览器地址会改变)(不传递原有请求对象)(response)(302 临时跳转)
请求转发一(服务端行为)(共发起 1 次请求)(游览器地址不改变)(会传递原有请求对象)(request)
session
index.jsp
----
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="java.text.SimpleDateFormat" %>
<%@ page import="java.util.Date" %>
<%@ page import="java.util.Enumeration" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
session.setAttribute("username", "admin");
session.setAttribute("password", "123456");
session.setAttribute("age", 20);
session.setMaxInactiveInterval(3600); 设置生存间隔时间(秒)
%>
Session ID:<%=session.getId()%><br>
Session 一一创建时间:<%=a(session.getCreationTime())%><br>
Session 最近请求时间:<%=a(session.getLastAccessedTime())%><br>
Session 生存间隔时间:<%=session.getMaxInactiveInterval()%> 秒<br>
Session 中保存的属性:<%
Enumeration<String> attributeNames = session.getAttributeNames();
StringBuilder s = new StringBuilder();
while (attributeNames.hasMoreElements()) {
String k = attributeNames.nextElement();
Object v = session.getAttribute(k);
s.append(k).append('=').append(v.toString()).append(" ");
}
out.print(s.toString());
%><br>
</body>
</html>
<%!
private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private String a(long i) {
return dateFormat.format(new Date(i));
}
%>
----
输出:
Session ID:C9E1EDACE8806D15DA4BE0354BBD75E8
Session 一一创建时间:2017-03-11 20:37:55
Session 最近请求时间:2017-03-11 20:43:09
Session 生存间隔时间:3600 秒
Session 中保存的属性:password=123456 age=20 username=admin
Note:
Session 生命周期
----
1. 创建
首次访问(无 JSESSIONID Cookie):发送 Cookie:JSESSIONID=4619A7A93D0DA9622F3FB06F93E2A328
2. 活动
重置 Session 生存间隔时间。
3. 销毁
主动:session.invalidate()、重启 Tomcat、重启浏览器(JSESSIONID Cookie 失效,导致 Session 过期)。
被动:Session 过期。
设置 Session 超时时间(默认 30 分钟)
----
session.setMaxInactiveInterval(1800); 秒
D:\Download\apache-tomcat-9.0.0\conf\web.xml(全局)
⇳
<session-config>
<session-timeout>30</session-timeout> 分
</session-config>
application
application 对象类似于 Java 中的 static 成员,属于 Web APP,由所有用户共享,可用于存放全局变量。
application 对象始于服务器,终于服务器。
----
<%
application.setAttribute("str", "ABC");
application.getAttribute("str");
Enumeration<String> attributeNames = application.getAttributeNames();
while (attributeNames.hasMoreElements()) {
String k = attributeNames.nextElement();
Object v = application.getAttribute(k);
out.print(k + " = " + v + "<br><br>");
}
%>
<%=application.getRealPath(request.getServletPath())%><br>
<%=application.getServerInfo()%><br>
----
输出:
C:\Users\Administrator\IdeaProjects\untitled\out\artifacts\untitled_war_exploded\index.jsp
Apache Tomcat/9.0.0.M18
page
page 对象类似于 Java 中的 this 指针,指代当前 JSP 页面本身,是 java.lang.Object 的实例。
----
<%=page%>
----
输出:
org.apache.jsp.index_jsp@2445d4f1
pageContext
pageContext 对象提供了对 JSP 页面内所有的命名空间的访问,相当于页面中所有功能的集大成者。
----
pageContext.forward("a.jsp"); 请求转发
pageContext.include("a.jsp"); 使当前位置包含另一个页面的内容(类似 include 动作,生成独立的 Servlet)
config
<%
StringBuilder s = new StringBuilder();
Enumeration<String> initParameterNames = config.getInitParameterNames();
while (initParameterNames.hasMoreElements()) {
String k = initParameterNames.nextElement();
String v = config.getInitParameter(k);
s.append(k).append(" = ").append(v).append("<br>");
}
out.print(s.toString());
%>
----
输出:
fork = false
trimSpaces = true
classdebuginfo = true
xpoweredBy = false
exception
index.jsp
----
<%@ page contentType="text/html;charset=UTF-8" language="java" errorPage="a.jsp" %> 指定异常处理页面
<html>
<head>
<title>Title</title>
</head>
<body>
<%
int i = 100 / 0; 将产生运行时异常
%>
</body>
</html>
a.jsp
----
<%@ page contentType="text/html;charset=UTF-8" language="java" isErrorPage="true" %> 设置为异常处理页面(可以使用 exception 对象)
<html>
<head>
<title>Exception</title>
</head>
<body>
<%=exception.toString()%><br> 输出异常信息
</body>
</html>
index.jsp
----
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录页面</title>
</head>
<body>
<h1>登录页面</h1>
<hr>
<form action="doLogin.jsp" name="loginForm" method="post">
<table>
<tr>
<td>账号:</td>
<td><input type="text" name="account"></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" name="password"></td>
</tr>
<tr>
<td><input type="reset" value="重置"></td>
<td><input type="submit" value="登录"></td>
</tr>
</table>
</form>
</body>
</html>
doLogin.jsp
----
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
request.setCharacterEncoding("UTF-8"); 指定输入字符集
String account = request.getParameter("account");
String password = request.getParameter("password");
if ("admin".equals(account) && "123456".equals(password)) {
request.getRequestDispatcher("login_successful.jsp").forward(request, response); 登录成功:请求转发
} else {
response.sendRedirect("login_failed.jsp"); 登录失败:请求重定向
}
%>
login_successful.jsp
----
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录成功</title>
</head>
<body>
<h1>登录成功</h1>
<hr>
欢迎用户:<%=request.getParameter("account")%>
</body>
</html>
login_failed.jsp
----
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录失败</title>
</head>
<body>
<h1>登录失败</h1>
<hr>
<a href="index.jsp">返回登录页面</a>
</body>
</html>
JavaBean
符合某种设计规范的类,用于封装业务数据和业务逻辑,减少代码冗余,提高代码的可维护性。
UserBean
package a;
public class User { 公有类
private String username; 私有属性
private String password;
public User() { 公有的无参构造方法
}
public String getUsername() { 公有 get/set
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
JSP 动作:useBean、set(get)Property
<%@ page import="a.User" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
普通方式
----
<%
User a = new User();
a.setUsername("admin");
a.setPassword("123456");
%>
账户:<%=a.getUsername()%><br>
密码:<%=a.getPassword()%><br>
使用 JSP 动作
----
useBean
<jsp:useBean id="b" class="a.User" scope="page"/> 在指定范围内实例化 JavaBean(默认范围为 page)
setProperty
<jsp:setProperty name="b" property="*"/> 根据表单自动匹配所有属性(跟表单关联)
<jsp:setProperty name="b" property="username"/> 根据表单手动匹配部分属性(跟表单关联)
<jsp:setProperty name="b" property="password"/>
<jsp:setProperty name="b" property="username" value="admin"/> 手动设置属性值
<jsp:setProperty name="b" property="password" value="123456"/>
<jsp:setProperty name="b" property="username" param="abc"/> 根据 URL 参数给属性赋值
<jsp:setProperty name="b" property="password" param="def"/>
<!--http://localhost:8080/index.jsp?abc=123&def=456-->
getProperty
账户:<jsp:getProperty name="b" property="username"/><br>
密码:<jsp:getProperty name="b" property="password"/><br>
</body>
</html>
useBean 作用域范围
----
作用于单个页面的生命周期:page
作用于单个请求的生命周期:request
作用于整个会话的生命周期:session
作用于整个应用的生命周期:application
https://tomcat.apache.org/tomcat-9.0-doc/jspapi/javax/servlet/jsp/PageContext.html#PAGE_SCOPE
https://tomcat.apache.org/tomcat-9.0-doc/jspapi/javax/servlet/jsp/JspContext.html#setAttribute-java.lang.String-java.lang.Object-int-
User.java 用封装业务数据
----
package a;
public class User {
private String username;
private String password;
public User() {
}
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;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
UserDAO.java 用于封装业务逻辑
----
package a;
public class UserDAO {
public boolean userLogin(User user) {
return "admin".equals(user.getUsername()) && "123456".equals(user.getPassword());
}
}
index.jsp
----
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录页面</title>
</head>
<body>
<h1>登录页面</h1>
<hr>
<form action="doLogin.jsp" name="loginForm" method="post">
<table>
<tr>
<td>账号:</td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" name="password"></td>
</tr>
<tr>
<td><input type="reset" value="重置"></td>
<td><input type="submit" value="登录"></td>
</tr>
</table>
</form>
</body>
</html>
doLogin.jsp
----
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<jsp:useBean id="userDAO" class="a.UserDAO"/> 默认生命周期为 page
<jsp:useBean id="loginUser" class="a.User" scope="session"/> 指定生命周期为 session
<jsp:setProperty name="loginUser" property="*"/> 根据表单自动匹配所有属性
<%
request.setCharacterEncoding("UTF-8"); 指定输入字符集
if (userDAO.userLogin(loginUser)) {
request.getRequestDispatcher("login_successful.jsp").forward(request, response); 登录成功:请求转发
} else {
response.sendRedirect("login_failed.jsp"); 登录失败:请求重定向
}
%>
login_successful.jsp
----
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<jsp:useBean id="loginUser" class="a.User" scope="session"/> 在整个 Session 中只有同一个 loginUser
<html>
<head>
<title>登录成功</title>
</head>
<body>
<h1>登录成功</h1>
<hr>
欢迎用户:<%=loginUser.getUsername()%>
</body>
</html>
login_failed.jsp
----
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录失败</title>
</head>
<body>
<h1>登录失败</h1>
<hr>
<a href="/">返回登录页面</a>
</body>
</html>
Cookie
index.jsp
----
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
String username = "";
String password = "";
Cookie[] cookies = request.getCookies();
if (cookies != null && cookies.length > 0) {
for (Cookie c : cookies) {
if (c.getName().equals("username")) {
username = c.getValue();
}
if (c.getName().equals("password")) {
password = c.getValue();
}
}
}
%>
<html>
<head>
<title>登录页面</title>
</head>
<body>
<h1>登录页面</h1>
<hr>
<form action="doLogin.jsp" name="loginForm" method="post">
<table>
<tr>
<td>账号:</td>
<td><input type="text" name="username" value="<%=username%>"></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" name="password" value="<%=password%>"></td>
</tr>
<tr>
<td colspan="2"><input type="checkbox" name="isUseCookie" checked>记住登录状态</td>
</tr>
<tr>
<td><input type="reset" value="重置"></td>
<td><input type="submit" value="登录"></td>
</tr>
</table>
</form>
</body>
</html>
doLogin.jsp
----
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<jsp:useBean id="userDAO" class="a.UserDAO"/>
<jsp:useBean id="loginUser" class="a.User" scope="session"/>
<jsp:setProperty name="loginUser" property="*"/>
<%
request.setCharacterEncoding("UTF-8");
if (userDAO.userLogin(loginUser)) {
request.getRequestDispatcher("login_successful.jsp").forward(request, response);
} else {
response.sendRedirect("login_failed.jsp");
}
%>
login_successful.jsp
----
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<jsp:useBean id="loginUser" class="a.User" scope="session"/>
<%
String isUseCookie = request.getParameter("isUseCookie");
if (isUseCookie != null) {
Cookie username = new Cookie("username", loginUser.getUsername()); 创建
Cookie password = new Cookie("password", loginUser.getPassword());
username.setMaxAge(86400); 设置 Cookie 有效期为 1 天(单位:秒)(若未设置,默认为浏览会话结束时过期)
password.setMaxAge(86400);
response.addCookie(username); 写入
response.addCookie(password);
} else {
Cookie[] cookies = request.getCookies(); 读取
if (cookies != null && cookies.length > 0) {
for (Cookie c : cookies) {
if (c.getName().equals("username") || c.getName().equals("password")) {
c.setMaxAge(0); 设置 Cookie 立即过期
response.addCookie(c); 写入
}
}
}
}
%>
<html>
<head>
<title>登录成功</title>
</head>
<body>
<h1>登录成功</h1>
<hr>
<a href="user.jsp">查看用户信息</a>
</body>
</html>
login_failed.jsp
----
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
Cookie[] cookies = request.getCookies();
if (cookies != null && cookies.length > 0) {
for (Cookie c : cookies) {
if (c.getName().equals("username") || c.getName().equals("password")) {
c.setMaxAge(0);
response.addCookie(c);
}
}
}
%>
<html>
<head>
<title>登录失败</title>
</head>
<body>
<h1>登录失败</h1>
<hr>
<a href="/">返回登录页面</a>
</body>
</html>
user.jsp
----
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
String username = "";
String password = "";
Cookie[] cookies = request.getCookies();
if (cookies != null && cookies.length > 0) {
for (Cookie c : cookies) {
if (c.getName().equals("username")) {
username = c.getValue();
}
if (c.getName().equals("password")) {
password = c.getValue();
}
}
}
%>
<html>
<head>
<title>用户信息</title>
</head>
<body>
<h1>用户信息</h1>
<hr>
账户:<%=username%><br>
密码:<%=password%><br>
</body>
</html>
Cookie 与 Session 的对比
Session | Cookie | |
---|---|---|
保存位置 | 服务端 | 客户端 |
保存类型 | Object 类 | String 类 |
保存数据 | 保存 重要 的数据 | 保存 不重要 的数据 |
保存时间 | 随 会话结束 而结束 | 可以 长期 保存至客户端 |
————— | ————————– | ——————————– |