Tomcat笔记
最后更新日期2020-05-08
今日学习内容
- mysql事务存在的问题(脏读,不可重复读,幻读)
- mysql的隔离级别
- DCL语句(添加用户、删除用户、更改用户密码、管理用户权限)
- web的相关概念(软件架构、资源分类、网络通讯三要素)
- web服务器软件Tomcat
web相关概念
软件架构
- C/S:客户端/服务器端
- B/S:浏览器/服务器端
资源分类
- 静态资源:所有用户访问后,所得到的结果都是一样的,称之为静态资源。静态资源可以直接被浏览器所解析(浏览器内置静态资源引擎可以直接解析静态自愿然后将其展示到页面上。eg:HTML CSS javascript等)
- 动态资源:每个用户访问相同资源后,得到的结果可以是不一样的,称之为动态资源。
- 动态资源展示在浏览器页面的过程
- 服务器中访问动态资源—>将动态资源转换为静态资源。
- 将转换后的静态资源返回到浏览器。
- 浏览器解析静态资源,展示到页面上。
- 如:servlet/jsp/php/asp…
- 动态资源展示在浏览器页面的过程
网络通讯三要素
- IP:电子设备在网络中的唯一标识。
- 端口:应用程序在计算机中的唯一标识。0~65536
- 传输协议:规定了数据传输的规则
- 传输协议:
- TCP:安全协议,三次握手,速度比较慢。
- UDP:不安全协议,速度比较快。
- 传输协议:
web服务器软件:Tomcat
-
web服务器软件:可以接受用户的请求,处理,做出响应的web容器
- web服务器软件中,可以部署web项目,让用户可以通过浏览器来访问这些项目。
-
常见的java相关的web服务器软件:
- weblogin:orcale公司开发的大型javaEE服务器,支持所以后的javaEE规范。
- webSphere:IBM公司
- JBOSS:JBOSS公司
- Tomcat:Apache基金组织中小型javaEE服务器,仅支持少量的javaEE规范(servlet/jsp)。
-
JavaEE规范:Java语言在企业级开发中使用的技术规范综合,一共规定了13项大的规范。
Tomcat:web服务器软件
-
端口号被占用的解决办法
-
关闭占用的端口号服务
-
修改自身的端口号
conf/server.xml <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000"redirectPort="8443" /> * 一般会将tomcat的默认端口号修改成80端口. 80端口是http协议默认的端口号 * 好处:在访问时,可以不用输入端口号 默认就是http对应的80端口号
-
-
关闭
ctrl+c即可关闭Tomcat服务
-
部署项目
- 直接将项目放入到webapps目录即可 http://localhost:8080/hello/hello.html
- 简化部署:将项目打包成war包繁花如webapps中访问时会自动将war包解压
-
配置相关配置文件 配置文件目录conf/server.xml
在<Host>标签体中配置 <Context docBase="D:\hello" path="hh" /> docBase:项目存放的目录 path:虚拟目录
-
在\cof\Catalinna\localhost 中创建任意名称的xml文件 在文件中编写
<Context docBase="D:\hello"/> 虚拟目录:xml文件的名称
-
为什么我们启动tomcat还需要配置JAVA_HOME环境变量
Tomcat在执行java代码时需要编译才能运行,但java的编译需要jdk的支持,在window中编译java的命令例如javac,javadoc等都存放在jdk的bin目录中,但Tomcat在安装时不能直接从系统注册表中读取jdk的目录信息,需要手动配置环境变量以确保在使用Tomcat时能找到了jdk的路径,才能对servlet/jsp进行编译成.class文件。
-
Servlet
-
概念: server applet 运行在服务器端的小程序
- Servlet本质上是一个接口,定义了Java类被浏览器访问到(tomcat所识别)的规则
- 将来我们想要自定义一个类被tomcat所识别,这个类必须要实现Servlet接口 重写其中的抽象方法.
-
Servlet快速入门
-
创建一个JavaEE项目
-
定义一个类,实现Servlet接口
-
实现Servlet接口中的抽象方法
-
配置Servlet
- web.xml 中配置Servlet
<servlet> <servlet-name>demo1</servlet-name> <servlet-class>com.huike.web.servlet.ServletDemo01</servlet-class> </servlet> <servlet-mapping> <servlet-name>demo1</servlet-name> <url-pattern>/demo1</url-pattern> </servlet-mapping>
-
-
执行原理
- 当服务器接收到客户端浏览器的请求后,会解析请求url路径,获取访问的Servlet的资源路径(/demo1)
- 查找web.xml文件 看文件中是否有对应的标签体的内容
- 如果有,则再找到所对应的的全限定类名
- tomcat会将该类的字节码文件加载至内存中,并创建对象
- 通过反射 revoke()方法去调用其 service方法 执行该方法
-
Servlet中的生命周期方法:
- 被创建:执行init方法 只执行一次
-
Q:Servlet什么时候会被创建?
- 默认情况下,第一次被访问时,Servlet会被创建
- 可以配置执行Servlet的创建时机
-
Servlet的init方法,只执行一次 说明了一个Servlet类在内存中只存在一个对象 --> Servlet是单例的
- 多个用户同时访问同一个Servlet 会同时调用其中的方法 service 会存在线程安全的问题
- 解决:尽量不要在Servlet中定义成员变量 即使定义了成员变量 也不要对其修改值
-
- 提供服务:执行service方法 执行多次
- 每次访问Servlet时,都会被调用一次
- 指定Servlet的创建时机 在web.xml中的标签中创建标签
1.第一次访问时创建 默认值
的值设置成负数
2.在服务器启动时就创建
的值设置成0或正整数
- 被销毁:执行destory方法 只执行一次
- Servlet被销毁时执行该方法 服务器关闭时,Servlet会被销毁
- 只有服务器正常关闭时,才会执行destory方法
- destory方法在Servlet被销毁前执行 一般用于进行资源的释放
- 被创建:执行init方法 只执行一次
-
Servlet3.0和3.0以下版本的区别
- Servlet3.0以下版本: 必须要配置web.xml文件 需要将Servlet对应的类配置到web.xml中
- Servlet3.0及以上版本:
-
好处:支持注解配置 可以不需要web.xml文件了
-
创建Servlet3.0及其以上版本项目的步骤 —>重点掌握
-
创建一个JavaEE项目 选择Servlet3.0版本以上的项目,可以不创建web.xml
-
定义一个类,实现Servlet接口
-
实现Servlet接口中的抽象方法
-
在类上使用注解进行配置–>在类前面使用@WebServlet(“资源路径”)
public @interface WebServlet {
String name() default “”; //相当于String[] value() default {};//代表urlPatterns() 注解类中有一个属性比较特殊 是value 如果注解中只定义这一个属性,这个属性名可以省略 String[] urlPatterns() default {}; //代表<url-pattern> int loadOnStartup() default -1; //相当于<load-on-startup> WebInitParam[] initParams() default {}; boolean asyncSupported() default false; String smallIcon() default ""; String largeIcon() default ""; String description() default "";
String displayName() default “”;
}
-
-
IDEA与tomcat相关的配置
- Q:我们通过IDEA将项目部署到了tomcat中,那么我们的项目到底是以哪种形式部署到了tomcat中呢?
-
查看控制台的log日志发现这么一行: Using CATALINA_BASE: “C:\Users\MrDong\AppData\Local\JetBrains\IntelliJIdea2020.1\tomcat\Tomcat_8_5_31_java_124_2”
-
说明了IDEA是采用我们部署web项目的第三种形式 在conf\Catalina\localhost\目录下新建一个xxx.xml文件 xxx为虚拟目录
<Context path="/02_servlet_haha" docBase="D:\study\IDEA\workspace\java_124\out\artifacts\02_servlet_war_exploded" />
其中docBase所指向的就是真正部署到tomcat的项目
其中docBase所指向的就是真正部署到tomcat的项目
-
- IDEA的工作空间项目 和 tomcat部署的web项目的 区别
- tomcat真正访问的是"tomcat部署的web项目", “tomcat部署的web项目"对应着"IDEA的工作空间项目” 的 web目录下的所有资源
- WEB-INF目录下的资源是不能被浏览器所访问的 <-- 切记
- tomcat如何进行debug调试?
- 只需要使用debug tomcat启动即可进入断点(运行按钮旁边的小虫子按钮)
- Q:我们通过IDEA将项目部署到了tomcat中,那么我们的项目到底是以哪种形式部署到了tomcat中呢?
-
-
Servlet的体系结构
-
分析前面的Servlet代码 存在一些问题:
- 每次在创建Servlet类的时候必须实现Servlet接口,必须强制要求我重新其中所有的方法(5个),但我们通常只需要用到其中的service方法.
- 解决方案: 新建一个抽象基类A 让其实现Servlet接口 重写其中用不到的方法(空方法体实现) 再定义ServletDemo类去继承抽象基类A即可.
- 每次在创建Servlet类的时候必须实现Servlet接口,必须强制要求我重新其中所有的方法(5个),但我们通常只需要用到其中的service方法.
-
体系结构
– Servlet接口–爷爷
– GenericServlet(实现Servlet接口的抽象类) <–就相当于我们定义的抽象基类A – 爸爸
– HttpServlet(继承了GenericServlet的抽象类) – 儿子(最常用的)- HttpServlet:对http协议的一种封装,简化操作
- 定义类继承HttpServlet
- 重写其doGet/doPost方法
- HttpServlet:对http协议的一种封装,简化操作
-
-
Servlet的相关配置
- urlPattern:值为Servlet的访问路径 本质上是一个String[]数组
- 一个Servlet可以定义多个访问路径 @WebServlet({"/h01","/h02","/h03","/http01"})
- 路径定义规则:
- /xxx:路径匹配
- /xxx/xxx:多层路径匹配 @WebServlet("/user/demo01") @WebServlet("/user/") @WebServlet("/")
- *.do:扩展名匹配 .action .xxx
- urlPattern:值为Servlet的访问路径 本质上是一个String[]数组
http协议
- 概念: Hyper Text Transfer Protocol:超文本传输协议
- 传输协议:定义了 客户端浏览器和服务器端通信时 发送数据的格式
- 特点:
- 基于TCP/IP的一种高级协议
- 默认端口号 80
- 基于请求/响应模型 一次请求对应一次响应 一对一的
- 无状态的: 每次请求和响应之间都是互相独立的 互不影响 不能进行数据的交互
- 历史版本
- 1.0:每一次请求都会建立一个新的连接–> 导致资源浪费
- 1.1:连接的复用
请求消息数据格式
-
响应消息数据格式 response
-
请求方式(HTTP协议中共有7中请求请求方式常用的有两种):
- GET:
- 请求参数在请求行中,在url后边
- url有长度限制
- 不太安全
- POST:
- 请求参数在请求体重
- 请求URL没有长度限制
- 相对比较安全
- GET:
-
请求头:客户端浏览器告诉浏览器的一些信息
-
格式:请求头名称:请求头值
-
常见的请求头:
-
User-Agent:告知服务器所使用的浏览器类型,根据不同的浏览器解决浏览器的兼容性问题。
-
Referer:告知服务器,该页面从哪个页面跳转过来的。
-
-
-
请求空行
-
请求体(正文)
request对象
-
原理:
- request和response对象是由服务器创建的。我们来使用它们
- request对象是来获取请求消息,response对象是来设置响应消息
-
request对象继承体系结构
ServletRequest //接口 |继承自 HttpServletRquest //接口 |继承自 org.apache.catalina.connector.RequestFacade 类(Tomcat的类 自行创建的)
-
获取请求行的数据
//1. 获取请求方式:GET String getMethod() //2. 获取虚拟目录: /day02_request String getContextPath() //3. 获取Servlet路径: /requestdemo1 String getServletPath() //4. 获取get方式的请求参数: username=zhangsan&&password=123 String getQueryString() //5. 获取请求的URI: /day02_request/requestdemo1 String getRequestURI() StringBuffer getRequestURL() //http://localhost:8080/day02_request/requestdemo1 //6. 获取协议及版本号:HTTP/1.1 String getProtocol() //7. 获取客户机的IP地址: ipv6的地址 String getRemoteAddr()
-
获取请求头的数据
- 常见的请求头:
1. User-Agent:浏览器告诉服务器,我访问你使用的浏览器版本信息
* 可以在服务器端获取该头的信息,解决浏览器的兼容性问题 - Referer:http://localhost/login.html
* 告诉服务器,我(当前请求)从哪里来?
* 作用:
1. 防盗链:
2. 统计工作: - 方法:
- String getHeader(String name):通过请求头的名称获取请求头的值
- Enumeration getHeaderNames():获取所有的请求头名称
- 常见的请求头:
-
获取请求体的数据
-
只要POST才有请求体,在请求体中封装了POST的请求参数
-
步骤:
-
获取流对象
BufferedReader getReader();//获取字符输入流,只能操作字符数据 ServletInputStream getInputStream();//获取字节输入流,可以操作所有类型的数据
-
从流中获取数据
String line = null; while ((line = reader.readLine())!=null){ System.out.println("获取的参数是"+line); }
-
其他功能
获取请求参数的通用方式:无论get还是post请求都可以使用以下方法来获取请求参数的 重要
request.setCharacterEncoding("utf-8");//根据当前页面字符集的类型进行设置 String getParameter(String name)://根据参数名称获取参数的值 String[] getParameterValues(String name): //根据参数名称获取参数的值 返回是一个数组 hobby=hobby1&&hobby=hobby2 Enumeration<String> getParameterNames()://获取所有请求参数的名称 Map<String,String[]> getParameterMap()://获取所有参数的map集合
- 解决中文乱码问题:
- get请求方式:tomcat8.0已经帮我们把get请求的乱码问题解决了
* post请求方式:会出现中文乱码的问题的
* 解决方案: 只需要在获取参数前加上如下代码即可:request.setCharacterEncoding(“utf-8”);
- get请求方式:tomcat8.0已经帮我们把get请求的乱码问题解决了
- 解决中文乱码问题:
-
请求转发:一种在服务器内部的资源跳转方式
-
步骤:
- 通过request对象获取请求转发器的对象 RequestDispatcher getRequestDispatcher(String path)
- 使用RequestDispatcher对象来进行转发操作 void forward(ServletRequest request,ServletResponse response)
-
特点:
- 浏览器地址栏路径不会发生变化
- 只能转发到当前服务器内部资源中
- 请求转发是一次请求 (1.A页面请求资源1,2.资源1转发资源2) 步骤1会发送一次请求 步骤2不会发送请求
-
共享数据:
- 域对象:一个有作用范围的域对象 可以在范围内共享数据
- request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据
- 方法:
- void setAttribute(String name, Object o) :用于存储数据 参数一:设置存储数据的key 参数二:要存储的数据
- Object getAttribute(String name) :用于取数据 通过name值获取特定的存储数据
- void removeAttribute(String name) :从请求中将特定name值的数据对移除
-
获取ServletContext对象
- ServletContext getServletContext() :它的用法后续讲解
-
-
-
response
-
数据格式
-
响应行:
- 组成:协议、版本 响应状态码 状态描述 eg:HTTP/1.1 200 OK
- 响应状态码:
- 1xx:服务器接收客户端,但是没有接收完成,等待一段时间后发送1xx状态码。
- 2xx:成功 eg:200 OK
- 3xx:重定向 eg:302(重定向) 304(访问缓存)
- 4xx:客户端错误 eg:404(请求路径没有对应资源)405(请求方式没有对应的方法)
- 5xx:服务器错误 eg:500(服务器内部出现异常)
-
响应头
-
格式:响应头名称:值
-
常见的响应头:
-
Content-Type:服务器告诉客户端本次响应数格式以及编码格式是什么
-
Content-disposition:服务器告诉客户端已什么样的格式打开响应体数据
eg:in-line:默认值,代表在当前页面打开 attachment:以附件形式打开当前响应体
-
-
-
响应空行
-
响应体: 服务器响应的内容
-
-
response对象
-
设置相应消息
-
设置响应行:
//格式:HTTP/1.1 200 OK response.setStatus(int status);
-
设置响应头
void setHeader(String name, String value)
-
设置响应体:
//1.获取输出流 PrintWriter writer = reqs.getWriter()//获取字符输出流 ServletOutputStream output = getOutputStream()//获取字节输出流 //2.使用字输出流,将数据输出到客户端浏览器 writer.Write();
-
-
案例
-
重定向:资源跳转的方式
//1.设置response的状态码为302 resp.setStatus(302); //2.设置响应头 location response.sendHeader("/responseDemo/resDemo"); //简单的重定向方法: response.sendReadirect("/responseDemo/resDemo")
-
-
重定向的特点:redirect
- 地址栏发生改变
- 重定向可以访问其他站点(服务器)的资源
- 重定向是两次请求,不可以通过request对象来共享数据
-
转发的特点:forward
- 转发的地址栏路径不变。
- 转发只能访问当前服务器下的资源。
- 转发是一次请求,可以通过request对象来共享数据。
-
路径写法:
-
路径分类:
-
相对路径:通过相对路径不可以确定唯一的资源
不以"/“开头以”./"(当前目录)或者"…/"(上一级目录)开头
-
绝对路径:通过绝对路径可以确定唯一资源以 / 开头的路径
-
是否需要使用虚拟目录判断依据:
-
规则:判断定义的路径给谁用?判断请求将来自哪里发出的
-
给客户端浏览器使用:必须加上虚拟目录
e.g:<a> <form> 重定向...
-
给服务器内部使用:不需要加虚拟目录
e.g:转发路径
-
-
-
-
-
-
服务器输出字符到浏览器
//在页面输入一句话 //1.设置编码 response.setContentType("text/html;charset=utf-8"); //2.输出 response.getWriter().write("登录失败,用户名或者密码错了吧...");
-
浏览器乱码问题
//第一种方案:将编码格式调整为和浏览器相同 response.setCharacterEncoding("GBK"); //第二种方法:将服务器使用的编码方式发送给浏览器,告知浏览器使用相同的字符集 response.setHeader("content-type","text/html;charset=GBK"); //第二种方法的简化版 response.setContentType("text/html;charset=GBK")
-
-
服务器输出字节到浏览器
//1.获取字节输出流 ServletOutputStream sos = response.getOutputStream(); sos.write("你好".getbytes()); sos.write("你好".getbytes("GBK"));
-
使用setAttribute()给jsp页面赋值
//获取request域中共享的user对象 User user = (User) request.getAttribute("user"); //在页面输入一句话 //1.设置编码 response.setContentType("text/html;charset=utf-8"); //2.输出 response.getWriter().write("登录成功!"+user.getUsername()+",欢迎您!!!!!");
//在jsp页面中读取key-value值 <div style="text-align: center; font-size: 30px; color: #333333"> 恭喜!用户<%=request.getAttribute("username")%>登录成功! </div>
-
jsp和html的区别以及jsp与ajax数据操作的优劣https://www.cnblogs.com/zq-kjy/p/8473692.html