一、了解 http 协议
1、概念作用特点
(1)概念:超文本传输协议
(2)作用:规范客户端和服务器之间的交互
(3)特点:简单便捷、无状态(对事务处理没有记忆能力)、无连接(1.1版本支持连接保持)
2、交互流程请求格式和请求方式
(1)交互流程:建立连接、发送请求、接受响应、关闭连接
(2)请求格式:行(请求方式、协议、地址)、头(附加信息)、空行(必须)、数据(体)
(3)请求方式:
- GET/POST比较:安全性、请求数据的位置和大小限制
3、响应格式和状态码
(1)响应格式:头、行、空行、实体(数据)
(2)状态码:200--成功;300--重定向;400--客户端错误;500--服务器错误
二、tomcat介绍和使用
1、服务器的概念
(1)概念:就是一个接受客户端请求而调用对应逻辑代码的容器
2、tomcat的目录结构
(1)结构:bin(可执行文件)、lib(依耐的jar)、conf(配置文件)、webapps(项目)、logs(日志)、
work(jsp编译目录)
3、tomcat安装配置常见错误
(1)路径不要有中文
(2)端口的占用问题
(3)电脑必须要有 jdk 环境
三、servlet
1、servlet简介
(1)第一个 web 程序:url 映射要写项目的名称
(2)什么是servlet:运行在服务器端的 java 程序,就是一个类实现了 servlet 接口
(3)servlet编写:
- 写一个类继承 httpServlet;
- 重写 service 方法;
- 在 web xml中配置 servlet;
2、servlet 访问流程和生命周期
(1)访问流程:请求url------项目-------web.xml-------servlet
(2)生命周期:
- 配了 load-on-startup 就是服务器的启动到停止(load-on-startup 配在 servlet 中,数字表示优先级);
- 没有配就是第一次访问到服务器关闭;
- 工作原理:init 初始化------调用 service 提供服务(doget 和 dopost)------ destroy 销毁实例
3、service、doGet和doPost
(1)作用:service 可以处理get 和 post 请求;doGet只能处理get;doPost只能处理post;
(2)优先:三者都存在的前提下,优先使用 service;
(3)说明:
- 父类的service 方法是做get和post 的判断,然后调用doGet 或 doPost方法;
- 一般使用用service 方法,在service做 get 和 post 判断,调用相应的代码;
4、request 和 response 对象
(1)request对象
- 获取行信息:getMethod(方法)、getRequestURL和getRequestURI、getScheme(协议);
- 获取头信息:
- getHeader("key")、getHeaderNames();key不存在返回 null;
- 获取请求体的数据:
- getParameter("key")、getParameterNames()、getParameterValues()
(2)response对象
- 设置响应头:setHeader(name,value)和 addHeader();前者会产生同键覆盖,后者不会;
- 设置响应状态:sendError(int code,str msg)--自定义错误响应的状态;
- 设置响应体:resp.getWriter.write(string str)
- 设置编码:resp.setContentType("text/html;charset=utf-8")
- servlet 中 service 的编写逻辑:
- 设置请求响应编码;
- 获取请求数据;
- 处理请求数据:数据库操作(mvc思想);
- 响应处理结果(直接响应;重定向;转发);
(3)说明:
- request 和 response 对象都是有服务器创建的;
- 请求参数乱码的问题:
- 解决方法一:new String(str.getBytes("iso8859-1"),"utf-8")------get 和 post 都可以这样处理;
- 解决方法二:post--setCharatorEncoding("utf-8");get----除了前面的设置外还要配置server xml(在connector 中配置useBodyEncodingforURI=true)
(4)登录练习:jsp、servlet、service、dao、jdbc、mysql
5、转发和重定向
(1)请求转发
- 作用:实现多个 servlet 的联动处理请求,解决了代码冗余,提高了灵活性;
- 方法:request.getRequestDispatcher("/jsp/login.jsp").forward(request, response);
- 特点:一次请求,地址栏不变;
- 注意:转发后直接 return;
(2)request对象的作用域
- request 实质是以域对象,就是一个容器,可以从里面存取东西;
- request 在一次请求的范围内有效;
- request 域对象的作用是实现多个 servlet 之间的数据共享(数据流转);
(3)重定向
- 作用:解决表单的重复提交问题;解决sevlet无法处理的问题;
- 方法:response.sendRedirect("/login/jsp/suc.jsp");
- 特点:两次请求,两个 request;地址栏会发生改变;
- 问题:重定向的数据的共享问题用 session 解决;
(4)二者的比较
- 转发只能访问统一站点同一 web 应用下的其他资源,而重定向不仅可以访问同一 web 应用的其他资源,还可以访问同一站点其他应用的资源,甚至可以访问其他站点的资源;
- 二者的速度来讲,转发比重定向更快,在使用二者都无所谓的前提下建议使用转发;
- 但是在表单提交之类的特殊场景,为了避免数据的重复提交,应该使用重定向;
- 二者路径的写法,转发没有项目名,而重定向要包括项目名;
6、cookie(钥匙) 和 session(房间)
(1)cookie(浏览器端)
- 作用:解决不同次请求之间的数据的共享问题
- 使用:Cookie c = new Cookie();resp.addCookie(c);req.getCookies()返回数组遍历即可(注意非空的判断);
- 特点:
- cookie 在服务器端添加,存到浏览器;
- 默认cookie是临时存储,存到内存;设置过期时间(setMaxAge)之后序列化到硬盘实现定期存储;
- 有限期内符合路径要求的请求都会携带该 cookie(有效路径没有设置的话都会携带的setPath);
- 注意:一个 cookie 对象存一条 cookie(一个键值对通过构造方法传入);
- 练习:三天之类免登录的 demo;
(2)session(服务器端)
- 作用:实现一个用户不同次请求之间的数据共享的问题,一般 session 中存放用户数据,便于取用
- 原理:用户第一次请求创建一个 session 对象,并将 Jsessionid 随 cookie 传到浏览器,以后用户再次请求的时候,带上 cookie 根据 id取到属于自己的 session,从而获得 session 中共享的数据
- 特点:由服务器创建并存储,依赖 cookie 技术,在不失效的前提下,作用域为一次会话;
- 使用:
- req.getSession() 可以做几件事:
- 第一次访问会创建一个 session 并将 id 存到浏览器的 cookie 中
- 再次访问在 cookie 和 session 都没有失效的前提下,可以直接根据请求中的 cookie 中的id 取到自己的session
- setAttribute(str,obj) getAttribute():session 是域对象可以使用通用的存取数据的方法;
- setMaxInactiveInterval():设置session 的失效时间,默认是 30 分钟,每次访问都会重新计时
- invalidate():强制销毁 session;
- session 的失效处理:将请求中的 JSESSIONID 和后台获取到的 id 进行对比,不一致则为失效;还可以做数据的 null 判断
- 练习:login 示例的用户名 null 的显示
7、servletContext
(1)作用:解决不同用户之间的数据的共享的问题;
(2)特点:服务器创建;用户共享(一个项目有且只有一个);
(3)作用域和生命周期:整个项目内;伴随服务器的启停;
(4)SC 对象的创建:可以通过servlet、servletConfig、session对象的 get方法来获取
(5)SC 对象的使用
- 域对象可以使用通用的方法存取数据;
- 获取web xml 中的全局配置数据:getInitParameter(name)getInitParameterNames()返回键的枚举;
- 获取项目根目录下资源的绝对路径:sc.getRealPath(path),这个方法能获取到项目根目录的绝对路径;
- 获取项目根目录下资源的IO流:sc.getResourceAsStream(path)只能获取普通资源文件的流,无法获取 class 文件的流;
- web xml 中全局配置变量:注意一个 context-param 只能配一个全局参数
<context-param>
<param-name>haha</param-name>
<param-value>123</param-value>
</context-param>
(6)练习:网站访问的计数(两个路径的访问都要计数,同时服务器停止要利用流技术进行持久化的存储)
(7)servletConfig对象
- 作用:获取独属于每个 servlet 的初始化参数;
- 特点:一个 servlet 对象一个 servletConfig;
- 使用:对象获取----this.getServletConfig();参数获取------sc.getInitParameter(name);
<servlet>
<init-param>
<param-name>haha</param-name>
<param-value>123</param-value>
</init-param>
</servlet>
(8)web xml 和 server xml 文件
- web xml
- 位置:项目和 tomcat 都有,项目的是只针对本项目有效,而 tomcat 的配置是全局的,默认先找项目的再找全局的;
- 核心组件:全局上下文配置、servlet 配置、监听器和过滤器;
- 加载时机:都是在服务器的启动时加载;
- server xml
- 核心:
- 注意:端口号的配置和项目热部署的配置,项目热部署后,如果移除项目需要删掉对应的context;
- 热部署:<Context docBase="xxx" path="/xxx" reloadable="true"/>
四、jsp
1、jsp 概述
(1)概念
- java server pages 中文java 服务器网页,是一种动态网页技术;
- 兼具 html 和 servlet 的优点,本质还是一个servlet,可以跨平台;
(2)原理
- tomcat 只认识 servlet;
- localhost:8080/login/1.jsp 这样的url 后面部分的 1.jsp 会被 tomcat 认为是一个 servlet 的映射;
- 通过这个映射会去找 tomcat 的 web xml 中的相关的配置,最终会找到一个名为 jspservlet 的servlet 程序(tomcat的jsp引擎);
- 这个sevlet 的作用就是把 jsp 文件进行转译输出,java原封不变,html相关的会 write 出去;
2、jsp page 指令
(1)作用:配置 jsp 文件转译相关参数
(2)jsp 的三种注释:
- 前端注释:会转译会发送但是浏览器不会执行;
- java 注释:会转译但sevlet 不会执行;
- jsp 注释:不会转译;<%-- --%>
(3)格式:
<%@ page language="java" pageEncoding="utf-8"%>
(4)详述:
- language:转译语言
- import:转译为java 后要导入的包,不同的包用逗号间隔
- pageencoding:jsp 的编码格式
- contenttype:响应给浏览器的格式和编码
- session:session 支持,默认为true 是开启的
- errorpage:jsp 运行错误跳转的页面
- extends:转译后的 servlet 要继承的类(包名+类名)
(5)关于乱码:本质的原因就是文件 读 和 写 的编码不一致造成的
3、java代码块-----局部代码块 | 全局代码块 | 输出代码块
(1)局部代码块
- 格式:<% java代码 %>
- 上面的java 代码最终都是转译到 service 方法中
- 和 html 元素配合使用用类似于拼接的方式实现逻辑判断,可读性很差
- 开发中通常是 jsp 少做逻辑的处理,尽量在servlet 中来完成
(2)全局代码块
- 格式:<%! code %>
- 转译后是全局代码
- 使用:全局进行方法的声明,局部来调用
(3)输出代码块
- 语法:<%= %>
- 实质就是一个输出,等价与 out.write()
- 结束不用写分号
- 可以在 html 的任意位置来使用
4、jsp 和动态引入和静态引入
(1)静态引入(include 指令引入)
- 语法:<%@include file="相对路径"%>
- 原理:多个jsp 合成为1个一起转译为一个servlet
- 注意:静态引入同名变量很可能会引起冲突
(2)动态引入(通过 include 动作标签来引入)
- 语法:<jsp:include page=" ">
- 原理:引入的文件会单独转译,最后在当前jsp 转译后的 servlet 中调用
- 注意:动态引入和静态引入最后的效果都是一样的;动态引入无需注意变量的同名问题
(3)总结
- 作用:都是降低代码冗余,提升维护性;
- 效果一模一样;
- 根据同名变量的多少来决定选用谁;
- 直接用动态引入更好;
5、forward 转发标签(动作标签)
(1)作用:和 sevlet 中的转发功能是一样的
(2)语法:
<jsp:forward page="path">
<jsp:param name="" value=""/>
</jsp:forward>
(3)注意:
- forward 标签中间只能是 param 标签,写其他的任何字符会报错;
- 其中的参数会拼接在地址?后面和get请求的类似;
- 在转发后的jsp 和servlet 中能够获取相应的参数;
6、jsp 九大内置对象 | 资源路径
(1)内置对象:jsp 在转译为 servlet后自动生成并声明的对象,我们在 jsp 页面可以直接使用
(2)注意:9 个对象都是在service 方法中声明的,所以使用的时候只能在局部代码块中使用
(3)九个对象(request、response、out、session、page、pageContext、application、config、exception)
- pageContext:页面上下文对象,里面封装了其他的8个对象,包含了jsp页面运行的信息;一个jsp 一个pc对象,作用域为当前页面;
- request:封装请求数据,服务器创建,一次请求;
- response:请求处理结果响应给浏览器,可以设置响应头和实现重定向;
- out:输出对象,在jsp 基本被输出的标签取代;
- session:存储用户不同次请求的共享数据,一次会话;
- application:就是 servletContext对象,一个项目一个,存不同用户的共享数据,作用域为项目内;
- page:就是 this,本jsp
- config:就是servletConfig,用来获取 web xml 配置的数据,完成初始化参数的读取;
- exception:异常对象,要用的话需要在 page 指令中设置 iserrorpage = true来开启;
(4)四个作用域对象(数据流转)
- request、session、application、pageContext;
- 通用的方法:get/setAttribute();
(5)jsp资源的路径问题
- 相对路径:相对位置不能变,文件一移动就会出现问题;../ 跳出文件夹比较麻烦;
- 绝对路径1(动态):/虚拟项目名/资源;第一个 / 直接定位到 webapps 目录;
- 绝对路径2(动态):使用 myEclipse 开发创建 jsp 文件自动生成3行代码,构建一个 basepath,后面只需直接写相对于 webroot 的目录即可;
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://"+ request.getServerName() + ":" + request.getServerPort()+ path + "/";
%>
<base href="<%=basePath%>"/> <!-- base放在 head 标签里 -->
- 总结:一般就使用绝对路径;
- 补充:servlet 中的路径问题
- 转发:/resource,第一个斜杠代表项目根目录;
- 重定向:/proname/resource,第一个斜杠代表服务器根目录;
- 补充:其他路径
- 加斜杠就是默认 classpath 目录;
- 不加就是从当前的包下找;