HTML和CSS

  • ctrl + shift + / 在同一行代码中的后半截产生注释

HTML标签的介绍

  • 标签拥有自己的属性,分为 基本属性 和 事件属性
  • 标签的基本属性bgcolor="red 可以修改简单的样式效果
  • 标签的事件属性onclick="alert('你好');"

单标签:

  • br/ 换行
  • hr/ 水平线

常用标签介绍:

  • foot标签是字体标签,可以用来修改文本的 字体face,颜色color,大小size
  • 特殊字符 :小于号,空格,和号&,引号",撇号’ 等 我是<br>标签
  • 标题标签 :h1 到 h6, 属性align控制左对齐left(默认),中间center,右对齐(会随着窗口大小自动调整)
  • 超链接标签 :属性href控制链接,属性target控制当前(_self),和另一个页面(_blank)
  • 无序列表ul :属性type可以修改列表项前面的符号(兼容)
  • img标签 :属性src设置图片的路径,width,height,border设置边框大小,alt
  • 表格标签table,tr是行标签,th(相当于td加上b加粗)是表头标签,td是单元格标签,align设置单元格文本对齐方式;bordr,width,height,align设置表格相对于页面的对齐方式,cellspacing设置单元格间距
  • 跨行跨列表格,colspan属性设置跨列(用了以后要把其他同一行的单元格删掉部分,否则表格会突出);rowspan属性设置跨行
  • iframe框架标签(内嵌窗口),可以在一个html页面上打开一个小窗口小区域,去加载一个单独的页面;iframe标签和a标签组合使用的步骤 :1.在iframe标签中使用name属性定义一个名称;2.在a标签的target属性上设置iframe的name属性值
  • 表单标签form :
  • 表单格式化 :form里面嵌套table
  • 表单提交的细节 :

  • 其他标签 :div标签默认独占一行;span标签 它的长度是封装数据的长度;p段落标签 默认会在段落的上方或下方各空出一行来(如果已经有就不再空)

CSS技术

常用样式:

  • 字体颜色color: red;
  • 宽度;高度;(像素值 / 百分比值)
  • 背景颜色background-color
  • 字体大小font-size
  • 红色1像素实线边框border: 1px solid red;
  • DIV居中margin-left: auto; margin-right: auto;
  • 文本居中text-align: center;
  • 超链接去下划线text-decoration: none;
  • 表格细线 :
  • 列表去除修饰ul {list-style: none;}

JavaScript语言入门

  • JS是弱类型(类型可变),Java是强类型
  • 特点 :1.信息的动态交互;2.安全性,不允许直接访问本地硬盘;3.跨平台性,只要是可以解释js的浏览器都可以执行,和平台无关
  • src属性专门用来引入js文件路径(可以是相对路径或者绝对路径)

变量

  • typeof()函数 判断变量的类型

比较运算

逻辑运算


数组

  • var arr = [];
  • var arr = [1,'abc',true];
  • js语言中的数组,只要我们通过数组下标赋值,那么最大的下标值,就会自动给数组做扩容操作

函数

  • 在java中函数允许重载,但是在js中函数的重载会直接覆盖掉上一次的定义

  • 函数的隐形参数 arguments(只在function函数内)

JS中的自定义对象


js中的事件

  • 事件 : 电脑输入设备与页面进行交互的响应

常用的事件 :

  • onload 加载完成事件;页面加载完成后,常用于做页面js代码初始化操作
  • onclick 单击事件;常用于按钮的点击响应操作
  • onblur 失去焦点事件;常用于输入框失去焦点后验证其输入内容是否合法
  • onchange 内容发生改变事件;常用于下拉列表和输入框内容发生改变后操作
  • onsubmit 表单提交事件;常用于表单提交前,验证所有表单项是否合法



  • 阻止表单提交 :
  • 静态注册 : 在标签属性中的onsubmit中 不仅要在函数中return false,在调用函数的前面,还要加上一个return!
  • 动态注册 : 直接在 标签对象 的函数中return false 即可

DOM模型

  • DOM全称是 Document Object Model 文档对象模型
  • 就是把文档中的 标签,属性,文本 转换成对象来管理
  • document对象 的理解 :
    1.document管理了所有的html文档内容
    2.document是一种 树结构 的文档,有层级关系
    3.它让我们把所有的标签 都 对象化
    4.我们可以通过document访问所有的标签对象
  • 正则表达式RegExp :
    1.表示要求字符串中,是否包含字母e :
    1)var patt = new RegExp(“e”);
    2)var patt = /e/;
    3)以上两种皆为 正则表达式对象
    4)验证方法 :
    var str = “abcd”;
    alert(patt.test(str));
    2.表示要求字符串中,是否包含字母a或b或c : var patt = /[abc]/;
    3.表示要求字符串中,是否包含任意小写字母 : var patt = /[a-z]/;
    4.表示要求字符串中,是否包含任意数字 : var patt = /[0-9]/;
    5.元字符中 \w 用于查找单词字符(a-z,A-Z,0-9,下划线);因此,var patt = /\w/; 表示要求字符串中,是否包含字母,数字,下划线; \W 查找 非单词字符
    6.量词中 a+ ,var patt = /a+/;表示要求字符串中,是否包含至少一个a;var patt = /a*/;表示字符串中是否包含零个 或 多个a;var patt = /a?/;表示字符串中是否包含零个 或 一个a;var patt = /a{3}/;表示字符串中是否包含连续三个a

  • document.getElementByName() :根据指定的name属性查询返回多个标签对象集合;这个集合的操作和数组一样;集合中每个元素都是dom对象;这个集合中的元素顺序是他们在html页面中从上到下的顺序
  • document.getElementByTagName() :按照指定标签名来进行查询并返回集合;同上
  • document对象的三个查询方法,如果有id属性,优先使用ById;如果没有id属性,则优先使用ByName;最后才用TagName
  • 以上三个方法一定要在页面加载完成之后执行,才能查询到标签对象

节点的常用属性和方法

  • 方法 :
    appendChild(divObj)
    document.createElement(tagName) 通过给定的标签名,创建一个标签对象
  • 属性 :
    childNodes 获取当前节点的所有子节点
    firstChild
    lastChild
    parentNode
    nextSibling
    previousSibling
    className 获取或设置标签的class属性值
    innerHtml 内容
    innerText 文本

jQuery

  • 引入jQeury库,<script type="text/javascripy" src="../script/jquery-1.7.2.js"></script>
  • $(function () {}); 表示 页面加载完成之后,相当于window.onload = function () {}
  • var $btnObj = $("#btnId"); 表示按id查询标签对象
  • $btnObj.click(function () {alert("");}); 绑定单击事件

$是jQeury的核心函数
传入参数为 函数 时 :表示页面加载完成之后,相当于window.onload = function () {}
传入参数为 HTML字符串 时 :会对我们创建这个html标签对象
传入参数为 选择器字符串 时 :id选择器、标签名选择器、类型选择器
传入参数为 DOM对象 时 : 会把这个dom对象转换为jQeury对象

jQeury对象和dom对象区分

  • jQeury对象的本质 :是dom对象的数组 + jQeury提供的一系列功能函数
  • jQeury对象不能使用DOM对象的属性和方法;DOM对象也不能使用jQeury…

dom对象转化为jQeury对象
1.先有dom对象
2.$(dom对象);就可以

jQeury对象转化为dom对象
1.先有jQeury对象
2.jQeury对象[下标]取出相应的dom对象

基础选择器

层级选择器

基本过滤选择器

内容过滤选择器

属性过滤选择器

表单过滤选择器

筛选元素

属性的操作


dom的增删改




CSS样式操作

jQeury动画

jQeury事件操作


jQeury中其他事件的处理方法

事件冒泡

事件对象

XML

<?xml version="1.0" encoding="utf-8" ?>
<!--
    <?xml version="1.0" encoding="utf-8" ?>
    以上内容就是xml文件的声明
    version="1.0"   version表示xml的版本
    encoding="utf-8"  encoding表示xml文件本身的编码
-->

<books>
    <book sn="1">
        <name>时间简史</name>
        <author>霍金</author>
        <price>100</price>
    </book>
    <book sn="2">
        <name>java</name>
        <author>teacher</author>
        <price>120</price>
    </book>
</books>


xml解析技术介绍

  • 不管是html文件还是xml文件它们都是标记型文档,都可以使用w3c组织制定的dom技术来解析
package com.atguigu.pojo;

import java.math.BigDecimal;

public class Book {
    private String sn;
    private String name;
    private BigDecimal price;
    private String author;

//    control + enter 快速生成函数


//    constructor -> a全选 -> ok
    public Book(String sn, String name, BigDecimal price, String author) {
        this.sn = sn;
        this.name = name;
        this.price = price;
        this.author = author;
    }

    @Override
    public String toString() {
        return "Book{" +
                "sn='" + sn + '\'' +
                ", name='" + name + '\'' +
                ", price=" + price +
                ", author='" + author + '\'' +
                '}';
    }

    //    constructor -> select none
    public Book() {
    }

    public String getSn() {
        return sn;
    }

    public void setSn(String sn) {
        this.sn = sn;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public BigDecimal getPrice() {
        return price;
    }

    public void setPrice(BigDecimal price) {
        this.price = price;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }
}

package com.atguigu.pojo;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.junit.jupiter.api.Test;

import java.util.List;

public class Dom4jTest {

    @Test
    public void test1() throws DocumentException {
        SAXReader saxReader = new SAXReader();

//        Document document = saxReader.read("src/books.xml");
        Document read = saxReader.read("src/books.xml");

//        System.out.println(document);
    }


    @Test
    public void test2() throws DocumentException {
        SAXReader reader = new SAXReader();
        Document document = reader.read("src/books.xml");
        Element rootElement = document.getRootElement();

//        System.out.println(rootElement);
        List<Element> books = rootElement.elements("book");

        for (Element book : books) {
//            System.out.println(book.asXML());
//            Element name = book.element("name");
//            System.out.println(name.asXML());
//            String text = name.getText();
//            System.out.println(text);
            String price = book.elementText("price");
            System.out.println(price);
        }
    }
}

JavaWeb

Web资源的分类

  • web资源按实现的技术和呈现的效果的不同,又分为静态资源和动态资源两种
  • 静态资源 :html、css、js、txt、mp4视频、jpg图片
  • 动态资源 :jsp页面、Servlet程序

常用的Web服务器
Tomcat :一种Web服务器,提供对jsp和Servlet的支持,它是一种轻量级的javaWeb容器(服务器),也是当前应用最广的JavaWeb容器(服务器)

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

Tomcat目录介绍
bin 专门用来存放tomcat服务器的可执行程序
conf 专门用来存放tomcat服务器的配置文件
lib 专门用来存放tomcat服务器的jar包
logs 专门用来存放tomcat服务器运行时输出的日记信息
temp 专门用来存放tomcat服务器运行时产生的临时数据
webapps 专门用来存放部署的web工程
work 是tomcat工作时的目录,用来存放tomcat运行时jsp翻译为servlet的源码,和session钝化的目录

如何在idea中部署工程到tomcat上运行

建议修改web工程对应的tomcat运行实例名称

Servlet 01

0.jsp,servlet,tomcat的关系

  • tomcat是web服务器(javaweb项目常用tomcat),servlet在tomacat中能运行,jsp是一种servlet
  • 浏览器是向服务器(tomcat)发出请求,然后tomcat根据浏览器的请求,派出对应的servlet去处理这些请求,在处理后,servlet得到一系列处理后的数据,然后将这个数据交给jsp,让jsp显示出来给用户看到
  • 在servlet中通过流将html代码输出给客户端(然后由客户端也就是浏览器渲染结果,所以并不是浏览器执行java代码),为了方便就诞生了jsp(本质上就是servlet),jsp中可以抛开java代码,直接使用html标签编写代码,这样就很好的将java代码和html代码分离,但其实jsp最终运行时会被编译成servlet

什么是Servlet

Servlet是JavaEE规范之一。规范 就是 接口
Servlet是JavaWeb三大组件之一。三大组件分别是 :Servlet程序、Filter过滤器、Listener监听器
Servlet是运行在服务器上的一个java小程序,它可以接收客户端发来的请求,并相应数据给客户端

手动实现Servlet程序

1.编写一个类去实现Servlet接口
2.实现service方法,处理请求,并相应数据
3.到web.xml中去配置servlet程序的访问地址

package com.atguigu.servlet;

import javax.servlet.*;
import java.io.IOException;

public class HelloServlet implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {

    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    /**
     * service方法 专门用来处理请求和响应的
     * @param servletRequest
     * @param servletResponse
     * @throws ServletException
     * @throws IOException
     */
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
//        System.out.println("HelloServlet 被访问了");
        System.out.println("this is the service method");
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp/xml/ns/javaee"
         xmlns:xsi="http://www.w3/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp/xml/ns/javaee http://xmlns.jcp/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <!-- servlet标签给tomcat配置servlet程序 -->
    <servlet>
        <!-- servlet-name标签 给Servlet程序起一个别名(一般是类名) -->
        <servlet-name>HelloServlet</servlet-name>
        <!-- servlet-class 是Servlet程序的全类名 -->
        <servlet-class>com.atguigu.servlet.HelloServlet</servlet-class>
    </servlet>


    <!-- servlet-mapping标签给servlet程序配置访问地址 -->
    <servlet-mapping>
        <!-- servlet-name标签的作用是告诉服务器,我当前配置的地址给哪个servlet程序使用 -->
        <servlet-name>HelloServlet</servlet-name>
        <!-- url-pattern标签配置访问地址
               / 斜杠在服务器解析的时候,表示地址为:http://ip:port/工程路径
               /hello 表示地址为:http://ip:port/工程路径/hello
         -->
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>

</web-app>

<!-- 常见错误1:url-pattern中配置的路径没有以斜杠打头 Invalid <url-pattern> hello in servlet mapping -->
<!-- 常见错误2:servlet-name配置的值不存在 Servlet mapping specifies an unknown sevlet name HelloServlet1 -->
<!-- 常见错误3:servlet-class标签的全类名配置错误 java.lang.ClassNotFoundException: com.atguigu.sssss.HelloServlet(写的时候直接输入Hello就会自己补全) -->

url地址如何定位到Servlet程序去访问 :

  • 在localhost中,一个程序可以占用多个端口号,但是一个端口号唯一标识一个程序

Servlet的生命周期

1.执行Servlet构造器方法
2.执行init初始化方法
第一、二步是在,第一次访问的,的时候 创建servlet程序会调用
3.执行service方法
第三步,每次访问都会调用
4.执行destroy销毁方法
第四步,在web工程停止的时候调用

package com.atguigu.servlet;

import javax.servlet.*;
import java.io.IOException;

public class HelloServlet implements Servlet {

	// Constructor方法(一开始点“实现方法”后这个不会出现,要另外再添加)
    public HelloServlet() {
        System.out.println("1 构造器方法");
    }

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("2 init初始化方法");
    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    /**
     * service方法 专门用来处理请求和响应的
     * @param servletRequest
     * @param servletResponse
     * @throws ServletException
     * @throws IOException
     */
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
//        System.out.println("HelloServlet 被访问了");
        System.out.println("3 service方法 -- HelloServlet被访问了");
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {
        System.out.println("4 destroy销毁方法");
    }
}

// console output
1 构造器方法
2 init初始化方法
3 service方法 -- HelloServlet被访问了
3 service方法 -- HelloServlet被访问了
3 service方法 -- HelloServlet被访问了
3 service方法 -- HelloServlet被访问了
3 service方法 -- HelloServlet被访问了
3 service方法 -- HelloServlet被访问了
3 service方法 -- HelloServlet被访问了

  • 因此发现是 单例模式

请求的分发处理

  • 问题 :service方法只有一个,而我们的请求有两种,一种是get,一种是post
  • 第1步,在 webapp 下创建一个 a.html ,里面有一个form表单,填入action属性(/hello)和method属性,form表单中有一个提交按钮
  • 第2步,启动服务器后,在工程后面加上/a.html,进入了http://localhost:8080/_servlet/a.html,然后按下提交按钮,就会进入hello,也就是http://localhost:8080/_servlet/hello?
  • 只有在点下按钮,进入到hello以后,Server才会输出“11111 Constructor
    22222 init
    33333 service – HelloServlet被访问啦“
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="http://localhost:8080/_servlet/hello" method="get">
        <!-- input:submit 然后tab -->
        <input type="submit">
    </form>
</body>
</html>
  • 将get改成post后,要记得刷新网页(但居然不需要重启服务器)
  • 改成post后,同样的操作,点了按钮后,会进入http://localhost:8080/_servlet/hello,同时,Server会输出"33333 service – HelloServlet被访问啦",service一样的被使用了
  • 问题 :一般情况下,get和post请求是不一样的,因此,在service方法中要写不同
  • 发现ServletRequest类无法直接使用getMethod方法
  • 查看子类 快捷键 :在HelloServlet.java中 鼠标选中 service方法中的 ServletRequest,然后control + h,然后显示该类(?)的层次结构,可以看到ServletRequest还有一个HttpServletRequest子类,点击后,看到里面有一个String getMethod()方法,也就是说子类可以
  • 因此,类型转换,将它转换为子接口(注意到这里是向下转型?,但本质上还是向上转型,接口的实现类就是它的子类,子类的对象就是该接口的子类对象),(快捷方式,先打出HttpServletRequest httpServletRequest = servletRequest;,然后option + enter,自动补全为HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
  • httpServletRequest.getMethod()后再option + enter然后补全为String method = httpServletRequest.getMethod();
@Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {

        // 类型转换(因为它有getMethod()方法)
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;

        // 获取请求的方式
        String method = httpServletRequest.getMethod();

        System.out.println(method);
    }
  • 然后 重启服务器,再在a.html中点击按钮后,Server中就会输出“POST“
  • 因此说明我们已经可以得到method了,那么就可以根据method的不同类型来作出不同代码
@Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        String method = httpServletRequest.getMethod();

        if ("POST".equals(method)) {
            System.out.println("post请求");
        } else {
            System.out.println("get请求");
        }
    }
  • 如果if里执行的语句太多,显得很臃肿;因此,我们采用 封装 的思想,将if中语句换成函数
@Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        String method = httpServletRequest.getMethod();

        if ("POST".equals(method)) {
            doPost();
        } else {
            doGet();
        }
    }
    
    public void doPost()
    {
        System.out.println("this is Post");
        System.out.println("ohayo!");
    }
    
    public void doGet()
    {
        System.out.println("this is Get");
        System.out.println("ohayo!");
    }

通过继承HttpServlet类来实现Servlet程序

  • 实际开发中,很少通过 “通过实现Servlet接口” 的方式来实现Servlet程序
  • 开发时,一般都是导入他的子类去继承即可
  • 一般在实际开发中,都是使用继承HttpServlet类的方法去实现Servlet程序
    1.编写一个类来继承HttpServlet类
    2.根据业务需求重写doGet()和doPost()方法
    3.到web.xml中配置Servlet程序的访问地址
package com.atguigu.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class HelloServlet2 extends HttpServlet {


    /**
     * 第一步,control + enter 然后点击 "重写方法"也就是 Overrride Methods
     * 第二部,按住 command ,然后就可以同时选择doGet()和doPost()
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        super.doGet(req, resp);
        System.out.println("this is HelloServlet2 - get");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        super.doPost(req, resp);
        System.out.println("this is HelloServlet2 - post");
    }
}

<!-- xml配置 -->
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp/xml/ns/javaee"
         xmlns:xsi="http://www.w3/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp/xml/ns/javaee http://xmlns.jcp/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    
    <servlet>
        <servlet-name>HelloServlet</servlet-name>
        <servlet-class>com.atguigu.servlet.HelloServlet</servlet-class>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>HelloServlet</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
    
    <servlet>
        <servlet-name>HelloServlet2</servlet-name>
        <servlet-class>com.atguigu.servlet.HelloServlet2</servlet-class>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>HelloServlet2</servlet-name>
        <url-pattern>/hello2</url-pattern>
    </servlet-mapping>
    
</web-app>
<!-- 修改html中表单的action属性 -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="http://localhost:8080/_servlet/hello2" method="post">
        <!-- input:submit 然后tab -->
        <input type="submit">
    </form>
</body>
</html>
  • 然后 重启服务器;就可以显示啦
  • 我们注意到在这个编写的继承类中,我们直接只需要重写doGet方法即可,不需要再得到method,然后ifelse

使用IDEA创建Servlet程序

  • 第一步,点击要在哪个包中编写这个类,然后

  • 会自动创建这个类(里面有准备好doGet方法和doPost方法的重写),以及在web.xml中自动配置(但要自行写serlet-mapping)

整个Servlet类的继承体系

ServletConfig类使用介绍


关于初始化参数init-param

  • 且这个init-param在一个servlet标签中可以有多对
  • servletConfig可以在HelloServlet的init初始化方法中使用

HelloServlet程序的别名是:HelloServlet
初始化参数username的值是:root
org.apache.catalina.core.ApplicationContextFacade@7602e52f

ServletConfig类的补充说明

  • Servlet程序和ServletConfig对象都是由Tomcat负责创建,我们负责使用
  • Servlet程序默认是第一次访问的时候创建,ServletConfig是每个Servlet程序创建时,就创建一个对应的ServletConfig对象
  • servletconfig还可以在除了init外使用 :

  • 重写 init方法后(init中只放了一个sout),在doGet方法中通过servletConfig获得init-param就会有 空指针异常
  • 注意,在重写了init方法后,一定要在里面调用super.init(config);,就不会报空指针异常
  • 原因 :doGet方法中的 getServletConfig()是从哪里来的呢?发现是从GenericServlet这个类的方法,而GenericServlet类持有一个ServletConfig类的引用;发现在GenericServlet类中的init方法有一个this.config = config;是将config保存起来,那我们如果重写不就没有了吗,那么父类中init的保存就消失了,因此,要写上super

  • 按住command 鼠标移到方法上 就可以查看 所在的类中这个方法的位置

ServletContext对象的介绍

ServletContext对象作用的演示

  • 先在web.xml中配置好ContextServlet程序的mapping 以及 上下文参数context-param
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp/xml/ns/javaee"
         xmlns:xsi="http://www.w3/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp/xml/ns/javaee http://xmlns.jcp/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <!-- context-param是上下文参数(它属于整个web工程,与servlet并列) -->
    <context-param>
        <param-name>username</param-name>
        <param-value>context</param-value>
    </context-param>

    <!-- context-param也可以拥有多对 -->
    <context-param>
        <param-name>password</param-name>
        <param-value>root</param-value>
    </context-param>

	<servlet>
    	...
</web-app>
  • 然后,通过 ServletConfig 来获得 ServletContext 对象
  • 有一个小细节,这个代码只能写在doGet中,写在doPost中是不会在Server中输出语句的
  • context.getInitParameter()只能得到context-param,不能得到servlet中的init-param(只能由ServletConfig的getInitParameter()得到)
package com.atguigu.servlet;

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;

public class ContextServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        // 1.获取web.xml中配置的上下文参数context-param
        ServletContext context = getServletConfig().getServletContext();

        String username = context.getInitParameter("username");
        System.out.println("context-param的参数username的值是:" + username);
        System.out.println("context-param的参数password的值是:" + context.getInitParameter("password"));

        // 2.获取当前的工程路径,格式:/工程路径
        System.out.println("当前工程路径:" + context.getContextPath());

        // 3.获取工程部署后在服务器硬盘的绝对路径
        /**
         *  /斜杠 被服务器解析地址为: http://ip:port/工程名/  映射到 IDEA代码的web目录
         */
        System.out.println("工程部署的路径是:" + context.getRealPath("/"));
        System.out.println("工程下css目录的绝对路径是:" + context.getRealPath("/css"));
//        System.out.println("工程下imgs目录1.jpg的绝对路径是:" + context.getRealPath("/imgs/1.jpg"));
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    }
}

<!-- Server输出的内容 -->
context-param的参数username的值是:context
context-param的参数password的值是:root
当前工程路径:/_servlet
工程部署的路径是:/Users/fieldxia/Desktop/JavaWeb/_servlet/target/_servlet-1.0-SNAPSHOT/
工程下css目录的绝对路径是:/Users/fieldxia/Desktop/JavaWeb/_servlet/target/_servlet-1.0-SNAPSHOT/css

ServletContext像map一样存取数据

public class ContextServlet1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 获取ServletContext对象
        ServletContext context = getServletContext();

        System.out.println("保存之前:Context1 获取key1的值为:" + context.getAttribute("key1"));

        context.setAttribute("key1", "value1");

        System.out.println("Context1 中获取域数据key1的值为:" + context.getAttribute("key1"));
        System.out.println("Context1 中获取域数据key1的值为:" + context.getAttribute("key1"));
    }
}

public class ContextServlet2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        ServletContext context = getServletContext();

        System.out.println("Context2 中获取域数据key1的值为:" + context.getAttribute("key1"));
    }
}
<!-- 只访问了/context1 -->
保存之前:Context1 获取key1的值为:null
Context1 中获取域数据key1的值为:value1
Context1 中获取域数据key1的值为:value1
<!-- 在访问了/context1后再访问了/context2 -->
保存之前:Context1 获取key1的值为:null
Context1 中获取域数据key1的值为:value1
Context1 中获取域数据key1的值为:value1
14-Mar-2022 19:45:37.570 信息 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory 把web 应用程序部署到目录 [/Users/fieldxia/Downloads/apache-tomcat-8.5.75/webapps/manager]
14-Mar-2022 19:45:37.601 信息 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Web应用程序目录[/Users/fieldxia/Downloads/apache-tomcat-8.5.75/webapps/manager]的部署已在[30]毫秒内完成
Context2 中获取域数据key1的值为:value1
<!-- 再访问一次/context1 -->
保存之前:Context1 获取key1的值为:null
Context1 中获取域数据key1的值为:value1
Context1 中获取域数据key1的值为:value1
14-Mar-2022 19:45:37.570 信息 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory 把web 应用程序部署到目录 [/Users/fieldxia/Downloads/apache-tomcat-8.5.75/webapps/manager]
14-Mar-2022 19:45:37.601 信息 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Web应用程序目录[/Users/fieldxia/Downloads/apache-tomcat-8.5.75/webapps/manager]的部署已在[30]毫秒内完成
Context2 中获取域数据key1的值为:value1
保存之前:Context1 获取key1的值为:value1
Context1 中获取域数据key1的值为:value1
Context1 中获取域数据key1的值为:value1
  • 因为 “ServletContext是在web1工程部署启动的时候创建。在web工程停止的时候销毁“
  • 因此, 如果 重新部署一次,或者重启这个工程,那么web工程就停止了,里面的数据就没有了
public class ContextServlet1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 获取ServletContext对象
        ServletContext context = getServletContext();

        System.out.println(context);
    }
}
public class ContextServlet2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        ServletContext context = getServletContext();

        System.out.println(context);
    }
}
<!-- 一个web工程,只有一个ServletContext对象实例 -->
org.apache.catalina.core.ApplicationContextFacade@4f419be1
14-Mar-2022 19:53:39.424 信息 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory 把web 应用程序部署到目录 [/Users/fieldxia/Downloads/apache-tomcat-8.5.75/webapps/manager]
14-Mar-2022 19:53:39.467 信息 [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Web应用程序目录[/Users/fieldxia/Downloads/apache-tomcat-8.5.75/webapps/manager]的部署已在[43]毫秒内完成
org.apache.catalina.core.ApplicationContextFacade@4f419be1

什么是HTTP协议

GET请求HTTP协议内容介绍


POST请求HTTP协议内容介绍


  • 注意要点了提交按钮以后才会是POST请求,直接在a.html录制还是GET请求



常用请求头

哪些是GET请求,哪些是POST请求

响应的HTTP协议介绍


常见的响应状态码说明

MIME数据类型

谷歌浏览器和火狐浏览器如何查看HTTP协议内容


  • 状态码304 点击 Disable Cache停用缓存 状态码200

Servlet 02

HttpServletRequest类的介绍

Request常用API的演示

public class RequestAPIServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // 获取请求的资源路径
        System.out.println("URI => " + req.getRequestURI());

        // 获取请求的统一资源定位符(绝对路径)
        System.out.println("URL => " + req.getRequestURL());

        // 获取客户端的ip地址
        /**
         * 在IDEA中 使用 localhost 访问时 得到的客户端ip地址是 => 127.0.0.1
         * 因此 将 "http://localhost:8080/_servlet02/requestAPIServlet"
         * 改成 "http://127.0.0.1:8080/_servlet02/requestAPIServlet" 也可以访问
         * 在IDEA中 使用 127.0.0.1 访问时 得到的客户端ip地址是 => 127.0.0.1
         * 在IDEA中 使用 真实ip 访问时 得到的客户端ip地址是 => 真实的客户端 ip地址
         */
        System.out.println("客户端 ip地址 => " + req.getRemoteHost());

        // 获取请求头
        System.out.println("请求头User-Agent => " + req.getHeader("User-Agent"));

        // 获取请求的方式 GET 或 POST
        System.out.println("请求的方式 => " + req.getMethod());
    }
}
URI => /_servlet02/requestAPIServlet
URL => http://localhost:8080/_servlet02/requestAPIServlet
客户端 ip地址 => 0:0:0:0:0:0:0:1
请求头User-Agent => Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36
请求的方式 => GET

获取请求的参数值-补充

<!-- form.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
  <form action="http://localhost:8080/_servlet02/parameterServlet" method="get">
    用户名:<input type="text" name="username"> <br/>
    密码:<input type="password" name="password"> <br/>
    兴趣爱好:<input type="checkbox" name="hobby" value="cpp">C++
    <input type="checkbox" name="hobby" value="java">Java
    <input type="checkbox" name="hobby" value="js">JS<br/>
    <input type="submit">
  </form>
</body>
</html>
public class ParameterServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 获取请求参数
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        String hobby = req.getParameter("hobby");

        System.out.println("username: " + username);
        System.out.println("password: " + password);
        System.out.println("hobby: " + hobby);
    }
}


跳转至http://localhost:8080/_servlet02/parameterServlet?username=javaweb&password=123456&hobby=cpp&hobby=java

<!-- Server -->
username: javaweb
password: 123456
hobby: cpp
  • 以上hobby的做法是错的,这样兴趣爱好多选只会返回一个值,应该将getParameter换成getParameterValues
public class ParameterServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 获取请求参数
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        String[] hobby = req.getParameterValues("hobby");

        System.out.println("username: " + username);
        System.out.println("password: " + password);
        System.out.println("hobby: " + Arrays.asList(hobby));
    }
}

http://localhost:8080/_servlet02/parameterServlet?username=123&password=123456&hobby=cpp&hobby=java&hobby=js

<!-- Server -->
username: 123
password: 123456
hobby: [cpp, java, js]

解决POST请求中文乱码问题

  • 如果在 用户名text 中输入中文的时候,如果method="get"不会有问题,但如果method="post",不是中文没有问题,但一旦是中文,getParameter时输出就变成乱码
  • 我们只需要一个操作
  • 注意!!!必须在获取请求参数之前调用才有效。比如说我先调用pasword的参数,然后才设置utf-8,然后再调用username,如果是post且中文,还是会乱码
@Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // 设置请求体的字符集为UTF-8,从而解决post请求的中文乱码问题
        // 也要在获取请求参数之前调用才有效
        req.setCharacterEncoding("UTF-8");

        String username = req.getParameter("username");
        String password = req.getParameter("password");
        String[] hobby = req.getParameterValues("hobby");

        System.out.println("username: " + username);
        System.out.println("password: " + password);
        System.out.println("hobby: " + Arrays.asList(hobby));
    }

请求的转发

public class Servlet1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // 获取请求的参数(办事的材料)查看
        String username = req.getParameter("username");
        System.out.println("在Servlet1(柜台1)中查看参数(材料): " + username);

        // 给材料 盖一个章,并传递到Servlet2(柜台2)去查看
        req.setAttribute("key1", "柜台1的章");

        // 问路:Servlet2(柜台2)怎么走
        /**
         * 请求转发必须要以斜杠打头, / 斜杠 表示地址为: http://ip:port/工程名/ ,映射到IDEA代码的web目录
         */
        RequestDispatcher requestDispatcher = req.getRequestDispatcher("/servlet2");

        // 走向Servlet2(柜台2)
        requestDispatcher.forward(req,resp);
    }
}
public class Servlet2 extends HelloServlet {
    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 获取请求的参数(办事的材料)查看
        String username = request.getParameter("username");
        System.out.println("在Servlet2(柜台2)中查看参数(材料): " + username);

        Object key1 = request.getAttribute("key1");
        System.out.println("柜台1是否有章:" + key1);

        // 处理自己的业务
        System.out.println("Servlet2 处理自己的业务");
    }
}
<!-- Server -->
在Servlet1(柜台1)中查看参数(材料): null
在Servlet2(柜台2)中查看参数(材料): null
柜台1是否有章:柜台1的章
Servlet2 处理自己的业务

  • 发现输入的前两句为null,因为我们在转入/servlet1的时候,没有传入参数
  • 若输入http://localhost:8080/_servlet02/servlet1?username=wzg168来访问,则Server打印 :
在Servlet1(柜台1)中查看参数(材料): wzg168
在Servlet2(柜台2)中查看参数(材料): wzg168
柜台1是否有章:柜台1的章
Servlet2 处理自己的业务

  • 第三个特点体现在上述代码中key1的传递

  • web-inf是受服务器保护的,客户端不能直接访问,但可以通过服务器中的资源进行间接访问

  • 比如如果我们把form.html放到web-inf下

  • 这样的话,访问/servlet1也显示form.html的表单的内容 :

base标签的作用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- base标签设置页面相对路径工作时参照的地址 -->
    <base href="http://localhost:8080/_servlet02/a/b/c.html">
    <!-- 可以省略为“http://localhost:8080/_servlet02/a/b/“,但斜杠不能去掉,因为斜杠说明b是一个目录,而不是一个资源路径 -->
</head>
<body>
  这是a下的b下的c.html页面 <br>
  <a href="../../index.html">跳回首页</a>
  <!-- http://localhost:8080/_servlet02/a/b/c.html../../index.html -->
  <!-- http://localhost:8080/_servlet02/index.html -->
</body>
</html>

回顾javaweb中的路径

斜杠在web中的不同意义

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
  这是Web下的index.html <br>
  <a href="a/b/c.html">a/b/c.html</a> <br>
  <a href="http://localhost:8080/_servlet02/forwardC">请求转发:a/b/c.html</a>
  <a href="/">斜杠</a>
</body>
</html>
  • 点击后跳转至 http://localhost:8080/

HttpServletResponse类的介绍

两个响应流的介绍

package com.atguigu.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class ResponseIOServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getOutputStream();
        resp.getWriter();
    }
}

给客户端回传字符串数据

package com.atguigu.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class ResponseIOServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // 要求 :往客户端回传 字符串 数据
        PrintWriter writer = resp.getWriter();
        writer.write("response's content!!!");
    }
}

解决响应的中文乱码

public class ResponseIOServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // 要求 :往客户端回传 字符串 数据
        PrintWriter writer = resp.getWriter();
        writer.write("即将出现中文乱码");
    }
}

public class ResponseIOServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        System.out.println(resp.getCharacterEncoding());
    }
}
  • 访问页面后,Server输出 ISO-8859-1
  • 说明,默认是ISO-8859-1,这个字符集是不支持中文的
  • 因此,我们要设置支持中文的字符集
public class ResponseIOServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // 设置 服务器 字符集为UTF-8
        resp.setCharacterEncoding("UTF-8");

        // 通过响应头,设置 浏览器 也使用UTF-8字符集(一般是GBK
        resp.setHeader("Content-Type", "text/html; charset=UTF-8");

        
        PrintWriter writer = resp.getWriter();
        writer.write("这不是中文乱码");
    }
}

解决响应中文乱码问题方案二

public class ResponseIOServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // 它会同时设置服务器和客户端都使用UTF-8字符集,还设置了响应头
        // 此方法一定要在获取流对象(PrintWriter writer = resp.getWriter();)之前使用才有效
        resp.setContentType("text/html; charset=UTF-8");

        System.out.println(resp.getCharacterEncoding());    // output:"UTF-8"
    }
}

请求重定向



public class Response1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        System.out.println("曾到此一游 Response1");

        // 设置响应状态码302,表示重定向(已搬迁)
        resp.setStatus(302);

        // 设置响应头,说明 新的地址在哪里
        resp.setHeader("Location", "http://localhost:8080/_servlet02/response2");
    }
}
public class Response2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        resp.getWriter().write("response2's result!!!");
    }
}
  • 然后访问http://localhost:8080/_servlet02/response1,会自动跳转至http://localhost:8080/_servlet02/response2

  • 关于第三个特点的解释 :
    如果在Response1中保存一些数据,比如req.setAttribute("key1", "value1"); ,然后在Response2中System.out,println(req.getAttribute("key1"));会得到null
    原因 :tomcat每次收到请求,就会把请求到的数据解析好,每次请求都会封装
  • 关于第四个特点 :



    原因 :
    第二次请求还是客户端给服务器发的,而WEB-INF目录是受保护的,浏览器无法直接访问,第二次请求还是浏览器发过来的,还是进不来
  • 第五个特点 :


请求重定向第二种实现方案

public class Response1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        resp.sendRedirect("http://localhost:8080/_servlet02/response2");
    }
}

更多推荐

尚硅谷最新版JavaWeb全套教程,java web零基础入门完整版(一)