java大数据开发训练营--Java Web 后端技术基础(上)

题记:

文章内容输出来源:拉勾教育大数据开发高薪训练营
本篇文章是java学习课程中的一部分笔记。

本博文主要是记录一些基础的知识点,通过实操更容易理解

这章主要讲的是JAVA Web后端基础

一 Web知识概述

1 软件架构

网络中有很多的计算机,它们直接的信息交流,我们称之为:交互

在互联网交互的过程的有两个非常典型的交互方式——B/S 交互模型(架构)和 C/S 交互模型 (架构)

C/S架构

Client/Server 客户端/服务器

访问服务器资源必须安装客户端软件

例如: QQ,绝地求生,LOL

B/S架构

Browser/Server 浏览器/服务器

访问服务器资源不需要专门安装客户端软件,而是直接通过浏览器访问服务器资源.

例如: 天猫、京东、知乎网站

2 资源的分类

资源:计算机中数据文件

静态资源

对于同一个页面,不同用户看到的内容是一样的。

例如:体育新闻、网站门户等,常见后缀: *.html*.js*.css

动态资源

用对于同一个页面,不同用户看到的内容可能不一样。

例如:购物车、我的订单等,常见后缀: *.jsp*.aspx*.php

3 URL 请求路径
        URL Uniform Resource Locator) ,统一资源定位符是对互联网上资源位置的一种表示,互联网上 的每个文件都有一个唯一的 URL

完整格式如下

协议://域名:端口号/资源位置?参数=

* 协议,httphttpsftp

* 域名,域名或IP地址,都可以访问WEB资源

* 端口号,程序必须使用端口号,才可以让另一个计算机访问。http协议的默认端:80

* 资源位置,用于描述WEB资源在服务器上的位置。

* 参数=值,浏览器和服务器交互传递的数据

常见的Web服务器

* Tomcat: Apache组织开源免费的web服务器,支持JavaEE规范(Servlet/Jsp.

* Jetty:Apache组织开源免费的小型web服务器,支持JavaEE规范.

* JBoss: RedHat红帽公司的开源免费的web服务器,支持JavaEE规范.

* Glass Fish:Sun公司开源免费的web服务器,支持JavaEE规范.

---------------------------------------------------------------------

* WebLogic: Oracle公司收费的web服务器,支持JavaEE规范.

* WebSphere:IBM公司收费的web服务器,支持JavaEE规范

JavaEE规范

Java 中所有的服务器厂商都要实现一组 Oracle 公司规定的接口,这些接口是称为 JavaEE规范。不同厂商的 JavaWeb 服务器都实现了这些接口,在 JavaEE 中一共有 13 种规范。实现的规范越多,功能越强。
 
 

Tomcat服务器【重点】

tomcat安装配置https://blog.csdn.net/qq_40881680/article/details/83582484

 1.目录说明

2.发布项目三种方式 

webapps 部署(最简单)

直接放置在 webapps 目录下

server.xml部署(了解)

tomcat/conf/server.xml中找到<Host>标签,添加<Context>标签

缺点
1. 配置文件修改完毕后,需要重启后生效 ...
2.server.xml tomcat 的核心配置文件,如果稍有不慎操作失误,整个 tomcat 启动失败
3. 这种方案作为了解即可 
③ 独立 xml 部署 ( 开发时使用 )

tomcat/conf/Catalina/localhost 目录下创建一个xml文件,添加标签

 

Intellij Idea 2017创建web项目及tomcat部署实战 (新建项目的时候选用javaEE)

经验值分享

HTTP协议  

1 Http 简介
什么是 Http 协议

HTTP协议:超文本传输协议(HTTPHyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议。用于定义WEB浏览器与WEB服务器之间交换数据的过程。

传输协议:在客户端和服务器端通信时,规范了传输数据的格式

必须先有请求,才会有响应

HTTP协议的作用

HTTP协议是学习JavaWEB开发的基石,不深入了解HTTP协议,就不能说掌握了WEB开发,更无法管理和维护一些复杂的WEB站点。

HTTP协议的特点

基于请求/响应模型的协议。

请求和响应必须成对;

先有请求后有响应。

简单快捷

因为发送请求的时候只需要发送请求方式和请求路径即可

HTTP协议默认的端口:80

例如: http://www.lagou.com:80

无状态协议

多次请求之间相互独立,不能交互数据

Http 协议的版本

HTTP/1.0,发送请求,创建一次连接,获得一个web资源,连接断开。

HTTP/1.1,发送请求,创建一次连接,获得多个web资源,连接断开。

HTTP 协议有两种报文格式:

请求报文:由客户端向服务器端发出的报文。

响应报文:从服务端到客户端的报文。

2 Http 协议详解
2.1 Http 请求报文详解

HTTP请求报文:由客户端向服务器端发出的报文。

HTTP请求报文格式:包含请求行、请求头、空行、请求体 四个部分

请求行
请求行格式:请求方式 资源路径 协议 / 版本
例如: POST /web01/login.html HTTP/1.1
请求行必须在 HTTP 请求格式的第一行。
请求方式:协议规定 7 种,常用两种: GET POST
GET 请求:

将请求参数追加在URL后面,不安全。例如:login.html?username=tom&password=1234

URL长度限制GET请求方式的数据大小。

没有请求体

POST 请求

请求参数显示请求体处,较安全。

请求数据大小没有限制。

只有表单设置为method=”post”才是post请求.其他的都是get请求。

常见GET请求:地址栏直接访问、<a href=””><img src=””>

请求头
请求头 : 描述了客户端向服务器发送请求时使用的 http协议类型,所使用的编码,以及发送内容的长度, referer ,等等。
请求头也是用的键值对 key
常见请求
描述
Referer浏览器通知服务器,当前请求来自何处。如果是直接访问,则不会有这个头。常用于:防盗链
Cookie与会话有关技术,用于存放浏览器缓存的cookie信息。
User-Agent浏览器通知服务器,客户端浏览器与操作系统相关信息
请求体
Http 请求报文演示
通常情况下,只有 post 请求方式才会使用到请求体,请求体中都是用户表单提交的数据,每一项数据都使用键
值对 key=value ,多组值使用 & 相连。
例如; username=tom&password=1234
创建页面,编写 “login.html” ,并提供表单,分别设置表单的提交方式为: get post。将表单提交位置设置成 # ,表示提交到当前表单。
<form action="#" method="post">
用户名:<input type="text" name="username" value=""/> <br/>
密 码:<input type="text" name="password" value=""/> <br/>
<input type="submit" />
</form>

观看下图,我们采用GET请求方式、POST请求方式的抓包结果:(Chrome浏览器)

GET 请求抓包数据:

POST 请求抓包数据:
2.2 Http 响应报文详解
响应报文:从服务端到客户端的报文。
HTTP 响应报文格式:响应行、响应头、空行、响应体 四个部分

响应行
例如: HTTP/1.1 200 OK
格式:协议 / 版本 状态码 状态码描述
状态码:服务器与浏览器用于确定状态的固定数字号码
200 :请求成功。
302 :请求重定向。
304 :请求资源没有改变,访问本地缓存。
404 :请求资源不存在。通常是用户路径编写错误,也可能是服务器资源已删除。
500 :服务器内部错误。通常程序抛异常
响应头

响应头: 用来描述服务器回给客户端浏览器的content的一些描述,例如: 我是什么服务器,我返回的是啥编码,我返回的内容有多长等

响应头也是用的键值对 key:value

常见响应头
描述
Location指定响应的路径,需要与状态码302配合使用,完成跳转。
Content-Disposition文件下载的时候使用。通过浏览器以下载方式解析正文
Set-Cookie与会话相关技术。服务器向浏览器写入cookie
Refresh定时刷新

响应体

响应体,就是服务器发送给浏览器的正文。
Http 响应报文演示
如下图,我们提供的响应的抓包结果( Chrome 浏览器)

Servlet

Servlet 概述

servlet= server+applet :运行在服务器端的java程序。

Servlet是一个接口,一个类要想通过浏览器被访问到,那么这个类就必须直接或间接的实现Servlet接口

作用

接收请求,处理逻辑,响应结果

二 servlet 实现步骤

创建 web 项目
编写普通 java 类,实现 servlet 接口
web.xml 配置 url-pattern
部署 web 项目
启动测试

 servlet执行原理

Servlet生命周期

 

// 1. servlet 对象创建时,调用此方法
public void init ( ServletConfig servletConfig );
// 2. 用户访问 servlet 时,调用此方法
public void service ( ServletRequest servletRequest , ServletResponse
servletResponse );
// 3. servlet 对象销毁时,调用此方法
public void destroy ();

 

 * 创建

1 )默认情况下

用户第一次访问时,创建servlet,执行init方法

2 )修改创建时机

<load-on-startup></load-onstartup>

正数:4-N 【服务器启动时,创建】

补充:Tomcatweb.xml里有1,3 所以推荐4-n

负数(默认值):-1 【用户第一次访问时,创建】

* 运行(提供服务)

用户每次访问时,都执行service方法

* 销毁

服务器正常关闭时,销毁servlet,执行destroy方法

```
笔试题:请描述下 servlet 的生命周期:

答案:servlet是一个单实例多线程的,默认情况下,第一次请求来的时候,才会对该servlet进行实例化,并执行初始化init方法,随后再执行service方法完成业务处理,当每一次请求发送过来,都会从新开启一个线程,来执行servlet中的service方法,当服务器关闭或者servlet被移除的时候,会执行destory方法

 

Servlet 体系结构

HttpServlet

 测试页面

<form method="post" action="http://127.0.0.1:8080/javaServer/servletTest">
    <input type="submit" value="提交">
</form>

web.xml

<servlet>
        <servlet-name>servletTest</servlet-name>
        <servlet-class>com.bigload.server.servletTest</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>servletTest</servlet-name>
        <url-pattern>/servletTest</url-pattern>
    </servlet-mapping>

servletTest.java

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 servletTest extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("doget....");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("dopost....");
    }
}
url-pattern 的配置方式

5.1 Servlet映射多个url

5.2 url映射模式

配置 url地址取值可以是:

1. 精确匹配 ( 掌握 )
/servletDemo3 localhost:8080/ 项目路径 /servletDemo3
2. 目录匹配
/aa/*
3. 后缀匹配
*.xxx 例如: *.do
    <!--
只要浏览器符合目录匹配规则,都可以访问到这个servlet:
/aa/abc
/aa/asadfasdf
-->
    <servlet>
        <servlet-name>ServletDemo4</servlet-name>
        <servlet-class>com.lagou.servlet.QuickServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>ServletDemo4</servlet-name>
        <url-pattern>/aa/*</url-pattern>
    </servlet-mapping>
    <!--
    只要浏览器符合后缀匹配规则,都可以访问到这个servlet
    aa.do
    bb.do
    xx.do
    -->
    <servlet>
        <servlet-name>ServletDemo5</servlet-name>
        <servlet-class>com.lagou.servlet.QuickServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>ServletDemo5</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>
Request 对象

6.1 request对象概述

用户通过浏览器访问服务器时,TomcatHTTP请求中所有的信息都封装在Request对象中

作用:开发人员可以通过request对象方法,来获取浏览器发送的所有信息.

6.2 获取请求行信息

* 例如:
GET /servlet_demo/requestDemo1 HTTP/1.1
* 相关API:
1. 获取请求方式 GET【掌握】
String getMethod()
2. 获取项目虚拟路径(项目名)/servlet_demo【掌握】
String getContextPath()
3. 获取URL http://localhost:8080/servlet_demo/requestDemo1
统一资源定位符(确定某一个地址) 中华人民共和国
StringBuffer getRequestURL()
4. 获取协议和版本号 HTTP/1.1
String getProtocol()
5. 获取客户端ip
String getRemoteAddr()

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        // System.out.println(req);
        System.out.println("请求方式:" + req.getMethod());
        System.out.println("虚拟路径:" + req.getContextPath());
        System.out.println("URL:" + req.getRequestURL());
        System.out.println("协议和版本:" + req.getProtocol());
        System.out.println("客户端ip:" + req.getRemoteAddr());
    }

6.3 获取请求头信息

* 例如:
Host: 127.0.0.1:8080
* 相关 API
1. 获取知道请求头名称对应的值,注:名称不区分大小写
String getHeader(String name)
2. 获取所有请求头的名称
Enumeration<String> getHeaderNames()
注:是 Iterator 前身
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        // 获取所有的请求头名称
        Enumeration<String> enumeration = req.getHeaderNames();
        // 遍历
        while(enumeration.hasMoreElements()){
            // 取出元素名(请求头名称)
            String name = enumeration.nextElement();
            // 根据名称获取值
            String value = req.getHeader(name);
            System.out.println(name +" : "+ value);
        }
    }

6.4 获取请求体信息(请求参数)【重点....

不论get还是post请求方式,都可以使用下列方法来获取请求参数

* 参数

username=jack&password=123&hobby=drink&hobby=perm

* API
1. 获取指定参数名的值 username=jack

String getParameter(String name)

2. 获取指定参数名的值数组 hobby=drink&hobby=perm

String[] getParameterValues(String name)

3. 获取所有参数名和对应值数组,参数名 name key ),值数组 value ,封装 map 集合

Map<String,String[]> getParameterMap()

* 中文乱码【重点】
get :在 tomcat8 及以上版本,内部 URL 编码( UTF-8
post :编码解码不一致,造成乱码现象

客户端(浏览器)编码:UTF-8

服务器默认 解码:ISO-8859-1 拉丁文

指定解码:void setCharacterEncoding(String env)

注:这哥们必须在方法内,行首

html 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>servletTest测试页面</title>
</head>
<body>
<form method="post" action="http://127.0.0.1:8080/javaServer/servletTest">
    <label>
        <span>姓名</span>
        <input type="text" name="name" value="姓名"/>
    </label>
    <label>
        <span>年龄</span>
        <input type="text" name="age" value="年龄">
    </label>
    <label>
        <span>爱好</span>
        <input type="checkbox" name="hobby" value="抽烟">抽烟
        <input type="checkbox" name="hobby" value="喝酒">喝酒
        <input type="checkbox" name="hobby" value="烫头">烫头
    </label>
    <input type="submit" value="提交">
</form>
</body>
</html>

java

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //根据游览器编码设置
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("GBK");
        resp.getWriter().write("dopost....");
        PrintWriter writer = resp.getWriter();
        writer.write("doget....");
        writer.write("测试一个中文");
        Map<String, String[]> parameterMap = req.getParameterMap();
        parameterMap.forEach((k,v)->{
            System.out.println("name:"+k+",value:"+Arrays.toString(v));
        });

    }

6.5 请求转发

一种在服务器内部的资源跳转方式

 

* API
1. 通过 reqeust 对象,获得转发器对象

RequestDispatcher getRequestDispatcher(String path) //要跳转到的路径

2. 通过转发器对象,实现转发功能

void forward(ServletRequest request, ServletResponse response)

* 请求转发特点

浏览器:发了一次请求

地址栏:没有发生改变

只能转发到服务器内部资源....

* 链式编程
request.getRequestDispatcher("/bServlet").forward(reqeust,response)

6.6 域对象(共享数据)

域对象:一个有作用范围的对象,可以在范围内共享数据

request域:代表一次请求的范围,一般用于一次请求中转发的多个资源中共享数据

 

* API
1. 设置数据

void setAttribute(String name, Object o)

2. 获取数据

Object getAttribute(String name)

3. 删除数据

void removeAttribute(String name)

* 生命周期

1. 何时创建?

用户发送请求时,创建request

2. 何时销毁

服务器返回响应是,销毁request

3. 作用范围?

一次请求,包含多次转发

@WebServlet("/aServlet")
public class AServlet extends HttpServlet {


    protected void doPost(HttpServletRequest request,
        HttpServletResponse response) throws ServletException, IOException {
        System.out.println("aServlet处理功能上....");
        // 转发到BServlet
        /* // 1.获得转发器对象 path = @WebServlet("/bServlet")
        RequestDispatcher requestDispatcher =
        request.getRequestDispatcher("/bServlet");
        // 2.实现转发功能
        requestDispatcher.forward(request, response);*/

        // 存一个数据
        request.setAttribute("hanbao", "香辣鸡腿堡");
        // 链式编程横
        request.getRequestDispatcher("bServlet").forward(request, response);
    }
}
    @WebServlet("/bServlet")
    public class BServlet extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse
                response) throws ServletException, IOException {
            System.out.println("bServlet处理功能下....");
            // 获取数据
            String hanbao = (String) request.getAttribute("hanbao");
            System.out.println("hanbao:" + hanbao);
        }
    }

Response对象  

7.1 概述

response对象表示web服务器给浏览器返回的响应信息

作用:开发人员可以使用response对象的方法,设置要返回给浏览器的响应信息

Response体系结构

7.2 设置Http响应消息

响应行

* 格式 协议/版本号 状态码

* 例如 HTTP/1.1 200

* API

1. 设置状态码

void setStatus(int sc) 200 302 304 404 500

响应头

* 格式 响应头名称:响应头的值
* 例如 Location:http://www.lagou.com
* API

1. 设置指定头名称和对应的值

void setHeader(String name, String value)

响应体【重点】

* API (输出流对象)

1. 字符输出流

PrintWriter getWriter()

2. 字节输出流

ServletOutputStream getOutputStream()

注意:在同一个 servlet 中,二种类型的输出流不能同时存在,互斥

 

7.3 响应重定向

需求:用户访问AServlet后,服务器告诉浏览器重定向到BServlet

步骤分析

 * 方式一

// 1. 设置状态码
response.setStatus(302);
// 2. 设置响应头 Location
response.setHeader("Location"," 重定向网络地址 ");
 
* 方式二
// 1.response 这哥们封装专门处理重定向的方法
response.sendRedirect(" 重定向网络地址 ");
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//       req.getRequestDispatcher("/servletTest2").forward(req,resp);
        resp.sendRedirect("/javaServer/servletTest2");
    }

重定向特点

1. 地址栏会发生改变

2. 重定向是二次请求

3. 重定向是客户端(浏览器)行为,可以跳转到服务器外部资源...

4. 不能使用request域共享数据

请求转发与重定向的区别

1. 哪个对象
  • 转发(request对象的方法)

request.getRequestDispatcher("/bServlet").forward(request,response);

  • 重定向(response对象的方法)

response.sendRedirect("/day10_response/bServlet");

2. 几次请求
  • 转发

地址栏: 没有改变

浏览器: 发了一次请求

服务器: 只有一对请求和响应对象

发生的位置: 服务器

  • 重定向

地址栏: 发生了改变

浏览器: 发了两次请求

服务器: 有两对请求和响应对象

发生的位置: 浏览器

3. 小结
  • 写法

转发("/servlet资源路径") 服务器内部行为

重定向 ("/虚拟路径(项目名)/servlet资源路径") 浏览器外部行为

  • 使用场景(重点掌握)

如果需要传递数据(request域),使用转发

如果不需要传递数据(request域),使用重定向

7.4 响应中文

需求

向页面输出中文数据没有乱码

 步骤分析

1. 通过 response 获取字符输出流

PrintWriter pw = response.getWriter();

2. 通过字符输出输出文本

pw.write("中文....");

解决中文乱码

1. 指定服务器响应编码方式

response.setCharacterEncoding("GBK");

2. 统一浏览器和服务器编码

response.setContentType("text/html;charset=utf-8");

ServletContext

8.1 概述

web容器(tomcat)在启动时,它会为每个web项目承建一个对应的ServletContext对象

它代表:当前web项目

 

主要作用

1. 域对象(共享数据)

2. 获取资源在服务器的真实地址

3. 获取全局的配置参数

4. 获取文件MIME类型

获取 ServletContext 对象
1. 通过 request 对象获得

ServletContext sc = request.getServletContext();

2. 继承 HttpServlet 后,可以直接调用

ServletContext sc = this.getServletContext();

8.2 域对象(共享数据)

在当前项目范围内,共享数据(多个servlet都可以获取)

 

1. 存储数据
void setAttribute(String name,Object value)
2. 获取数据
Object getAttribute(String name)
3. 删除数据
void removeAttribute(String name)
    @WebServlet("/OneServlet")
    public class OneServlet extends HttpServlet {
        protected void doGet(HttpServletRequest request, HttpServletResponse
                response) throws ServletException, IOException {
            this.doPost(request, response);
        }
        protected void doPost(HttpServletRequest request, HttpServletResponse
                response) throws ServletException, IOException {
// 向servletContext域存数据....
            ServletContext sc1 = request.getServletContext();
            ServletContext sc2 = getServletContext();
            sc1.setAttribute("user", "jack");
            System.out.println("OneServlet存了数据。。。");
        }
    }
    @WebServlet("/TwoServlet")
    public class TwoServlet extends HttpServlet {
        protected void doGet(HttpServletRequest request, HttpServletResponse
                response) throws ServletException, IOException {
            this.doPost(request, response);
        }
        protected void doPost(HttpServletRequest request, HttpServletResponse
                response) throws ServletException, IOException {
// 从servletContext域获取数据
            String user = (String) request.getServletContext().getAttribute("user");
            System.out.println("TwoServlet获取数据:"+user);
        }
    }
 

生命周期

1. 何时创建?
项目加载时,创建
2. 何时销毁?
项目卸载时,销毁
3. 作用范围?
与项目共存亡( 多个servlet都可以操作它

 

8.3 获取资源在服务器的真实地址

可以实现web项目的移植性...动态获取文件真实路径

 

* API
String getRealPath(String path);
例:
String realPath = req.getServletContext().getRealPath("/js/vue.js");
String realPath1 = req.getServletContext().getRealPath("/WEB-INF/web.xml");

8.4 获取全局的配置参数

读取web.xml配置文件中标签信息,实现参数和代码的解耦(多个servlet都可以获取)

<?xml version="1.0" encoding="utf-8"?>

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">  
  <!--全局配置参数:所有的servlet都可以读取...-->  
  <context-param> 
    <param-name>encode</param-name>  
    <param-value>UTF-8</param-value> 
  </context-param> 
</web-app>
@WebServlet("/ContextPathServlet")
public class ContextPathServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse
            response) throws ServletException, IOException {
        this.doPost(request, response);
    }
    protected void doPost(HttpServletRequest request, HttpServletResponse
            response) throws ServletException, IOException {
// 获取全局参数
        String value = request.getServletContext().getInitParameter("encode");
        System.out.println("全局配置参数:"+value);
    }
}

 8.5 获取文件MIME类型

  • 在互联网通信过程中定义的一种文件数据类型格式
  • 格式: 大类型/小类型 例如: text/html image/jpeg

<a href="/day10_servletContext/MimeServlet?filename=luola.avi">获取文件的mime类型 </a><br>
@WebServlet("/MimeServlet")
public class MimeServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse
            response) throws ServletException, IOException {
        this.doPost(request, response);
    }
    protected void doPost(HttpServletRequest request, HttpServletResponse
            response) throws ServletException, IOException {
// 获取指定文件的mime类型
// 获取请求参数
        String filename = request.getParameter("filename");
// 获取文件的mime类型
        String mimeType = request.getServletContext().getMimeType(filename);
        response.getWriter().write(filename + "---" + mimeType);
    }
}

8.6 案例:统计网站的访问次数

需求

一般个人博客的首页,都会显示你是第几位访问此网站...

@WebServlet(value = "/CountServlet", loadOnStartup = 4) 
// 服务器启动时,创建此servlet对象
public class CountServlet extends HttpServlet {
    @Override
    public void init() throws ServletException {
        getServletContext().setAttribute("count", 0);
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse
            response) throws ServletException, IOException {
        this.doPost(request, response);
    }
    protected void doPost(HttpServletRequest request, HttpServletResponse
            response) throws ServletException, IOException {
// 设置response响应编码
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().write("<h1>拉勾网站</h1>");
// 用户每次访问,从域中取出,加1,再存进去
        ServletContext servletContext = request.getServletContext();
// 从域中取出
        Integer count = (Integer) servletContext.getAttribute("count");
// 加1
        count++;
// 再存进去servletContext.setAttribute("count", count);
        response.getWriter().write("<div>你是,第" + count + "位访问此网站...
                </div>");
    }
}

Cookie & Session

一 会话概述

1.1 什么是会话?

日常生活中:从拨通电话到挂断电话之间的一连串你问我答的过程就是一个会话。

B/S架构中:从浏览器第一次给服务器发送请求时,建立会话;直到有一方断开,会话结束。

一次会话:包含多次请求响应。

1.2 会话技术

问题:Http是一个无状态协议,同一个会话的连续两个请求相互独立,彼此并不了解

作用:用于==存储==浏览器与服务器在请求和响应过程中产生的==数据==

客户端会话技术:cookie

服务器端会话技术:session

 

Cookie 【重点】

2.1 概述

Cookie作用:在一次会话的多次请求之间共享数据,将数据保存到客户端(浏览器)

2.2 快速入门

1. 设置数据到 cookie

// 1.创建cookie对象,设置数据 *value只能存字符串

Cookie cookie = new Cookie(String name,String value);

// 2.通过response,响应(返回)cookie

response.addCookie(cookie);

2. cookie 中获取数据

// 1.通过request对象,接收cookie数组

Cookie[] cookies = request.getCookies();

// 2.遍历数组

if(cookies!=null){
    for (Cookie c : cookies) {
        String name = c.getName();
        String value = c.getValue();
        System.out.println(name + " : " + value);
    }
}

2.3 工作原理

基于HTTP协议:请求头cookie 和 响应头 set-cookie

2.4 Cookie细节

2.4.1 服务器发送多个Cookie

* 答案是可以的

// 1. 创建多个cookie对象

Cookie cookie1 = new Cookie("name","lucy");

Cookie cookie2 = new Cookie("age","18");

// 2. 通过response响应多个

response.addCookie(cookie1);

response.addCookie(cookie2);

 2.4.2 Cookie在浏览器保存时间?

* 默认情况下

浏览器关闭(会话结束),cookie销毁(内存)

* 设置 cookie 的存活时间

cookie.setMaxAge(int second); -- 单位是秒

正数:指定存活时间,持久化浏览器的磁盘中,到期后自动销毁

负数:默认浏览器关闭,cookie销毁

零:立即销毁(自杀)

2.4.3 Cookie是否可以存储中文?

 

* tomcat8 之前的版本,不支持中文

URLEncoder 编码

URLDecoder 解码

* tomcat8 以后的版本,支持中文 ...

Rfc6265Cookie规范,不允许使用 分号、空格等一些特殊符号...

    protected void doPost(HttpServletRequest request, HttpServletResponse
            response) throws ServletException, IOException {
        String product = "华为荣耀 30X,";
        product= URLEncoder.encode(product, "UTF-8");
        // 1.创建cookie对象
        Cookie cookie = new Cookie("product", product);
        //自杀cookie,清除cookie使用
        //cookie.setMaxAge(0);
        // 2.response响应cookie
        response.addCookie(cookie);
    }
    protected void doPost(HttpServletRequest request, HttpServletResponse
            response) throws ServletException, IOException {
        // 1.通过request对象,接收cookie数组
        Cookie[] cookies = request.getCookies();
        // 2.遍历数组
        if(cookies!=null){
            for (Cookie c : cookies) {
                String name = c.getName();
                String value = c.getValue();
        // 解码
                value = URLDecoder.decode(value, "UTF-8");
                System.out.println(name + " : " + value);
            }
        }
    }

2.5 Cookie特点

 1. cookie存储数据都在客户端(浏览器)

2. cookie的存储数据只能是字符串

3. cookie单个大小不能超过4KB

4. cookie存储的数据不太安全

Session【重点】

3.1 概述

session作用:在一次会话的多次请求之间共享数据,将数据保存到服务器端

Session基于Cookie技术实现

3.2 快速入门

HttpSession也是一个域对象

* API

1. 存储数据

void setAttribute(String name,Object value)

2. 获取数据

Object getAttribute(String name)

3. 删除数据

void removeAttribute(String name)

1. 将数据存储到session中
// 1.通过rquest对象,获取session对象
HttpSession session = request.getSession();
// 2.操作session的API,存储数据
session.setAttribute("username","哈哈,呵呵");
2. 从session中获取数据
// 1.通过rquest对象,获取session对象
HttpSession session = request.getSession();
// 2.操作session的API,获取数据
session.getAttribute("username");

 

 3.3 生命周期

* 何时创建

用户第一次调用request.getSession()方法时,创建

* 何时销毁

服务器非正常关闭

非活跃状态30分钟后

tomcat进行配置 /tocmat安装目录/conf/web.xml

session.invalidate(); 自杀

* 作用范围

一次会话中,多次请求之间

注意:每一个浏览器跟服务器都是独立的会话...

四 三大域对象总结

requestsessionServletContext

ServletContext域对象

* 何时创建
服务器正常启动,项目加载时,创建
* 何时销毁
服务器关闭或项目卸载时,销毁
* 作用范围
整个 web 项目(共享数据)

HttpSession域对象

* 何时创建
用户第一次调用 request.getSession() 方法时,创建
* 何时销毁
服务器非正常关闭
未活跃状态 30 分钟
自杀
* 作用范围
一次会话中,多次请求间(共享数据)

HttpServletRequest域对象

* 何时创建
用户发送请求时,创建
* 何时销毁
服务器做出响应后,销毁
* 作用范围
一次请求中,多次转发间(共享数据)

小结

能用小的不用大的: request<session<servletContext
常用的场景:

request:一次查询的结果(servlet转发jsp

session:存放当前会话的私有数据

用户登录状态

验证码

购物车

servletContext:若需要所有的servlet都能访问到,才使用这个域对象.

 Filter & Listener

web 的三大组件:
  • servlet(控制器)
  • filter(过滤器)
  • listener(监听器)  

Filter

应用场景

如:登录验证、统一编码处理、敏感字符过滤

二 快速入门

需求:编写filter对目标资源servlet进行拦截

① 编写java类,实现filter接口

public class QuickFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    /**
    * 此方法拦截用户请求
    * @param servletRequest :请求对象
    * @param servletResponse :响应对象
    * @param filterChain :过滤器链(是否放行)
    */
    @Override
    public void doFilter(ServletRequest servletRequest,
        ServletResponse servletResponse, FilterChain filterChain)
        throws IOException, ServletException {
        System.out.println("QuickFilter拦截了请求...");
        // 放行
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {
    }
}
 

② 配置web.xml

<?xml version="1.0" encoding="utf-8"?>

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">  
  <!--快速入门-->  
  <!--注册filter-->  
  <filter> 
    <filter-name>QuickFilter</filter-name>  
    <filter-class>com.lagou.a_quick.QuickFilter</filter-class> 
  </filter>  
  <!--配置filter拦截路径-->  
  <filter-mapping> 
    <filter-name>QuickFilter</filter-name>  
    <url-pattern>/*</url-pattern> 
  </filter-mapping> 
</web-app>

三 生命周期

// 初始化方法
public void init ( FilterConfig config );
// 执行拦截方法
public void doFilter ( ServletRequest request , ServletResponse
response , FilterChain chain );
// 销毁方法
public void destroy ();
 
* 创建
服务器启动项目加载,创建 filter 对象,执行 init 方法(只执行一次)
* 运行(过滤拦截)
用户访问被拦截目标资源时,执行 doFilter 方法
* 销毁
服务器关闭项目卸载时,销毁 filter 对象,执行 destroy 方法(只执行一次)
* 补充:
过滤器一定是优先于 servlet 创建的

四 拦截路径

在开发时,我们可以指定过滤器的拦截路径来定义拦截目标资源的范围

* 精准匹配
用户访问指定目标资源( /targetServlet )时,过滤器进行拦截
* 目录匹配
用户访问指定目录下( /user/* )所有资源时,过滤器进行拦截
* 后缀匹配
用户访问指定后缀名( *.html )的资源时,过滤器进行拦截
* 匹配所有
用户访问该网站所有资源( /* )时,过滤器进行拦截

 过滤器链

在一次请求中,若我们请求匹配到了多个filter,通过请求就相当于把这些filter串起来了,形成了过滤器链

* 需求

用户访问目标资源 /targetServlet时,经过 FilterA FilterB

* 过滤器链执行顺序 (先进后出)

1.用户发送请求

2.FilterA拦截,放行

3.FilterB拦截,放行

4.执行目标资源 show.jsp

5.FilterB增强响应

6.FilterA增强响应

7.封装响应消息格式,返回到浏览器

* 过滤器链中执行的先后问题 ....

配置文件

谁先声明,谁先执行

<filter-mapping>

六 综合案例

需求
用户访问某论坛网站,可以写评论的方式对比赛内容进行留言
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>bbs</title></head>
<body><h3>LPL季后赛观看留言板</h3>
<hr>
<form action="${pageContext.request.contextPath}/WordsServlet" method="post">
    <textarea name="content" id="" cols="30"rows="10"></textarea> 
    <input type="submit" value="请留言">
</form>
</body>
</html> 
public class WordsServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse
            response) throws ServletException, IOException {
        this.doPost(request, response);
    }
    protected void doPost(HttpServletRequest request, HttpServletResponse
            response) throws ServletException, IOException {
        // 1.接收请求参数 content
        String content = request.getParameter("content");
        // 2.将结果响应到 浏览器
        response.getWriter().write(content);
    }
}

统一网站编码

需求

tomcat8.5 版本中已经将 get 请求的中文乱码解决了 , 但是 post 请求还存在中文乱码
浏览器发出的任何请求,通过过滤器统一处理中文乱码
 
public class codeFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) servletRequest;
        if(req.getMethod().equalsIgnoreCase("post")){
            servletRequest.setCharacterEncoding("UTF-8");
        }
        servletResponse.setContentType("text/html;charset=utf-8");
        filterChain.doFilter(servletRequest,servletResponse);

    }
}

Listener【了解】

1.1 概述

生活中的监听器

我们很多商场有摄像头,监听着客户的一举一动。如果客户有违法行为,商场可以采取相应的措施。

javaweb中的监听器

在我们的java程序中,有时也需要监视某些事情,一旦被监听的对象发生相应的变化,我们应该采取相应的操作。

监听web三大域对象:HttpServletRequestHttpSessionServletContext 通过监听器监听三大域对象它们的创建和销毁

场景

历史访问次数、统计在线人数、系统启动时初始化配置信息

1.2 快速入门

监听器在web开发中使用的比较少,见的机会就更少了,所以我们就使用ServletContextListenner来带领大家学习下监听器,因为这个监听器是监听器中使用率最高的一个,且监听器的使用方式都差不多。

我们使用这个监听器可以在项目启动和销毁的时候做一些事情,例如,在项目启动的时候加载配置文件。

ServletContextListener接口的API介绍--重要

void contextDestroyed ( ServletContextEvent sce ) 监听 servletcontext 销毁
void contextInitialized ( ServletContextEvent sce ) 监听 servletcontext 创建

使用步骤

1.创建一个类实现ServletContextListenner接口

2.实现ServletContextListennercontextInitializedcontextDestroyed方法。

3.给这个类在xml中配置

public class MyServletContextListenner1 implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        System.out.println("服务器启动,servletContext被创建了");
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        System.out.println("服务器停止,servletContext被销毁了");
    }
}
<listener>
    <listener-class>com.itheima.listenner.MyServletContextListenner1</listener- class>
</listener>
同理:使用如下接口以相同的方式也可以监听到 session 对象和 request 对象的创建和销毁

HttpSessionListener:监听Httpsession域的创建与销毁的监听器

ServletRequestListener:监听ServletRequest域的创建与销毁的监听器

MVC模式&三层架构【思想】

MVC模式

1.1 JSP发展史

早期只有servlet,只能使用response输出html标签,非常麻烦。

后来有了JSP,简化了servlet开发;如果过度使用JSP,在JSP页面中写了大量的java代码和html标签,造成难于维护,难于分工协作的场景。

再后来为了弥补过度使用jsp的问题,我们使用servlet+jsp这套组合拳,利于分工协作

 1.2 MVC介绍

MVC设计模式: Model-View-Controller简写。

MVC是软件工程中的一种软件架构模式,它是一种分离业务逻辑显示界面的设计方法。

简单来说:前辈们总结的一套设计经验,适合在各种软件开发领域,目的:高内聚,低耦合

* M model (模型) JavaBean 1. 处理业务逻辑、 2. 封装实体)
* V view (视图) Jsp (展示数据)
* C controller (控制器) Servlet 1. 接收请求、 2. 调用模型、 3. 转发视图) MVC: 笔试题
* 优缺点

优点

降低耦合性,方便维护和拓展,利于分工协作

缺点

使得项目架构变得复杂,对开发人员要求高

二 三层架构( MVC 升级版)

改造了MVC以后的架构,就称为三层架构

2.1 概念

通常意义上的三层架构就是将整个业务应用划分为:表示(现)层、业务逻辑层、数据访问层。

区分层次的目的 为了高内聚低耦合的思想

表示(现)层:又称为 web 层,与浏览器进行数据交互(控制器和视图)
业务逻辑层:又称为 service 层,处理业务数据( if 判断, for 循环)
数据访问(持久)层:又称为 dao 层,与数据库进行交互的(每一条(行)记录与 javaBean实体对应)

包目录结构

* com.lagou 基本包(公司域名倒写)

* com.lagou.dao 持久层

* com.lagou.service 业务层

* com.lagou.web 表示层

* com.lagou.domain 实体(JavaBean

* com.lagou.util 工具

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值