1、XML简介
1.1 什么是XML?
- xml是可扩展性的标记性语言
- 可扩展的含义是:标签可以自定义
1.2 作用
- 用来保存数据,而且这些数据具有自我描述性
- 可以作为项目或者模块的配置文件
- 可以作为网络传输数据的格式
1.3 语法
- 文档声明
<?xml version="1.0" encoding="utf-8" ?>
- 元素(标签)
<books>
<book sn ="SN123" > <!-- 属性可以提供元素的额外信息,每个属性的值必须使用“”引起来 -->
<name>谁</name>
<age>123</>
</book>
</books>
根元素就是顶级元素
没有父标签的元素叫顶级元素
根元素是没有父标签的顶级元素
- xml属性
- xml注释
- 文本区域(CDATA区):将输入的字符原样显示,不需要xml解析
<![CDATA[
<<<<<<<<<
]]>
1.4 xml的解析技术
- xml是可扩展性的标记语言,不管是html文件还是xml文件它们都是标记型文档,都可以使用w3c组织制定的dom技术来解析
- document:表示的是整个文档(可以是html文档,也可以是xml文档)
- 解析历程
(1)早期:DOM,SAX
(2)第三方解析:
jdom 在 dom基础上进行了封装
dom4j又对jdom进行了封装
pull主要用于Android手机开发,根sax类似
1.5 dom4j解析技术
2、 JavaWeb的概念
2.1 什么是javaWeb
所有通过Java语言编写的可以通过浏览器访问的程序的总称
是基于请求和响应开发的
2.2 请求和响应
request、response
2.3 web资源的分类
web资源按照实现的技术和呈现的效果不同,又分为静态资源和动态资源两种
- 静态资源:html,css,js,txt,mp4
- 动态资源:jsp,servlet程序
2.4 常用的服务器
- Tomcat
- JBoss
- GlassFish
- Resin
- WebLogic
2.5 动态web工程
- WEB-INF:其中的WEB-INF目录是一个受服务器保护的目录,浏览器无法直接访问其中的内容
- web.xml:是整个动态web工程的配置部署描述文件
(1)Servlet程序
(2)Filter过滤器
(3)Listener监听器
(4)Session超时
3、Tomcat服务器
3.1 Tomcat服务器和Servlet版本的对应关系
3.2 Tomcat在mac下的安装
- 下载
- 解压
- 打开终端 启动tomcat:sudo sh ./startup.sh
- 关闭 tomcat:sh ./shutdown.sh
3.3 Tomcat另一种部署项目方式
在conf目录下的/Catalina/localhost中,写配置文件xxx.xml
<Context path="/abc" docBase="路径" />
3.4 访问路径
- file:///E:/book/index.html(file://协议,直接读取file:协议后面的路径,解析展示在浏览器上即可)
- http://www.baidu.com
4、Servlet
4.1 基本概念
- Servlet是JavaEE规范之一。规范就是接口
- Servlet是JavaWeb三大组件之一。
- 三大组件:Servlet程序、Filter过滤器、Listener监听器
- Servlet是运行在服务器上的一个Java小程序,通常就是接收客户端发送过来的请求,并响应数据给客户端
4.2 手动实现Servlet程序(maven)
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.1</version>
</dependency>
- 编写一个类区实现servlet接口
- 实现service方法,处理请求,并响应数据
- 到web.xml中配置,servlet程序的访问地址
<servlet>
<servlet-name>/test1</servlet-name>
<servlet-class>Test.Test1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>/test1</servlet-name>
<url-pattern>/test1</url-pattern>
</servlet-mapping>
4.3 路径解析
http://localhost:8080/JavaWeb_war_explod/test
- /JavaWeb_war_explod :为工程路径
- /test:为资源路径
4.4 servlet的声明周期
public class Test1 implements Servlet {
public Test1() {
System.out.println("1. constructor .... ");
}
@Override
public void init(ServletConfig config) throws ServletException {
System.out.println("2. init .... ");
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
System.out.println("3. service... ");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
System.out.println("4. destory ....");
}
}
运行结果:
1. constructor ....
2. init ....
// 第一次访问的时候servlet程序会调用
3. service...
4. service...
5. destory...
在web工程停止的时候调用
4.5 请求的分发处理
<form action:"http://xxx:8080/xxx/hello" mehtod="post">
<input type="submit" />
</form>
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
HttpServletRequest servletRequest = (HttpServletRequest)req;
System.out.println(servletRequest.getMethod());
}
运行结果:POST
可以通过修改 method中的方法
4.6 通过继承HttpServlet实现HttpServlet
- 实现doGet()、和doPost()方法
4.7 servlet体系
4.8 ServletConfig类
- ServletConfig类的作用:
是servlet程序的配置信息类
Servlet程序和ServletConfig对象是由Tomcat负责创建的,我们负责使用
Servlet程序默认是第一次访问的时候创建,ServletConfig是每个Servlet程序创建的时候,就创建一个对应的ServletConfig对象
- ServletConfig类的三大作用
(1)可以获取Servlet程序的别名-Servlet name 的值
(2)获取初始化参数init-param
(3)获取ServletContext对象
/**
* 输出别名
*/
http://localhost:8080/JavaWeb_war_exploded/test1?
@Override
public void init(ServletConfig config) throws ServletException {
System.out.println("别名:" + config.getServletName());
}
输出: 别名:/test1
<servlet>
<servlet-name>/test1</servlet-name>
<servlet-class>Test.Test1</servlet-class>
<init-param>
<param-name>username</param-name>
<param-value>ld</param-value>
</init-param>
</servlet>
/**
* 获取初始化参数
*/
@Override
public void init(ServletConfig config) throws ServletException {
System.out.println("获取初始化参数:" + config.getInitParameter("username"));
}
输出结果:初始化参数:ld
@Override
public void init(ServletConfig config) throws ServletException {
System.out.println("获取ServletContext对象:" + config.getServletContext());
}
- service实现方法中获取ServletConfig
ServletConfig servletConfig = getServletConfig();
- 继承实现HttpServlet中的init()方法获取ServletConfig
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
}
4.9 ServletContext类
- 什么是ServletContext?
ServletContext是一个接口,他表示Servlet上下文对象
一个web工程,只有一个ServletContext对象实例
ServletContext对象是一个域对象
ServletContext是在web工程部署启动的时候创建,在web工程停止的时候销毁
- 什么是域对象:
域对象,是可以像Map一样存取数据的对象,叫做域对象
这里的域值得是可以存取数据的操作范围
- ServletContext类的四个作用
(1)获取web.xml中配置的上下文参数 context-param(context-param是上下文参数,它属于整个web工程 )
(2)获取当前的工程路径,格式:/工程路径
(3)获取工程部署后在服务器硬盘上的绝对路径
(4)像Map一样存取数据 (ServletContext是在web工程部署启动的时候创建,在web工程停止的时候销毁 -------> 只要存一次,就可以在web工程停止之前一直取到数据)
- 实例:
<context-param>
<param-name>namespace</param-name>
<param-value>test</param-value>
</context-param>
public class ServletContextTest extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletContext servletContext = getServletConfig().getServletContext();
// 获取web.xml中配置的上下文参数 context-param(context-param是上下文参数,它属于整个web工程 )
System.out.println( "获取web.xml中配置的上下文参数 : " + servletContext.getInitParameter("namespace"));
// 获取当前的工程路径,格式:/工程路径
System.out.println("获取当前的工程路径 : " + servletContext.getContextPath());
// 获取工程部署后在服务器硬盘上的绝对路径
System.out.println("获取工程部署后在服务器硬盘上的绝对路径 : " + servletContext.getRealPath("/"));
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
输出结果:
获取web.xml中配置的上下文参数 : test
获取当前的工程路径 : /JavaWeb_war_exploded
获取工程部署后在服务器硬盘上的绝对路径 : /Users/xxxx/Desktop/JAVA/web/insist/JavaWeb/target/JavaWeb/
/**
* 像Map一样存取数据
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletContext servletContext = getServletContext();
servletContext.setAttribute("te1", "ld"); System.out.println(servletContext.getAttribute("te1"));
}
/**
* 从 properties 中读取数据
*/
ServletContext servletContext = this.getServletContext();
InputStream is = servletContext.getResourceAsStream("/WEB-INF/classes/db.properties");
Properties prop = new Properties();
prop.load(is);
String name = prop.getProperty("username");
String pwd = prop.getProperty("password");
4.10 HttpServletRequest类
- HttpServletRequest类的作用
每次只要有请求进入Tomcat服务器,Tomcat服务器就会把请求过来的HTTP协议信息解析好封装到Request对象中
然后传递到service方法(doGet\doPost)中给我们使用。我们可以通过HttpServletRequest对象,获取到所有请求的信息
- 常用方法:
(1)getRequestURI() // 获取请求的资源路径
(2)getRequestURL() // 获取请求的统一资源定位符(绝对路径)
- 实例:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println(request.getRequestURI()); // /JavaWeb_war_exploded/httpSRT
System.out.println(request.getRequestURL()); // http://localhost:8080/JavaWeb_war_exploded/httpSRT
System.out.println(request.getRemoteHost()); // 0:0:0:0:0:0:0:1
System.out.println(request.getHeader("User-Agent")); // Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36
System.out.println(request.getMethod()); // GET
System.out.println(request.getParameter("username")); // LD
}
- 注意:
当表单提交 发送的为GET请求的时候,不会发生中文乱码
当表单提交 发送的为POST请求的时候,会发生中文乱码
request.setCharacterEncoding("UTF-8");
4.11 请求转发
- 什么是请求转发?
服务器收到请求之后,从一个资源跳转到另外一个资源的操作叫做请求转发
- 代码实例:
/**
* 例1
*/
RequestDispatcher dis = request.getRequestDispatcher("/test1");
dis.forward(request,response);
/**
* 例2
*/
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.getRequestDispatcher("/a/b/in.jsp").forward(req,resp);
}
- 请求转发的特点:
(1)浏览器地址栏没有发生变化
(2)一次请求
(3)共享request域中的数据
(4)可以转发到 WEB-INF 目录下
(5)是否可以访问工程以外的资源:不可以 —> /JavaWeb_war_exploded/http://www.baidu.com
4.12 HttpServletResponse类
- 基本概念
每次请求进来Tomcat服务器都会创建一个Response对象传递给Servlet程序去使用,表示的是响应信息
我们如果需要设置返回给客户端的信息,我们都可以通过HttpServletResponse对象来进行设置
- 两个输出流的说明
(1)字节流:getOutputStream() 常用于下载(传递二进制数据)
(2)字符流:getWrite() 常用于回传字符串
注意:两个流同时只能使用一个,使用了字节流就不能再使用字符流,反之亦然。
同时使用两个响应流会报错
- 往客户端回传字符
PrintWriter printWriter = response.getWriter();
printWriter.write("xxxxx");
- 往客户端回传字符解决中文乱码
/**
* 方法1:
*/
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Type", "text/html; charset=UTF-8");
PrintWriter printWriter = response.getWriter();
// response.setContentType("UTF-8");
printWriter.println("辣的");
/**
* 方法2:
*/
response.setContentType("text/html; charset=UTF-8");
PrintWriter printWriter = response.getWriter();
printWriter.println("辣的");
/**
* 亲测可用
*/
4.13 请求重定向
- 定义:
指客户端给服务器发送请求,然后服务器告诉客户端,去访问新的地址
- 使用方法:
/**
* 方法1:
*/
response.setStatus(302);
response.setHeader("Location", "xxxxxx");
/**
* 方法2:
*/
response.sendRedirect("xxx");
- 请求重定向的特点:
(1)浏览器的地址栏会发生变化
(2)两次请求
(3)不共享Request域中的数据
(4)不能访问WEB-INFO目录下的文件
(5)可以访问工程以外的资源
5、Http协议
5.1 什么是Http协议
- 什么是协议?
指的是双方或者多方相互约定好,大家都要遵守的规则,叫做协议
- 什么是Http协议
所谓http协议就是客户端和服务器之间通信时,发送数据需要遵守的协议
- 报文
HTTP协议中的数据
5.2 请求的Http协议格式
- GET请求:
(1)请求行
请求的方式: GET
请求的资源路径[+?+请求参数]
请求的协议和版本号:HTTP/1.1
(2)请求头
key:value 组成 不同的键值对,表示不同的含义
Accept:告诉服务器,客户端可以接收的数据类型
Accept-Language:告诉服务器,客户端可以接收的语言类型
User-Agent:浏览器的信息
Accept-Encoding:告诉服务器,客户端可以接收的数据编码格式
Host:服务器的ip和端口号
(3)请求体:发送给服务器的数据
- POST请求:
(1)请求行
(2)请求头
Content-Type:表示发送的数据类型
application/x-www-form-urlencoded:表示提交的数据格式是:name=value&name=value,然后对其进行url编码
multipart/form-data:表示以多段的形式提交数据给服务器(以流的形式提交,用于上传)
Cache-Control:表示如何控制缓存 no-cache不缓存
5.3 响应的Http协议格式
- 常用的响应码说明
200 表示请求成功
302 表示请求重定向
404 表示请求服务器已经收到,但是需要的数据不存在(请求地址错误)
500 表示服务器已经收到请求,代码错误
5.4 MIME类型说明
- 是HTTP协议中数据类型
6、JSP页面
6.1 解决base页面乱码问题
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
6.2 base标签解决路径问题
- 基本概念
base标签设置页面相对路径工作时参照的地址
href属性就是参数的地址值
- 应用
<head>
<meta charset="UTF-8">
<base href="http://localhost:8080/BookJDBCTest_war/">
</head>
- 具体实例
<a href="index.jsp">跳转到index页面</a>
<a href="login">通过请求转发的方式:跳转到 /a/b/in.jsp页面</a>
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.getRequestDispatcher("/a/b/in.jsp").forward(req,resp);
}
/**
* 不加base相互跳转的时候
*/
找不到与以下网址对应的网页:http://localhost:8080/index.jsp
/**
* 加base相互跳转的时候
*/
可以成功跳转
6.3 相对路径和绝对路径
6.4 web中,“/” 的不同意义
- “ / ” 如果被浏览器解析,得到的地址是:
http://ip:port/
<a href="/">xx</>
- “ / ” 如果被服务器解析,得到的地址是:
http://ip:port/工程路径
<url-pattern>/xxx</url-pattern>
servletContext.getRealPath("/");
request.getRequestDispathcer("/");
6.5 什么是JSP页面,他有什么用?
- Java的服务器页面(Java server pages)
- 主要作用代替servlet程序回传html页面的数据
- 因为Servlet程序回传html页面数据是一件非常繁琐的事,开发成本和维护成本都很高
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html; charset=utf-8");
PrintWriter printWriter = resp.getWriter();
printWriter.write("<html>\r\n");
printWriter.write("<head>\r\n");
printWriter.write("</head>\r\n");
printWriter.write("<body>\r\n");
printWriter.write("<a> hello </a>\r\n");
printWriter.write("</body>\r\n");
printWriter.write("</html>\r\n");
}
6.6 jsp的本质是什么?
本质是一个Servlet程序
当我们第一次访问jsp页面时,Tomcat服务器会帮我们把jsp页面翻译成一个Java源文件,并将它编译成为.class字节码程序。
打开Java源文件发现,其继承了HttpJspBase
HttpJspBase直接的继承了HttpServlet
其Servlet程序的源代码,不难发现,其底层的实现,也是通过输出流。将html页面数据回传给客户端
6.7 jsp头部的page指令
<%@ page contentType=“text/html;charset=UTF-8” language=“java” %>
autoFlush属性:设置当out输出流缓冲区满了之后,是否自动刷新缓冲区。默认为true(out缓冲期满了之后不能自动刷新,就会报错)
buffer属性:设置out缓冲区大小为8kb
6.8 jsp中的常用脚本
- 声明脚本
<%! 声明Java代码 %>
(1)声明类属性
<%!
private Integer id;
%>
(2)声明static静态代码块
<%!
static {
map = new HashMap<String, Object> (); // 此处需要使用page导包
}
%>
(3)声明类方法:
<%!
public int abc(){
return 12;
}
%>
(4)生成内部类
<%!
public static class A(){
private Integer id;
}
%>
- 表达式脚本(不可以以封号结束)
<%= xxxx %>
在jsp页面上输出数据 :out.print("xxxx");
由于表达式脚本翻译的内容都在_jspService()中,所以_jspService()方法中的对象都可以直接使用
- 代码脚本
// 格式
<%
java语句
%>
// 多个代码脚本可以完成一个Java语句
6.9 jsp中的三种注释
HTML注释:
JAVA注释://、/* */
JSP注释:<%-- --%>
6.10 jsp中的9大内置对象
jsp中的内置对象,是指Tomcat在翻译jsp页面成为Servlet源代码后,内部提供的九大对象,叫做内置对象
request(请求对象)
response(响应对象)
pageContext(jsp的上下文对象)
session(会话对象)
application(ServletContext对象)
config(ServletConfig对象)
out(JSP输出流对象)
page(指向当前jsp的对象 )
exception(异常对象)
- jsp四大域对象
域对象是可以像Map一样存取数据的对象
四个域对象功能一样,不同的是他们对于数据的存取范围
(1)pageContext(PageContextImpl类):当前jsp范围内有效
(2)request(HttpServletRequest):一次请求内有效
(3)session(HttpSession类):一个会话范围内有效,打开浏览器访问服务器,知道关闭浏览器
(4)application(ServletContext对象):整个web工程范围内都有效,只要web工程不停止,数据都在
2. jsp中的out输出和response.getWritter输出的区别
(1)response表示响应,设置返回给客户端的内容的输出
(2)out也是给用户做输出使用的
1
<%
out.write("out输出------");
response.getWriter().write("response输出------");
%>
输出结果:
response输出------
1 out输出------
分析结果:
(1)out缓冲区、response缓冲区
(2)当jsp页面中所有代码执行完成之后会进行下面两个操作:
执行out.flash()操作,将out缓冲区中的数据追加写入到response缓冲区末尾
会执行response的刷新操作,会把全部数据写给客户端
out.print(12) // 可以显示 (输出任意数据会转化为字符串之后调用write输出)
out.write(12) // 不能显示 (输出字符串没有问题)
6.11 jsp的常用标签
- 静态包含
静态包含其实是把被包含的jsp页面的代码拷贝到包含的位置执行输出。
<%@ include file="index.jsp" %>
- 动态包含
调用方法不同
<jsp:include page="index.jsp" >
<jsp:param name="usrname" value="xx" ></jsp>
<jsp:param name="password" value="xxx" ></jsp>
</jsp:include>
- 请求转发
<jsp:forward page="/index.jsp"></jsp:forward>
<%
request.getRequestDispatcher("index.jsp").forward(request,response)
%>
6.12 Listener监听器
- 基本概念
Listener监听器他是JavaWeb的三大组件之一
Listener他是JavaEE 规范,就是接口
作用是:监听某种事物的变化,然后通过回掉函数,反馈给客户去做一些响应的处理
- ServletContextListener监听器
他可以监听ServletContext对象的创建和销毁
ServletContext对象在web工程启动的时候创建,在web工程停止的时候销毁
监听到创建和销毁之后分别会调用ServletContextListener监听器的方法反馈
两个方法分别是:
- 实现步骤:
(1) 编写一个类去实现ServletContextListener
(2)实现ServletContextListener
(3)到web.xml中配置
public class Test implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("servletContext 初始化了--------");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("servletContext 被销毁了--------");
}
}
<listener>
<listener-class>Test</listener-class>
</listener>
7、EL表达式
7.1 作用
EL表达式的作用主要是代替jsp页面中的表达式在jsp页面中进行数据的输出。
因为EL表达式在输出数据的时候,要比jsp表达式脚本要简洁很多
<%@ page isELIgnored="false" %>
7.2 EL表达式搜索数据的顺序
当四个域中都有相同的key的数据的时候,EL表达式会按照四个域 从小到大的顺序区进行搜索,找到就输出
pageContext < request < session < pageContext
<%
pageContext.setAttribute("key", "1234");
request.setAttribute("key", "1234");
session.setAttribute("key", "1234");
application.setAttribute("key", "1234");
%>
${ key }
注意:EL表达式在寻找实体类中的属性元素时,是直接寻在getXXX()方法获取元素的值
private String username;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
${ key.username }
7.3 Empty表达式
${ empty 字段 } // 字段为空 则为真
7.4 点运算和【】运算
7.5 EL表达式中11个隐含对象
是EL表达式中自己定义的,可以直接使用
(1)pageContext:获取jsp中的九大内置对象
<%
request.getScheme(); // 获取请求的协议
request.getServerName(); // 获取请求的服务器ip或者域名
request.getServerPort(); // 获取服务器请求端口号
request.getContextPath(); // 获取工程路径
request.getMethod(); // 获取请求的方式(GET/POST)
request.getRemoteHost(); // 获取客户端ip地址
session.getId(); // 获取会话的ID
%>
${ pageContext.request.scheme }
${ pageContext.session.id }
(2)pageScope:获取域中的信息
(3)requestScope
(4)sessionScope
(5)applicationScope
<%
pageContext.setAttribute("key", "1234");
request.setAttribute("key", "1234");
session.setAttribute("key", "1234");
application.setAttribute("key", "1234");
%>
${ pageScope.key }
${ sessionScope.key }
${ requestScope.key }
${ applicationScope.key }
(6)param:获取参数信息
(7)paramValues
(8)header:获取请求头中的信息
(9)headerValues
(10)cookie
(11)initParam:可以获取在web.xml中配置的上下文参数()
7.6 在JSP页面中无法使用application.getxxx方法时
/**
* 添加jar包
*/
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
8、 JSTL标签库
8.1 概念
JSTL标签库:是一个不断完善的开放源代码的JSP标签库
EL表达式主要是为了替换JSP中的表达式脚本,而标签库是为了替换代码脚本,这样使得整个JSP页面变得更加简洁
8.2 导入
8.3 核心库的使用
- <c:set />:往域中保存数据
<c:set scope="session" value="123" var="keySet" />
${sessionScope.keySet}
- <c:if 表达式> </c:if>
<c:if test='${ 12 == 13 }'>
12 = 12
</c:if>
- <c:choose/>、<c:when>、<c:otherwise>标签
<c:set scope="session" value="99" var="cho" />
<c:choose>
<c:when test='${ sessionScope.cho > 100 }'>
<H1>大于100</H1>
</c:when>
<c:when test='${sessionScope.cho == 100}'>
<h1>等于100</h1>
</c:when>
<c:otherwise>
<h1>all</h1>
</c:otherwise>
</c:choose>
- <c:forEach />
<%--循环 1 - 10--%>
<c:forEach begin='1' end="10" var='i' >
${i}
</c:forEach>
<%--循环数组--%>
<%
request.setAttribute("arr", new String[]{"1", "2", "3"});
%>
<c:forEach items="${requestScope.arr}" var='arr'>
${arr}
</c:forEach>
<%--循环集合--%>
<%
Map<String, Object> map = new HashMap<String, Object>();
map.put("key1", "key -- 1");
map.put("key2", "key -- 2");
map.put("key3", "key -- 3");
map.put("key4", "key -- 4");
request.setAttribute("map", map);
%>
<c:forEach items="${requestScope.map}" var="map" >
<h1>${map.key}---${map.value}</h1>
</c:forEach>
9、文件的上传和下载
9.1 文件上传
- 必要条件
(1)要有一个form标签,method=post请求(get请求上传数据都会有长度限制,而post请求没有长度限制 )
(2)form标签的enctype="multipart/form-data"属性
(3)在form标签中使用input type=file添加上传文件
(4)编写服务器代码接收,处理上传数据
- enctype=“multipart/form-data”
表示提交的数据,以多段(每一个表单项一个数据段)的形式拼接,然后以二进制流的方式发送给服务器
ServletInputStream stream = req.getInputStream();
byte[] buffer = new byte[1024000];
int read = stream.read(buffer);
System.out.println(new String(buffer, 0, read));
/**
* 输出
*/
------WebKitFormBoundaryim00xjxYBTN09A5w
Content-Disposition: form-data; name="username"
侯保君
------WebKitFormBoundaryim00xjxYBTN09A5w
Content-Disposition: form-data; name="photo"; filename="截屏2019-10-1612.31.07.png"
Content-Type: image/png
- 导包
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
- 具体实现
/*
* 后台
*/
public class UploadTest extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1.先判断上传的数据是否为多端数据,只有多段的数据才是文件上传的
if (ServletFileUpload.isMultipartContent(req)) {
System.out.println("上传文件------");
// 创建FileItemFactory工厂实现类
FileItemFactory fileItemFactory = new DiskFileItemFactory();
// 创建用于解析上传数据的工具类
ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory);
List<FileItem> list;
try {
// 2.解析上传的数据,得到每一个表单项
list = servletFileUpload.parseRequest(req);
for (FileItem fileItem : list) {
if (fileItem.isFormField()) {
// 普通表单项
System.out.println("表单项的name属性值 : " + fileItem.getFieldName());
System.out.println("表单项的value属性值 : " + fileItem.getString("UTF-8"));
} else {
// 上传的文件
System.out.println("上传的文件的name属性值 : " + fileItem.getFieldName());
System.out.println("上传的文件的value属性值 : " + fileItem.getName());
fileItem.write(new File("/Users/baojunhou/Desktop/JAVA/web/insist_progrem/BookJDBCTest/photo/"+fileItem.getName()));
}
}
} catch (FileUploadException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
} else {
System.out.println("非上传文件------");
}
}
}
/*
* 前端jsp
*/
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<meta charset="UTF-8">
<body>
<form action="upload" method="post" enctype="multipart/form-data" >
姓名:<input name="username" type="text"><br/>
头像:<input type="file" name="photo"><br/>
<input type="submit" value="上传"><br/>
</form>
</body>
</html>
9.2 文件下载
public class DownLoadTest extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1、获取要下载的文件名
String downLoadFileName = "2.png";
// 2、读取要下载的文件内容(通过ServletContext对象可以读取)
ServletContext servletContext = getServletContext();
// 获取要下载的文件类型
String mimeType = servletContext.getMimeType("/photo/"+downLoadFileName);
System.out.println("下载的文件类型 : " + mimeType);
// 4、在回传前,告诉客户端返回的数据类型
resp.setContentType(mimeType);
// 5、还要告诉客户端收到的数据类型使用于下载(Content-Disposition:表示收到的数据怎么处理,attachment:表示附件)
resp.setHeader("Content-Disposition","attachment; filename="+downLoadFileName);
InputStream inputStream = servletContext.getResourceAsStream("/photo/"+downLoadFileName);
OutputStream outputStream = resp.getOutputStream();
// 3、将下载的内容回传给客户端
// 读取输入流中的全部数据,复制给输出流,输出给客户端
IOUtils.copy(inputStream,outputStream);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
- 中文乱码:
resp.setHeader(“Content-Disposition”,“attachment; filename=”+downLoadFileName);
当downLoadFileName为中文名称时,会出现乱码问题
/*
* IE/Google
*/
resp.setHeader("Content-Disposition","attachment; filename="+ URLEncoder.encode("中国.jpg","UTF-8"));
/*
* 火狐:base64编码器
*/
resp.setHeader("Content-Disposition","attachment; filename=?UTF-8?B?"+ new BASE64Encoder().encode("中国.jpg".getBytes("UTF-8"))+"?=");
public class Base64Test {
@Test
public void Base64Test1() throws IOException {
String str1 = "测试base64的句子。。";
// 创建一个base64编码器
BASE64Encoder base64Encoder = new BASE64Encoder();
// 执行base64编码操作
String encodeString = base64Encoder.encode(str1.getBytes("UTF-8"));
System.out.println(encodeString);
// 解码操作(解码器)
BASE64Decoder base64Decoder = new BASE64Decoder();
byte[] bytes = base64Decoder.decodeBuffer(encodeString);
String str2 = new String(bytes,"UTF-8");
System.out.println(str2);
}
}
// 输出结果:
5rWL6K+VYmFzZTY055qE5Y+l5a2Q44CC44CC
测试base64的句子。。
选择器:
if (req.getHeader("User-Agent").contains("firefox")) {
resp.setHeader("Content-Disposition","attachment; filename=?UTF-8?B?"+ new BASE64Encoder().encode("中国.jpg".getBytes("UTF-8"))+"?=");
} else {
resp.setHeader("Content-Disposition","attachment; filename="+ URLEncoder.encode("中国.jpg","UTF-8"));
}
10、项目设计
10.1 通过反射查找对象方法
public class ReflectTest {
String name = "register";
@Test
public void ReflectT() {
try {
Method method = ReflectTest.class.getDeclaredMethod(name);
System.out.println(method);
method.invoke(new ReflectTest());
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
public void login(){
System.out.println("登陆");
}
public void register(){
System.out.println("注册");
}
public void test(){
System.out.println("测试");
}
}
10.2 反射2
-----------
<form action="invoke" method="post" >
<input type="hidden" name="action" value="login">
姓名:<input name="ussssername" type="text"><br/>
<input type="submit" value="login test"><br/>
</form>
-------------
<form action="invoke" method="post" >
<input type="hidden" name="action" value="register">
姓名:<input name="xxxx" type="text"><br/>
<input type="submit" value="register test"><br/>
</form>
-------------
public class ReflectT extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println( "invoke ------ ");
String methodName = req.getParameter("action");
System.out.println(methodName);
System.out.println();
try {
Method method = this.getClass().getDeclaredMethod(methodName,HttpServletRequest.class,HttpServletResponse.class);
System.out.println(method);
method.invoke(this,req,resp);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
public void login(HttpServletRequest req, HttpServletResponse resp) {
System.out.println(" login ---- ");
}
public void register(HttpServletRequest req, HttpServletResponse resp) {
System.out.println(" register ---- ");
}
}
10.3 invoke3
通过继承一个抽象的Base
-----------
<form action="Function" method="post" >
<input type="hidden" name="action" value="login">
姓名:<input name="ussssername" type="text"><br/>
<input type="submit" value="login test"><br/>
</form>
-------------
<form action="Function" method="post" >
<input type="hidden" name="action" value="register">
姓名:<input name="xxxx" type="text"><br/>
<input type="submit" value="register test"><br/>
</form>
-------------
// -------------------------------------------------------------------------------
public abstract class ReflectT extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println( "invoke ------ ");
String methodName = req.getParameter("action");
System.out.println(methodName);
System.out.println();
try {
Method method = this.getClass().getDeclaredMethod(methodName,HttpServletRequest.class,HttpServletResponse.class);
System.out.println(" method :" + method);
method.invoke(this,req,resp);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
// -------------------------------------------------------------------------------
public class Function extends ReflectT {
public Function(){}
public void login(HttpServletRequest req, HttpServletResponse resp) {
System.out.println(" login ---- ");
}
public void register(HttpServletRequest req, HttpServletResponse resp) {
System.out.println(" register ---- ");
}
}
10.4 数据的封装和抽取BeanUtils的使用
- 导包
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.3</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>
- 实现
try {
User user = new User();
BeanUtils.populate(user,req.getParameterMap()); // 将表单提交的用户信息注入user中
} catch (Exception e) {
e.printStackTrace();
}
11、Cookie
11.1 什么是cookie?
cookie是服务器通知客户端保存键值对的一种技术
客户端有了cookie之后,每次都会发送给服务器
每个cookie大小不可以超过4kb
11.2 如何创建cookie
Cookie cookie = new Cookie("key1", "value1");
resp.addCookie(cookie);
try {
resp.getWriter().write("cookie创建成功");
} catch (IOException e) {
e.printStackTrace();
}
11.3 注意 resp.getWriter().write(“xxx”);中文乱码问题
resp.setContentType("text/html;charset=UTF-8");
resp.getWriter().write("cookie创建成功");
11.4 服务器获取cookie的值
Cookie[] cookies = req.getCookies();
for (Cookie cookie :cookies) {
try {
resp.getWriter().write("name : " +cookie.getName() + " - value : " + cookie.getValue());
} catch (IOException e) {
e.printStackTrace();
}
}
11.5 服务器修改Cookie的值
/**
* 方法一:直接给某个键重新赋值
*/
Cookie cookie = new Cookie("key1", "newValue");
/**
* 方法二:找到某个cookie值,然后调用setValue方法赋值
*/
cookie.setValue("newValue2");
11.6 cookie的生命控制
- setMaxAge()
正数,表示在指定的秒数后过期
负数,表示浏览器一关,cookie就过期
0,表示马上删除cookie
11.7 cookie的path设置
Cookie的path属性可以有效的过滤哪些Cookie可以发送给服务器。哪些不发
path属性是通过请求的地址来进行有效的过滤
public void cookieSetPath(HttpServletRequest req, HttpServletResponse resp) {
Cookie cookie = new Cookie("key1", "value1");
cookie.setPath(req.getContextPath() + "/abc");
System.out.println(cookie.getPath());
resp.addCookie(cookie);
try {
resp.setContentType("text/html;charset=UTF-8");
resp.getWriter().write("cookie创建成功");
} catch (IOException e) {
e.printStackTrace();
}
}
输出:
/BookJDBCTest_war/abc
12、Session会话
12.1 什么是Session会话?
Session就是一个接口(HttpSession)
Session就是会话,它是用来维护一个客户端和服务器之间关联的一种技术
每个客户端都有自己的一个Session会话
Session会话中,我们经常会用来保存用户登录之后的信息
12.2 Session的创建和获取
如何创建和获取Session,他们的API是一样的
request.getSession()
第一次调用是:创建Session会话
之后调用都是:获取前面创建好的Session会话对象
isNew(); 判断到底是不是刚创建出来的
每个会话都有一个身份证号。也就是ID值,而且这个ID值是唯一的
getID() 得到 Session的ID值
public void createSession(HttpServletRequest req, HttpServletResponse resp){
HttpSession session = req.getSession();
System.out.println(session.isNew());
System.out.println(session.getId());
}
12.3 Session域中的数据的存取
req.getSession().setAttribute("val1" , " value1");
req.getSession().getAttribute("val1");
12.4 Session的生命周期的控制
值为正数时,设定Session的超时时长
值为负数时表示永不超时
Session的默认超时时长为30min(在Tomcat服务器的配置文件 web.xml 中默认有以下的配置),可以在自己的web.xml中配置
<session-config>
<session-timeout>20</session-timeout>
</session-config>
req.getSession().getMaxInactiveInterval();
req.getSession().setMaxInactiveInterval(60*60*1000);
req.getSession().invalidate();
13、Filter过滤器
13.1 什么是Filter过滤器
Filter过滤器是Javaweb的三大组件之一。三大组件分别是:Servlet程序、Listener监听器、Filter过滤器
Filter过滤器他是JavaEE规范。也就是接口
Filter过滤器他的作用是:拦截请求、过滤响应
13.2 基本实现
public class FilterTest implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException { }
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpSession httpSession = req.getSession();
Object user = httpSession.getAttribute("user");
if (null == user) {
req.getRequestDispatcher("/login.jsp").forward(request,response);
return;
} else {
chain.doFilter(request,response);
}
}
@Override
public void destroy() { }
}
<filter>
<filter-name>filterTest</filter-name>
<filter-class>controller.FilterTest</filter-class>
</filter>
<filter-mapping>
<filter-name>filterTest</filter-name>
<!--
url-pattern配置拦截路径
/ 表示请求的地址为:http://localhost:port/工程路径/
-->
<url-pattern>/admin/*</url-pattern>
</filter-mapping>
13.3 Filter的生命周期
Filter的生命周期包含几个方法
(1)构造器方法:在web工程启动的时候执行(Filter已经创建)
(2)init初始化方法:在web工程启动的时候执行
(3)doFilter过滤方法
(4)destory销毁:停止web工程的时候执行
13.4 FilterConfig类
- 简介
FilterConfig是Filter过滤器的配置文件类
Tomcat每次创建Filter时,也会创建一个FilterConfig类,这里包含了Filter配置文件的配置信息
FilterConfig类的作用是获取Filter过滤器的配置内容
- 获取的内容信息
// 获取Filter的名称Filter-name的内容
@Override
public void init(FilterConfig filterConfig) throws ServletException {
filterConfig.getFilterName();
}
// 获取在Filter中配置的init-param初始化参数
// 在web.xml中配置
<filter>
<filter-name>filterTest</filter-name>
<filter-class>controller.FilterTest</filter-class>
<init-param>
<param-name>username</param-name>
<param-value>ld</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>filterTest</filter-name>
<!--
url-pattern配置拦截路径
/ 表示请求的地址为:http://localhost:port/工程路径/
-->
<url-pattern>/admin/'*'</url-pattern>
</filter-mapping>
@Override
public void init(FilterConfig filterConfig) throws ServletException {
filterConfig.getInitParameter("username");
}
// 获取ServletContext对象
@Override
public void init(FilterConfig filterConfig) throws ServletException {
filterConfig.getServletContext();
}
13.5 FilterChain类(过滤器链)
- 简介(filterChain.doFilter() )
执行下一个Filter过滤器(如果有Filter)
执行目标资源(没有Filter)
- 操作步骤
// 在配置文件中,谁先配置谁先执行
<filter>
<filter-name>filter1</filter-name>
<filter-class>controller.Filter1</filter-class>
</filter>
<filter-mapping>
<filter-name>filter1</filter-name>
<url-pattern>/index.jsp</url-pattern>
</filter-mapping>
<filter>
<filter-name>filter2</filter-name>
<filter-class>controller.Filter2</filter-class>
</filter>
<filter-mapping>
<filter-name>filter2</filter-name>
<url-pattern>/index.jsp</url-pattern>
</filter-mapping>
- 多个Filter过滤器执行的特点
多个filter和目标资源默认都执行在同一个线程中
多个filter共同执行的时候,他们都使用一个Request对象
13.6 Filter的拦截路径
- 精确匹配
<url-pattern>/index.jsp</url-pattern>
- 目录匹配
<url-pattern>/admin/'*'</url-pattern>
- 后缀名匹配
<url-pattern>'*'.html</url-pattern>
<url-pattern>'*'.do</url-pattern>
<url-pattern>'*'.action</url-pattern>
13.7 使用Filter和ThreadLocal管理事务
14、使用Tomcat统一管理异常
<error-page>
<error-code>500</error-code>
<location>/pages/error/error500.jsp</location>
</error-page>
需要将异常抛给服务器