文章目录
1. Web概述
1.1 常见的Web服务器
- Tomcat:Apache组织提供的开源的、免费的Web服务器。满足EE的Servlet和JSP规范。
- WebSphere
- WebLogic
- IIS
- Apache:应用在PHP平台上。
2. Tomcat服务器
2.1 下载 & 安装
访问官方网站。
下载 Tomcat 7 版本。
解压到任意路径(如C盘根目录)。
2.2 运行
进入 bin 目录,运行 startup.bat。
然后在浏览器中访问 localhost:8080,访问成功则说明成功了。
2.3 解决控制台乱码
修改 conf 目录下的 logging.properties 文件即可。
2.4 配置环境变量
Tomcat运行需要依赖Java环境,因此要配置 JAVA_HOME 环境变量。
2.5 修改端口号
默认情况下,Tomcat端口号是8080。
修改端口号,只需要修改 conf 目录下的 server.xml 即可。
2.6 Tomcat目录结构
- bin:二进制文件。
- conf:配置文件。
- lib:Tomcat 所需要的jar包。
- logs:日志文件。
- temp:临时文件。
- webapps(重要):需要运行的Web项目。
- work:JSP 编译成 Servlet 产生的代码。
2.7 动态Web资源的目录结构
假如有一个项目 Website,其结构如下:
- 根目录:存放静态页面(如HTML、CSS、JS)。也可以放动态页面 JSP。
- WEB-INF 目录:其中必须含有 web.xml 文件,存放一些配置。还有 classes(可选)。还有 lib 目录(可选),存放开发中需要使用到的第三方jar包。
2.8 Tomcat的项目发布方式
方式一
直接将项目复制到 webapps 文件夹。
例如,创建项目目录 aaa,在其中添加 index.html 文件,然后将整个目录复制到 webapps 文件夹下,启动 Tomcat 服务器。
在浏览器中访问的地址是:http://localhost:8080/hello-world/
方式二(不推荐)
在 conf 目录下的 server.xml 配置 Tomcat 的虚拟路径。
Q:什么是虚拟路径?
A:配置一个虚拟路径,与一个真实的路径绑定,然后访问这个虚拟路径就能找到真实路径。
例如,在C盘根目录创建项目文件夹 hello-world(同方式一)。
修改 conf 目录下的 server.xml 文件。
启动服务器,在浏览器中访问的地址是:
方式三
在 /conf/Catalina/localhost 下配置 Tomcat 的虚拟路径。
第二种方式官方并不推荐,因为需要修改 server.xml 核心配置文件,牵一发而动全身。下面演示第三种方式:
在 \conf\Catalina\localhost 目录下创建 haohao.xml 文件(xml的文件名即表示虚拟路径)。
启动 Tomcat 服务器,在浏览器中访问的地址为:
2.9 IDEA整合Tomcat
目录结构说明
2.10 虚拟主机配置
以下示例演示了如何制作一个钓鱼的“百度”页面。
创建项目文件
在 C:\baidu\website 目录下创建 index.html 文件:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>百度</title>
</head>
<body>
<h1>百度</h1>
<p>假装我是一个百度qvq</p>
</body>
</html>
创建虚拟主机路径
修改 server.xml,创建虚拟主机。这里 baidu 是虚拟主机的目录,website 是项目名称。
复制上面的 Host 标签改改即可。
修改hosts文件
hosts 文件路径:C:\Windows\System32\drivers\etc\hosts
在 hosts 文件末尾添加一行:
127.0.0.1 www.gengdu.com
启动服务器
启动服务器,然后在浏览器中进行测试:
http://www.gengdu.com:8080/
3. Servlet
3.1 什么是Servlet?
Servlet 是一个运行在 web 服务器上的小 Java 程序,用于处理 web 客户端发送的请求,并且做出响应,使用的是 HTTP 协议。
Servlet 是一个接口。
3.2 Hello world
3.2.1 创建包
3.2.2 创建 Servlet 类
3.2.3 编写GET请求的响应代码
3.3.4 配置 web.xml 文件
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- 配置Servlet -->
<servlet>
<!-- 配置Servlet的名称(随便取) -->
<servlet-name>HelloServlet</servlet-name>
<!-- 配置Servlet类的全路径 -->
<servlet-class>xyz.genghao.servlet.demo1.HelloServlet</servlet-class>
</servlet>
<!-- 配置Servlet的映射 -->
<servlet-mapping>
<!-- 配置Servlet的名称(与上面对应) -->
<servlet-name>HelloServlet</servlet-name>
<!-- 配置访问URL -->
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
3.3.5 配置运行参数
主要是修改URL根路径,当然不修改也没关系。
3.3.6 启动项目
按正常启动 Java 项目的方法运行即可,此时 Tomcat 服务器启动,在浏览器中输入网址即可查看到页面。
3.3 Servlet类的继承体系
3.4 Servlet的生命周期
- 执行Servlet构造器方法
- 执行init初始化方法
- 执行service方法
- 执行destroy方法
第1、2步是在第一次访问的时候实例化Servlet类时会调用;
第3步每次访问都会调用;
第4步在Web工程停止的时候调用。
3.5 Servlet的启动时加载
Servlet 对象是第一次被访问时被创建,init 方法就会执行。假设在 init 方法中做了比较耗时的操作,第一个用户等待的时间会较长。解决方案——启动时加载,即在服务器启动时创建 Servlet 对象。
创建 Servlet 类:
package xyz.genghao.servlet.demo1;
import javax.servlet.*;
import java.io.IOException;
public class ServletDemo implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("Servlet对象被初始化了!");
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
修改 web.xml:
注意,这里的优先级不能高于 1 , 1 是 Tomcat 中默认的 Servlet 的优先级。可以在 conf 目录下的 web.xml 中进行查看:
3.6 Servlet访问路径(URL)的配置
配置 web.xml 中的 url-pattern 标签。有三种配置方式。
完全路径匹配
以“/”开始,比如 /aaa/servlet-demo 。
目录匹配
以“/”开始,以“/*”结束。比如 /aaa/bbb/* 。
例如,设置 url-pattern 为 /hello/* ,那么如下 URL 都可以匹配上:
http://localhost:8080/hello
http://localhost:8080/hello/
http://localhost:8080/hello/a/b/c/d/
扩展名匹配
不能以“/”开始,以“*”开始。比如 *.action *.jsp 。
优先级
完全路径匹配 > 目录匹配 > 扩展名匹配
3.7 ServletConfig对象(不重要)
ServletConfig 用来获得 Servlet 的相关配置的对象。
不是很重要,略。
3.8 ServletContext对象
ServletContext,即 Servlet 的上下文对象。这个对象一个 Web 项目只有一个,在服务器启动时为每个 Web 项目创建一个单独的 ServletContext 对象。
特点:
- ServletContext是一个接口,它表示Servlet上下文对象。
- 一个Web工程,只有一个ServletContext对象实例。
- ServletContext对象是一个域对象。
- ServletContext是在Web工程部署启动的时候创建,在Web工程停止的时候销毁。
域对象:可以像Map一样存取数据的对象,这里的域指的是存取数据的操作范围。
三个方法:setAttribute()、getAttribute()、removeAttribute()
四个作用:
- 获取web.xml中配置的上下文参数context-param
- 获取当前的工程路径
- 获取工程部署到服务器硬盘上的绝对路径
- 像Map一样存取数据
读取Web项目中的文件
在 WEB-INF 目录中创建 info.properties 文件:
创建 Servlet 类:
注意,getServletContext().getResourceAsStream()方法是以 web 目录为根目录的。
package xyz.genghao.servlet.demo1;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Properties;
public class HelloServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
InputStream is = getServletContext().getResourceAsStream("/WEB-INF/info.properties");
Properties properties = new Properties();
properties.load(is);
String username = properties.getProperty("username");
String password = properties.getProperty("password");
PrintWriter responseWriter = response.getWriter();
responseWriter.println("Username: " + username);
responseWriter.println("Password: " + password);
}
}
作为域对象存取数据
通过 this.getServletContext() 方法获得对象,它有三个域对象的方法。
三个方法:
- setAttribute(String name, Object object):向域对象存入数据。
- getAttribute(String name):取出数据。
- removeAttribute(String name):删除数据。
ServletContext 对象的作用范围:
从服务器启动,直到服务器关闭,ServletContext 对象才被销毁,其中的数据才会失效。
3.9 Response对象
3.9.1 Response关于响应行的方法
设置响应状态码
设置响应的状态码:
- 200:OK
- 400:Bad Request
- 500:Internal Server Error
- 404:Not Found
- 401:Unauthorized
3.9.2 Response关于响应头的方法
设置响应头
3.9.3 Response关于响应体的方法
修改返回的网页内容
3.9.4 Response其他API
增加Cookie
请求重定向
setContentType
3.9.5 Response响应中文乱码的解决
使用字节流输出中文
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class HelloServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 设置浏览器解析时采用的字符集
response.setHeader("Content-Type", "text/html;charset=UTF-8");
// 设置字符串转字节数组的编码
byte[] data = "我是中文".getBytes("UTF-8");
ServletOutputStream outputStream = response.getOutputStream();
outputStream.write(data);
}
}
使用字符流输出中文
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class HelloServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 设置浏览器解析时采用的字符集
response.setHeader("Content-Type", "text/html;charset=UTF-8");
// 设置response获得的字符流缓冲区的编码
response.setCharacterEncoding("UTF-8");
response.getWriter().println("我是中文");
}
}
3.10 Request对象
3.10.1 获取客户机信息
获取请求方式GET/SET
获取查询字符串
获取请求地址
获取客户端的IP地址
3.10.2 获取请求头的方法
获取请求头
3.10.3 获取请求参数的方法
获取请求参数
既可以获得 GET 请求的查询字符串,也可以获得 POST 请求的表单信息。
解决乱码问题(重点)
表单 POST 出现乱码的原因:
POST 方式提交的数据是在请求体中,request 对象接收到数据后,放入 request 的缓冲区中。缓冲区默认的编码是 ISO-8859-1 不支持中文。
解决方案:
修改 request 缓冲区的编码。
表单 GET 出现乱码的原因:
GET 方式提交的数据在请求行的 URL 后面,而 URL 是会对中文进行编码的。
解决方案:
将存入到 request 缓冲区中的值以 ISO-8859-1 的方式获取到,再以 UTF-8 解码。
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLDecoder;
import java.net.URLEncoder;
public class HelloServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
String name = request.getParameter("name");
System.out.println("POST:" + name);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String name = request.getParameter("name");
String encode = URLEncoder.encode(name, "ISO-8859-1");
String decode = URLDecoder.decode(encode, "UTF-8");
System.out.println("GET:" + decode);
}
}
可用以下 HTML 进行测试:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/hello" method="get">
<label>姓名:</label>
<input type="text" name="name">
<input type="submit" value="GET提交">
</form>
<form action="/hello" method="post">
<label>姓名:</label>
<input type="text" name="name">
<input type="submit" value="POST提交">
</form>
</body>
</html>
3.10.4 Request作为域对象存取数据的方法
3.11 会话技术
3.11.1 实现原理
会话技术的分类:
- Cookie:客户端技术,程序把每个用户的数据以 Cookie 的形式保存到各自的浏览器中。当用户使用浏览器访问服务器时,就会带着 Cookie 过去。
- Session:服务器端技术,服务器在运行时为每个用户的浏览器创建一个独享的 Session 对象。每个用户访问服务器时可以把各自的数据放在各自的 Session 中。
区别:一个将数据保存在客户端,一个保存在服务器端。
3.11.2 使用Cookie记录用户上次访问时间
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
public class HelloServlet extends HttpServlet {
// 获取特定名称的Cookie
private Cookie getCookie(Cookie[] cookies, String name) {
if (cookies == null)
return null;
for (Cookie cookie : cookies) {
if (name.equals(cookie.getName())) {
return cookie;
}
}
return null;
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取所有Cookie
Cookie[] cookies = request.getCookies();
Cookie cookie = getCookie(cookies, "lastTime");
if (cookie == null) {
response.getWriter().println("It's your first time to visit me!");
} else {
String lastTime = cookie.getValue();
response.getWriter().println("Hello! Your last time is: " + lastTime);
}
// 构造Cookie对象
Cookie newCookie = new Cookie(
"lastTime",
new Date().toString()
);
// 服务器向客户端回写Cookie
response.addCookie(newCookie);
}
}
第一次访问,查看响应头:
第二次访问,查看请求头:
3.11.3 Cookie的有效时长
如果不设置有效时间,默认情况下,在关闭浏览器后 Cookie 被销毁(存在浏览器内存中)。
使用持久级别的 Cookie,浏览器会将其内容持久化到硬盘上。
修改 Cookie 的有效时长:
如果参数为 -1,表示当浏览器关闭后清除 Cookie;如果参数为 0,表示立即删除该 Cookie。
3.11.4 Cookie的有效路径和有效域名
3.11.5 Session的使用
获取 Session 对象,调用 request 对象的方法:
HttpSession 对象的方法: