Tomcat
Web服务器软件
- 服务器:安装了服务器软件的计算机
- 服务器软件:接收用户请求,处理请求,做出响应
- Web服务器软件:用户通过浏览器进行访问我们部署的项目
- webLogic:oracle公司,大型JavaEE服务器,收费,支持所有的JavaEE规范
- webSphere:IBM公司,大型JavaEE服务器,收费,支持所有的JavaEE规范
- JBOSS:JBOSS公司,大型JavaEE服务器,收费,支持所有的JavaEE规范
- Tomcat:Apache基金组织,中小型JavaEE服务器,仅仅支持少量的JavaEE规范,开源的,免费的
下载、安装、卸载
下载:tomcat.apache.org(Tomcat 8)
安装:解压压缩包即可(路径不要含中文)
卸载:删除文件夹
bin 可执行文件 |
启动
- 双击bin/startup.bat
- 访问:127.0.0.1:8080,有页面说明访问成功(127.0.0.1可写为localhost)
启动遇到的问题
黑窗口一闪而过
原因:没有配置JAVA_HOME
在环境变量中新建JAVA_HOME,值为jdk的路径,不包括bin目录
然后将PATH中的…/bin(jdk的路径)改为%JAVA_HOME%/bin
启动报错
原因:端口被占用,两种方法
找到占用8080端口的进程杀死
修改自身的端口号
conf/server.xml文件
修改port
一般会将tomcat的默认端口号修改为80(浏览器默认端口号)
关闭
- 正常关闭
- shutdown.bat
- Ctrl + C
- 强制关闭
部署项目
- 直接将项目(这里假设为hello)放到webapps文件夹中即可
- */hello:项目的访问路径,虚拟路径
- 简化部署:打包为war包,将war包复制到webapps下,war包会自动解压缩
- 缺点:必须拷贝到webapps中
- config/server.xml
<Host ...> |
- 缺点:不安全,弄坏配置文件
- /conf/Catalina/localhost
- 创建一个文件xxx.xml(任意名称)
- 编写<Context docBase=”项目路径” />
- 虚拟目录就是xml文件的名称
Java动态项目的目录结构
根目录 |
Tomcat集成到IDEA中
Run –> Edit Configurations -> Defaults -> Tomcat Server -> Local -> Configure -> Tomcat安装目录
Servlet(server applet)
概念
Servlet就是一个接口,定义了Java类被浏览器访问到(tomcat)识别的规则。
快速入门
- 创建JavaEE项目
- 定义一个类实现Servlet接口
- 实现接口中的抽象方法
- 配置Servlet
package web; |
配置Servlet(web.xml)
<!--Servlet配置--> |
Servlet执行原理
- 解析URL请求路径,获取Servlet的资源路径
- 查找web.xml中是否有对应的<url-pattern>标签内容
- 查找<servlet-class>全类名
- tomcat将字节码文件加载进内存,并且创建其名称
- 调用其方法
Servlet生命周期方法
init
- 在Servlet创建时执行,只会执行一次
- 默认情况第一次被访问时创建Servlet
- 配置<servlet>下的<load-on-startup>可修改Servlet创建时机
- 负数,第一次被访问时创建
- 0或正数,服务器启动时创建
- 配置<servlet>下的<load-on-startup>可修改Servlet创建时机
- Servlet是单例的
- 多个用户同时访问时,可能存在线程安全问题
- 解决:尽量不要在Servlet中定义成员变量,定义了成员变量,也不要进行赋值
service
- 提供服务的方法,每一次Servlet访问时执行
destroy
- Servlet被杀死时被执行(服务器被正常关闭时)
- 在Servlet被销毁之前执行
getServletConfig(了解)
- 获取Servlet的配置对象
getServletInfo(了解)
- 获取Servlet的信息(版本、作者…)
Servlet3.0注解配置
Servlet3.0
- 支持注解配置
- 创建JavaEE项目,勾选servlet3.0以上版本,可以不勾选web.xml
- 定义类实现Servlet接口,实现方法
- 在类上使用@WebServlet注解
@WebServlet(“资源路径”)
Servlet体系结构
Servlet –> GenericServlet –> HttpServlet
- GenericServlet:将Servlet接口除service()外进行了空实现,只对service()进行了抽象
- HttpServlet:对http协议封装,简化操作
- doGet()
- doPost()
Servlet url_pattern配置
可以定义多个访问路径:@WebServlet({“/d4”,”/dd4”,”/ddd4”})
- /xxx
- /xxx/xxx(目录结构)
- /xxx/*(*是通配符,优先级较低)
- *.do(*表示任意,.do代表后缀名,如/demo4.do)
HTTP
规定请求消息和响应消息的格式。
特点:
- 基于TCP/IP的高级协议
- 默认端口号:80
- 基于请求响应模型,一次请求对应一次响应
- 无状态的:每次请求相互独立
历史版本:
- 1.0:每一次请求响应会建立新的连接
- 1.1:复用连接
请求消息数据格式
- 请求行
- 请求头
- 请求空行
- 请求体
请求方式(七种,只介绍常见两种):
- GET:
- 参数在请求行中,在url后
- 请求的url长度有限制
- 不太安全
- POST
- 参数在请求体中
- 请求的url长度没有限制
- 相对安全
请求头:
- Host:主机
- User-Agent:使用的浏览器版本信息
- Accept:可以接受什么格式
- Accept-Language:可接受的语言
- Referer:告诉服务器我从哪里来,作用
- 防盗链
- 统计信息
- Connection:keep-alive(连接不会断开,可复用)
请求正文:
- 封装POST请求消息的请求参数的
Request
Request和Response原理:
- tomcat根据url创建对应的Servlet对象
- tomcat服务器会创建request和response对象,request对象中封装的是请求消息数据
- tomcat将request和response传递给service方法,并调用service方法
- 程序员通过request对象获取请求消息数据,通过response对象设置响应数据
- 服务器在做出响应之前,会用response对象中拿程序员设置的响应消息数据
Request继承结构:
ServletRequest(接口) –> HttpServletRequest(接口) –> RequestFacade(类,Tomcat编写)
获取请求消息数据
- 获取请求行
格式:GET 虚拟路径/Servlet路径?参数 HTTP/1.1
获取请求方式:getMethod
获取虚拟目录:getContextPath
获取Servlet路径:getServletPath
获取请求参数:getQueryString
获取URI:getURI
获取URL:getURL
获得协议及版本:getProtocol
获取客户机的IP地址:getRemoteAddr
URL < URI
- 获取请求头
- 通过请求头的名称获取请求头的值:getHeader(String name)
- 获取所有的请求头名称:Enumeration<String> getHeaderNames()
- 获取请求体
- 获取流数据
- 字符流:BufferedReader getReader()
- 字节流:ServletInputStream getInputStream()
- 再从流对象中
- 获取流数据
其他功能
- 获取请求方法通用方式(get和post都可以)
- **String getParameter(String name)**:根据参数名称获取参数值
- String[] getParameterValues(String name):根据参数名称获取参数值的数组(多用于复选框)
- Enumeration getParameterNames():获取所有请求的参数名称
- Map<String, String[]> getParameterMap:获取所有参数的Map集合
中文乱码问题:
get:tomcat 8已经解决
post:设置流的编码
- resquest.setCharacterEncoding(“utf-8”)
请求转发:一种在服务器内部的资源跳转的方式
- 通过request对象获取请求转发器对象:RequestDispatcher getRequestDispatcher(String path)
- 使用RequestDispatcher进行转发:forward(ServletRequest request, ServletResponse response)
特点:
- 浏览器地址栏路径没有发生变化
- 只能转发到当前服务器内部资源中
- 转发是一次请求
共享数据
- 域对象:一个有作用范围的对象,可以在范围内共享对象
- request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据
- 方法
- setAttribute(String name, Obkect obj):存储数据
- Object getAttribute(String name):通过键获取值
- void removeAttribute(String name):删除键值对
获取ServletContext
- ServletContext getServletContext()
开发步骤:
- 创建项目,导入html,配置文件,jar包
- 创建数据库环境,User表
- 创建实体类User
- 创建UserDao,操作数据库中User表的类
BeanUtils
简化数据封装
Map<String String[]) map = req.getParameterMap(); |
响应消息数据格式
- 响应行
- 响应头
- 响应空行
- 响应体
响应行:
协议以及版本:HTTP/1.1
响应状态码:200
1xx:服务器接客户端消息但是没有接收完成,一段时间后服务器向客户端询问是否还有数据发送
2xx:成功。
- 200
3xx:重定向。
302(重定向)
304(访问缓存)
4xx:客户端错误。
404(请求路径没有对应的资源)
405(请求方式没有对应的doXxx方法)
5xx:服务器端错误。
- 500(服务器内部出现异常)
状态码的描述:OK
响应头:
- 格式
- 名称:值
- 常见响应头
- Content-Type:服务器告诉客户端响应体数据格式以及编码格式
- Content-disposotion:服务器告诉客户端以什么格式打开我的响应体
- in-line:默认值,在当前页面打开
- attachment:以附件形式打开(文件下载)
响应体:
- 真实传输的数据
Response
功能:设置响应消息的
- 设置响应行
- 设置状态码:setStatus(int sc)
- 设置响应头:
- setHeader(String name, String value)
- 设置响应体
- 获取输出流
- 字符输出流:PrintWriter getWriter()
- 字节输出流:ServletOutputStream getOutputStream()
- 使用输出流,将数据输出到客户端浏览器
- 获取输出流
重定向:
- 设置状态码302
- 设置响应头location
简单重定向方法:
- sendRedirect(String url)
重定向的特点:
- 地址栏发生变化
- 可以访问其他站点(服务器)的资源
- 两次请求(不可用Request域对象共享数据)
路径写法:
- 相对路径:当前资源与访问资源的路径关系(./index.html = index.html)
- 绝对路径:(/responseDemo2)
- 给客户端浏览器使用(a标签,表单,重定向等):需要加虚拟目录(项目访问路径)
- req.getContextPath:动态获取虚拟目录
- 给服务器端使用:不需要加虚拟目录(如转发)
输出字符/字节:
- 乱码问题:浏览器默认以GBK解码(与操作系统有关,Windows在中文环境下是GBK)
response.setHeader("content-type", "text/html;charset=utf-8");
//简便写法
response.setContentType("text/html;charset=utf-8");
验证码:
int width = 100;
int height = 50;
//设置图片的宽高和类型
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//美化图片
//获取画图对象
Graphics g = image.getGraphics();
//设置背景色
g.setColor(Color.PINK);
g.fileRect(0, 0, width, height);
//设置边框色以及绘制
g.setColor(Color.BLUE);
g.drawRect(0,0 width - 1, height - 1);
//获取随机字符并绘制
String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
Random ran = new Random();
for (int i = 1; i <= 4; i++) {
index = ran.nextInt(str.length());
char ch = str.charAt(index);
g.drawString(ch+"", 20*i, 25);
}
//设置干扰线
g.setColor(Color.GREEN);
for (int i = 0; i < 10; i++) {
int x1 = ran.nextInt(width);
int x2 = ran.nextInt(width);
int y1 = ran.nextInt(height);
int y2 = ran.nextIne(height);
g.drawLine(x1, y1, x2, y2);
}
//绘制到浏览器中
ImageIO.writer(image, "jpg", response.getOutputStream());
ServletContext
概念:代表整个Web应用,可以和程序的容器来通信。
获取:
- request对象获取:request.getServletContext()
- HttpServlet的方法:this.getServletContext()
功能:
获取MIME类型
MIME:互联网通信过程中定义的一种文件数据类型
- 格式:大类型/小类型(text/html image/jpeg)
String getMimeType(String file)
- ```java
String fileName = “a.jpg”;
String mimeType = servletContext.getMimeType(fileName);
2. 域对象:共享数据
- 方法:
- setAttribute(String name, Object value)
- getAttribute(String name)
- removeAttribute(String name)
- 范围:
- 所有用户所有请求的数据
3. 获取文件的真实路径(服务器路径)
- 方法:
- String getRealPath(String path)
- ```java
//web目录下资源访问
getRealPath("/a.txt");
//WEB-INf目录下资源访问
getRealPath("/WEB-INF/b.txt");
//src目录下资源访问
getReadPath("/WEB-INf/classes/c.txt");
- ```java
Cookie
会话:
概念:一次会话(浏览器第一次发生请求,直到一方断开)包含多次请求和响应
功能:一次会话的多次请求间共享数据
方式:
- 客户端:Cookie
- 服务器:Session
将数据保存到客户端,使用步骤:
- 创建Cookie对象,绑定数据
- new Cookie(String name, String value)
- 发送Cookie对象
- response.addCookie(Cookie cookie)
- 获取Cookie,得到数据
- Cookie[] request.getCookies()
package web; |
package web; |
实现原理:
response发送响应头:set-cookie:msg=hello
request发送请求头:Cookie:mas=hello
细节:
- 一次可不可以发送多个Cookie
- 可以
- Cookie能在浏览器中保存多长的时间
- 默认:浏览器关闭时Cookie数据被销毁
- 持久化存储:
- cookie.setMaxAge(int seconds)
- 正数:将Cookie数据写到硬盘的文件中,数值表示存活时间
- 负数:默认值
- 0:删除Cookie信息
- cookie.setMaxAge(int seconds)
- Cookie能不能存中文
- Tomcat 8之前不能直接存储中文信息,Tomcat 8之后可以
- Cookie共享问题
- 一个Tomcat服务器部署了多个web项目,在这些项目中cookie能不能共享
- 默认不能共享
- setPath(String path):设置Cookie的获取范围,默认情况设置当前的虚拟目录
- 不同的Tomcat服务器间Cookie共享问题
- setDomain(String path):如果一级域名相同,那么多个服务器之间Cookie可以共享
- 一个Tomcat服务器部署了多个web项目,在这些项目中cookie能不能共享
特点:
Cookie存储数据在浏览器
浏览器对于单个Cookie的大小有限制(4KB),数目也有限制(20个)
作用:
- 一般用于存在少量不太敏感的数据
- 在不登录的情况下,完成服务器对客户端的身份识别
案例:记住上一次登录时间
package web; |
Session
概念:服务器端会话技术,用以保存一次请求的数据,相关类为HttpSession
- HttpSession session = request.getSession();
方法(Session是域对象):
- setAttribute
- getAttribute
- removeAttribute
原理:Session的实现是依赖于Cookie的
细节:
客户端关闭,服务器不关闭获取的Session是同一个吗
不是
```java
//如果希望是同一个,可以这么写
Cookie c = new Cookie(“JSESSIONID”, session.getId());
c.setMaxAge(60 * 60);
response.addCookie(c);
2. 服务器关闭,客户端关闭,获取的Session是同一个吗
- 不是,但是要确保数据不丢失(Tomcat已经实现了)
- Session的钝化:保存在硬盘中
- Session的活化:由硬盘加载到内存中
3. Session什么时候被销毁
1. 服务器关闭
2. Session对象调用invalidate()
3. Session的默认失效时间(30分钟)
特点:
1. 存储在服务器
2. 可以存储任意类型,任意大小的数据
> Session与Cookie的区别:
>
> 1. Session存储于服务器,Cookie存储于浏览器
> 2. Session没有数据大小限制,Cookie有
> 3. Session数据相对安全,Cookie相对不安全
## JSP
JSP(Java Server Page):
- 既可以写html,又可以写Java。
原理:
- index.jsp –> index_jsp.java –> index_jsp.class
- JSP本质上就是一个Servlet
JSP脚本:JSP定义Java代码的方式
1. \<% 代码 %\>:转换后在servive方法中,service方法中能写什么,就能写什么
2. \<%! 代码 %\>:JSP转换后在的Java类的成员位置,所以只能写成员变量和成员方法
3. \<%= 代码 %\>:转换为输出语句,输出语句能什么,该脚本就可以定义什么
- \<%= i %\>
JSP内置对象
- 在JSP页面中不需要获取和创建,可以直接使用的对象
- 一共有9个内置对象
- request(域对象):一次请求间共享数据
- response:响应对象
- out:字符输出流,可以将数据输出到页面上
- > response.getWriter()与out的区别:
>
> - Tomcat服务器响应时,先找response缓冲区,然后找out缓冲区
> - response.getWriter()输出永远在out之前
- pageContext(域对象):当前页面共享数据,还可以获取其他8个内置对象
- session(域对象):一次会话的多个请求间共享数据
- application(域对象):所有用户间共享数据
- page:当前页面的对象
- config:Servlet的配置对象
- exception:异常对象
指令:
1. 作用:用于配置JSP页面,导入资源文件
2. 格式:\<%@ 属性名=属性值 …\>
3. 分类:
1. page:配置页面
1. contentType:等同于response.setContentType()
2. language:java
3. buffer:缓冲区大小,默认8KB
4. import:导包
5. errorPage:错误页面,发送异常后跳转到指定的错误页面
6. isErrorPage:标识当前页面是否为errorPage(设为true可以使用exception内置对象)
2. include:导入资源文件
- \<%@ include file="top.jsp"\>
3. taglib:导入资源
- <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core">
注释:
1. HTML注释
- \<!-- --\>
2. JSP注释(推荐使用)
- \<%-- --%\>
## MVC开发模式
演变:
1. Servlet
2. JSP,在JSP中写Java代码和HTML标签,难以维护,难以分工
3. Java Web借鉴MVC开发模式
MVC:
1. M:Model(JavaBean)
- 业务逻辑操作,如查询数据库
2. V:View(JSP)
- 展示数据
3. C:Controller(Servlet)
- 获取客户端输入
- 调用Model
- 将数据交给View
优点:
1. 耦合性低,方便维护,利于分工协作
2. 重用性高
缺点:
- 使得项目结构复杂,对开发人员要求高,需要精心设计
## EL
概念:Expression Language:表达式书写,替换和简化JSP页面中Java代码的编写
语法:${表达式}
注意:JSP默认支持EL表达式
- 在$前加入\可忽略EL表达式
- 在page指令中设置isELIgnored="true"该JSP种EL表达式全部忽略
使用:
1. 运算
1. +, -, *, /(div), %(mod)
2. \> < >= <= == !=
3. &&(and) ||(or) !(not)
4. empty:用以判断字符串、集合、数组对象是否为null或长度是否为0
2. 获取值
1. 语法:
1. ${域名称.键名}
1. pageScope –> pageContext
2. requestScope –> request
3. sessionScope –> session
4. applicationScope –> application
2. ${键名}
- 顺序:pageContext –> request –> session –> application
2. 获取对象
1. 对象:${域名.键名.属性名}
- u.name(u.getName())
2. List集合:\${域名.键名[索引]}
- \${list[0]},越界什么都不显示
3. Map集合:\${域名.键名.key名称}或\${域名.键名["key名称"]}
- ${map.gender}
- ${map["gender"]}
3. 隐式对象(11个)
- pageContext:获取其他八个内置对象
- ```jsp
${pageContext.request.contextPath}
JSTL
概念:JavaServer Pages Tag Library
作用:简化和替换JSP页面上的Java代码
使用步骤:
- 导入jar包
- 引入标签库:taglib指令(<%@ taglib %>)
- 使用标签
常用标签:
if
<c:if test="">
</c:if>choose
<c:choose>
<c:when test=""></c:when>
... ...
<c:otherwise></c:otherwise>
</c:choose>forEach
<c:forEach begin="" end="" var="" step="">
</c:forEach>
<c:forEach items="${list}" var="str" varStatus="s">
${s.index}
${s.count}
</c:forEach>
Filter
作用:
- 一般用于完成通用的操作,如登录验证、统一编码处理,敏感字符过滤
入门:
- 定义类实现接口Filter
- 实现方法
- 配置拦截路径
package web; |
web.xml配置
<filter> |
生命周期:
- init
- doFilter
- destroy
过滤器配置:
拦截路径配置
- 具体路径:/index.jsp
- 目录拦截:/user/*
- 后缀名拦截:*.jsp
- 拦截所有资源:/*
拦截方式配置:资源被访问的方式
注解配置:设置dispatcherTypes属性
- REQUEST:默认值,浏览器直接请求资源
- FORWORD:转发访问资源
- INCLUDE:包含访问资源
- ERROR:错误跳转资源
- ASYNC:异步访问资源
web.xml配置
<filter-mapping>
<filter-name>demo</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>...</dispatcher>
</filter-mapping>
过滤器链的配置
- 如果有两个过滤器
- Filter1 –> Filter2 –> 资源执行 –> Filter2 –> Filter1
- 执行顺序问题
- 注解配置:按照类名的字符串比较规则进行比较,最小的先则执行
- AFilter < BFilter(AFilter先执行)
- web.xml配置:谁定义在上面,谁先执行
- 注解配置:按照类名的字符串比较规则进行比较,最小的先则执行
- 如果有两个过滤器
代理:
- 概念
- 真实对象
- 代理对象
- 代理模式:代理对象代理真实对象,达到增强真实对象功能的目的
- 实现方式
- 静态代理:有一个类文件描述代理模式
- 动态代理:在内存中形成代理类
- 代理对象和真实对象实现相同的接口
- 代理对象:Proxy.newProxyInstance()
- 第一个参数:类加载器
- 第二个参数:接口数组
- 第三个参数:处理器
- invoke
- proxy
- method:代理对象调用的方法,被封装为对象
- args:代理对象调用方法时,传递的实际对象
- 使用代理对象调用方法
Listener
事件监听机制
- 事件源
- 监听器
- 注册监听
ServletContextLinstener:监听ServletContext对象的创建和监听
- contextDestroyed(ServletXontextEvent sec)
- contextImitialized(ServletContextEvent sec)
步骤:
- 定义一个类,实现ServletContextLinstener接口
- 实现方法
- 配置
package web; |