面4-JavaWeb

1、XML简介

1.1 什么是XML?
  1. xml是可扩展性的标记性语言
  2. 可扩展的含义是:标签可以自定义
1.2 作用
  1. 用来保存数据,而且这些数据具有自我描述性
  2. 可以作为项目或者模块的配置文件
  3. 可以作为网络传输数据的格式
1.3 语法
  1. 文档声明
<?xml version="1.0" encoding="utf-8" ?>
  1. 元素(标签)
<books>
    <book sn ="SN123" >  <!-- 属性可以提供元素的额外信息,每个属性的值必须使用“”引起来  -->
        <name></name>
        <age>123</>
    </book>
</books>

根元素就是顶级元素
没有父标签的元素叫顶级元素
根元素是没有父标签的顶级元素

  1. xml属性
  2. xml注释
  3. 文本区域(CDATA区):将输入的字符原样显示,不需要xml解析
            <![CDATA[
                <<<<<<<<<
            ]]>
1.4 xml的解析技术
  1. xml是可扩展性的标记语言,不管是html文件还是xml文件它们都是标记型文档,都可以使用w3c组织制定的dom技术来解析
  2. document:表示的是整个文档(可以是html文档,也可以是xml文档)
  3. 解析历程
    (1)早期:DOM,SAX
    (2)第三方解析:
    jdom 在 dom基础上进行了封装
    dom4j又对jdom进行了封装
    pull主要用于Android手机开发,根sax类似
1.5 dom4j解析技术

dom4j解析技术

2、 JavaWeb的概念

2.1 什么是javaWeb

所有通过Java语言编写的可以通过浏览器访问的程序的总称
是基于请求和响应开发的

2.2 请求和响应

request、response

2.3 web资源的分类

web资源按照实现的技术和呈现的效果不同,又分为静态资源和动态资源两种

  1. 静态资源:html,css,js,txt,mp4
  2. 动态资源:jsp,servlet程序
2.4 常用的服务器
  1. Tomcat
  2. JBoss
  3. GlassFish
  4. Resin
  5. WebLogic
2.5 动态web工程
  1. WEB-INF:其中的WEB-INF目录是一个受服务器保护的目录,浏览器无法直接访问其中的内容
  2. web.xml:是整个动态web工程的配置部署描述文件
    (1)Servlet程序
    (2)Filter过滤器
    (3)Listener监听器
    (4)Session超时

3、Tomcat服务器

3.1 Tomcat服务器和Servlet版本的对应关系

在这里插入图片描述

3.2 Tomcat在mac下的安装
  1. 下载
  2. 解压
  3. 打开终端 启动tomcat:sudo sh ./startup.sh
  4. 关闭 tomcat:sh ./shutdown.sh
3.3 Tomcat另一种部署项目方式

在conf目录下的/Catalina/localhost中,写配置文件xxx.xml

<Context path="/abc" docBase="路径" />
3.4 访问路径
  1. file:///E:/book/index.html(file://协议,直接读取file:协议后面的路径,解析展示在浏览器上即可)
  2. http://www.baidu.com

4、Servlet

4.1 基本概念
  1. Servlet是JavaEE规范之一。规范就是接口
  2. Servlet是JavaWeb三大组件之一。
  3. 三大组件:Servlet程序、Filter过滤器、Listener监听器
  4. 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>
  1. 编写一个类区实现servlet接口
  2. 实现service方法,处理请求,并响应数据
  3. 到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

  1. /JavaWeb_war_explod :为工程路径
  2. /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
  1. 实现doGet()、和doPost()方法
4.7 servlet体系
  1. 在这里插入图片描述
4.8 ServletConfig类
  1. ServletConfig类的作用:

是servlet程序的配置信息类
Servlet程序和ServletConfig对象是由Tomcat负责创建的,我们负责使用
Servlet程序默认是第一次访问的时候创建,ServletConfig是每个Servlet程序创建的时候,就创建一个对应的ServletConfig对象

  1. 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());
    }
  1. service实现方法中获取ServletConfig
ServletConfig servletConfig = getServletConfig(); 
  1. 继承实现HttpServlet中的init()方法获取ServletConfig
@Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
    } 
4.9 ServletContext类
  1. 什么是ServletContext?

ServletContext是一个接口,他表示Servlet上下文对象
一个web工程,只有一个ServletContext对象实例
ServletContext对象是一个域对象
ServletContext是在web工程部署启动的时候创建,在web工程停止的时候销毁

  1. 什么是域对象:

域对象,是可以像Map一样存取数据的对象,叫做域对象
这里的域值得是可以存取数据的操作范围

  1. ServletContext类的四个作用

(1)获取web.xml中配置的上下文参数 context-param(context-param是上下文参数,它属于整个web工程 )
(2)获取当前的工程路径,格式:/工程路径
(3)获取工程部署后在服务器硬盘上的绝对路径
(4)像Map一样存取数据 (ServletContext是在web工程部署启动的时候创建,在web工程停止的时候销毁 -------> 只要存一次,就可以在web工程停止之前一直取到数据)

  1. 实例:
<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类
  1. HttpServletRequest类的作用

每次只要有请求进入Tomcat服务器,Tomcat服务器就会把请求过来的HTTP协议信息解析好封装到Request对象中
然后传递到service方法(doGet\doPost)中给我们使用。我们可以通过HttpServletRequest对象,获取到所有请求的信息

  1. 常用方法:

(1)getRequestURI() // 获取请求的资源路径
(2)getRequestURL() // 获取请求的统一资源定位符(绝对路径)

  1. 实例:
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
    }
  1. 注意:

当表单提交 发送的为GET请求的时候,不会发生中文乱码
当表单提交 发送的为POST请求的时候,会发生中文乱码

request.setCharacterEncoding("UTF-8");
4.11 请求转发
  1. 什么是请求转发?

服务器收到请求之后,从一个资源跳转到另外一个资源的操作叫做请求转发

  1. 代码实例:
/**
 * 例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. 请求转发的特点:

(1)浏览器地址栏没有发生变化
(2)一次请求
(3)共享request域中的数据
(4)可以转发到 WEB-INF 目录下
(5)是否可以访问工程以外的资源:不可以 —> /JavaWeb_war_exploded/http://www.baidu.com

4.12 HttpServletResponse类
  1. 基本概念

每次请求进来Tomcat服务器都会创建一个Response对象传递给Servlet程序去使用,表示的是响应信息
我们如果需要设置返回给客户端的信息,我们都可以通过HttpServletResponse对象来进行设置

  1. 两个输出流的说明

(1)字节流:getOutputStream() 常用于下载(传递二进制数据)
(2)字符流:getWrite() 常用于回传字符串
注意:两个流同时只能使用一个,使用了字节流就不能再使用字符流,反之亦然。
同时使用两个响应流会报错

  1. 往客户端回传字符
        PrintWriter printWriter = response.getWriter();
        printWriter.write("xxxxx");
  1. 往客户端回传字符解决中文乱码
/**
 * 方法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. 定义:

指客户端给服务器发送请求,然后服务器告诉客户端,去访问新的地址

  1. 使用方法:
/**
 * 方法1:
 */
        response.setStatus(302);
        response.setHeader("Location", "xxxxxx");
/**
 * 方法2:
 */
  		response.sendRedirect("xxx");
  1. 请求重定向的特点:

(1)浏览器的地址栏会发生变化
(2)两次请求
(3)不共享Request域中的数据
(4)不能访问WEB-INFO目录下的文件
(5)可以访问工程以外的资源

5、Http协议

5.1 什么是Http协议
  1. 什么是协议?

指的是双方或者多方相互约定好,大家都要遵守的规则,叫做协议

  1. 什么是Http协议

所谓http协议就是客户端和服务器之间通信时,发送数据需要遵守的协议

  1. 报文

HTTP协议中的数据

5.2 请求的Http协议格式
  1. GET请求:

(1)请求行
请求的方式: GET
请求的资源路径[+?+请求参数]
请求的协议和版本号:HTTP/1.1
(2)请求头
key:value 组成 不同的键值对,表示不同的含义
Accept:告诉服务器,客户端可以接收的数据类型
Accept-Language:告诉服务器,客户端可以接收的语言类型
User-Agent:浏览器的信息
Accept-Encoding:告诉服务器,客户端可以接收的数据编码格式
Host:服务器的ip和端口号
(3)请求体:发送给服务器的数据

  1. 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协议格式
  1. 常用的响应码说明
200 表示请求成功
302 表示请求重定向
404 表示请求服务器已经收到,但是需要的数据不存在(请求地址错误)
500 表示服务器已经收到请求,代码错误
5.4 MIME类型说明
  1. 是HTTP协议中数据类型

6、JSP页面

6.1 解决base页面乱码问题
<%@ page contentType="text/html;charset=UTF-8" language="java" %>

6.2 base标签解决路径问题
  1. 基本概念

base标签设置页面相对路径工作时参照的地址
href属性就是参数的地址值

  1. 应用
<head>
    <meta charset="UTF-8">
    <base href="http://localhost:8080/BookJDBCTest_war/">
</head>
  1. 具体实例
	<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中,“/” 的不同意义
  1. “ / ” 如果被浏览器解析,得到的地址是:
http://ip:port/
<a href="/">xx</>
  1. “ / ” 如果被服务器解析,得到的地址是:
http://ip:port/工程路径
<url-pattern>/xxx</url-pattern>
servletContext.getRealPath("/");
request.getRequestDispathcer("/");
6.5 什么是JSP页面,他有什么用?
  1. Java的服务器页面(Java server pages)
  2. 主要作用代替servlet程序回传html页面的数据
  3. 因为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中的常用脚本
  1. 声明脚本
<%! 声明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;
}
%>

  1. 表达式脚本(不可以以封号结束)
<%= xxxx %>   
在jsp页面上输出数据 :out.print("xxxx"); 

由于表达式脚本翻译的内容都在_jspService()中,所以_jspService()方法中的对象都可以直接使用

  1. 代码脚本
	// 格式
	<%
		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(异常对象)

  1. 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的常用标签
  1. 静态包含

静态包含其实是把被包含的jsp页面的代码拷贝到包含的位置执行输出。

<%@ include file="index.jsp" %> 
  1. 动态包含

调用方法不同

<jsp:include page="index.jsp" >
	<jsp:param name="usrname" value="xx" ></jsp>
	<jsp:param name="password" value="xxx" ></jsp>
</jsp:include>
  1. 请求转发
<jsp:forward page="/index.jsp"></jsp:forward> 

<%
request.getRequestDispatcher("index.jsp").forward(request,response)
%>
6.12 Listener监听器
  1. 基本概念

Listener监听器他是JavaWeb的三大组件之一
Listener他是JavaEE 规范,就是接口
作用是:监听某种事物的变化,然后通过回掉函数,反馈给客户去做一些响应的处理

  1. ServletContextListener监听器

他可以监听ServletContext对象的创建和销毁
ServletContext对象在web工程启动的时候创建,在web工程停止的时候销毁
监听到创建和销毁之后分别会调用ServletContextListener监听器的方法反馈
两个方法分别是:

  1. 实现步骤:

(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 核心库的使用
  1. <c:set />:往域中保存数据
<c:set scope="session" value="123" var="keySet" />
${sessionScope.keySet}
  1. <c:if 表达式> </c:if>
<c:if test='${ 12 == 13 }'>
    12 = 12
</c:if>
  1. <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> 
  1. <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. 必要条件

(1)要有一个form标签,method=post请求(get请求上传数据都会有长度限制,而post请求没有长度限制 )
(2)form标签的enctype="multipart/form-data"属性
(3)在form标签中使用input type=file添加上传文件
(4)编写服务器代码接收,处理上传数据

  1. 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
  1. 导包
    <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>
  1. 具体实现
/*
 * 后台
 */ 

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);
    }
}
  1. 中文乱码:

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的使用
  1. 导包
    <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>
  1. 实现
		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的生命控制
  1. 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类
  1. 简介

FilterConfig是Filter过滤器的配置文件类
Tomcat每次创建Filter时,也会创建一个FilterConfig类,这里包含了Filter配置文件的配置信息
FilterConfig类的作用是获取Filter过滤器的配置内容

  1. 获取的内容信息
// 获取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类(过滤器链)
  1. 简介(filterChain.doFilter() )

执行下一个Filter过滤器(如果有Filter)
执行目标资源(没有Filter)

  1. 操作步骤
  // 在配置文件中,谁先配置谁先执行
  <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>
  1. 多个Filter过滤器执行的特点

多个filter和目标资源默认都执行在同一个线程中
多个filter共同执行的时候,他们都使用一个Request对象

13.6 Filter的拦截路径
  1. 精确匹配
<url-pattern>/index.jsp</url-pattern>
  1. 目录匹配
<url-pattern>/admin/'*'</url-pattern>
  1. 后缀名匹配
<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>

需要将异常抛给服务器

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值