JavaWeb学习记录

1.web相关概念

1.1 软件的基本架构

C/S(Client-Server),比如我们手机上的app QQ 微信

特点:必须下载特定的客户端程序。服务端升级之后,客户端也需要随着升级。

B/S(Broswer-Server),比如京东网站,腾讯qq官方网站

特点:只需要安装浏览器就可以访问。如果服务器端升级了,浏览器端不需要随之升级。

JavaWeb开发,开发的软件是基于B/S的软件架构。

1.2 资源

资源就是用户想要获取的资源。资源分为两种,一种是静态资源,一种是动态资源

静态资源是不会经常发生变化的资源,比如HTML CSS JS 图片。

动态资源是会发生变化的资源,比如servlet jsp。如果我们想要获取动态资源,这些动态资源必须通过服务器部署之后才能获取。

1.3 tomcat

服务器的种类有很多,有文件服务器、邮件服务器、web服务器、数据库服务器。我们的动态资源是部署在web服务器上的,web服务器接收到http请求之后把请求交给Servlet来处理,调⽤业务类实现动态资源获取。

web服务器有很多,比如tomcat、jetty、weblogic,jboss。

1.3.1 tomcat是什么

Tomcat是一个免费的开放源代码的Web应用服务器,是Apache软件基金会项目中的一个核心项目,由Apache ,Sun共同开发而成,深受Java爱好者的喜爱,是一款比较流行的web应用服务器。
tomcat

1.3.2 tomcat的下载和安装

官网:https://tomcat.apache.org/

安装:下载绿色版tomcat后,解压到本地磁盘即完成安装

1.3.3 tomcat结构目录

tomcat目录结构

①bin:启动和关闭tomcat的bat文件。

  • startup.bat , shutdown.bat 用于在windows下启动和停止脚本;
  • startup.sh, shutdown.sh 用于在linux下启动和停止脚本;

②conf:配置文件。

  • logging.properties Tomcat 的日志配置文件, 可以通过该文件修改Tomcat 的日志级别、日志字符编码及日志路径等
  • server.xml该文件用于配置server相关的信息,比如tomcat启动的端口号,配置主机(Host)。

③lib:该目录放置运行tomcat运行需要的jar包。

④logs:存放日志,当我们需要查看日志的时候,可以查询信息。

⑤webapps:放置我们的web应用。

⑥work工作目录:该目录用于存放jsp被访问后生成对应的server文件和.class文件。

1.3.4 tomcat的启动和关闭

启动:双击 bin/startup.bat 文件 ;
停止:双击 bin/shutdown.bat 文件 ;
访问:http://localhost:8080

1.4 war包

  war 包是 Sun 提出的一种 web 应用程序格式,它与 jar 类似是一个特殊的压缩包。
  一个 war 文件包含 Servlet、HTML 页面、Java 类、图像文件及其他资源,简单的来说,jar 只是类的归档文件,而 war 包是一个完整的 web 应用程序
  我们war文件直接放在 Tomcat 的 webapps 文件夹下就可以启动该项目了。

2.Http协议

什么是Http协议: 浏览器和服务器之间进行数据传输需要遵循的格式规范。

2.1 请求行

主要包含:请求方式、请求URL、状态码、HTTP协议及版本
请求行

2.2 请求头

请求头

  • Accept:表示浏览器能接收的资源类型,如text/*,image/或者/*表示所有。
  • Accept-Encoding:告诉服务器当前浏览器支持的内容编码。
  • Accept-Language:告诉服务器当前浏览器能接受和处理的语言。
  • Connection:keep-alive,告诉服务器在完成本次请求的响应后,保持该TCP连接不释放,等待本次连接的后续请求。这样可以减少打开关闭TCP连接的次数提升处理性能。另外的可选项是Close,表明直接响应接受完成后直接将其关闭。
  • Content-Length:用于描述HTTP消息实体的传输长度。
  • Content-Type:内容类型,用于定义网络文件的类型和网页的编码,决定浏览器将以什么形式、什么编码读取这个文件。
  • Cookie:表示服务器端为本次访问分配了一个Session ID,每次发送请求时都会主动将该Session ID通过Cookie字段又发送回服务器,用于验证身份和保持状态。
  • Host:描述请求将被发送的目的地,在任何类型的请求中都会包含此信息。
  • Origin:用来说明请求从哪里发起的。
  • Referer:指定发起该请求的源地址。
  • TE:采用何种传输编码。
  • User-Agent:是一种向访问网站提供你所使用的浏览器类型及版本、操作系统及版本、浏览器内核等信息的标识。
  • X-Requested-With:用来判断请求是Ajax请求还是其他请求。

2.3 请求体

  • POST请求通过请求体来传递数据,通过param1=value1&param2=value2的键值对形式编码。
  • GET请求通过URL地址参数来传递数据,也就是我们平时看到的URL地址里面“?”后面的所包含的键值对。

2.4 响应头

响应头

服务器响应的第一行总是版本号+空格+数字+空格+文本,数字表示响应代码,其中2xx表示成功,3xx表示重定向,4xx表示客户端引发的错误,5xx表示服务器端引发的错误。数字是给程序识别,文本则是给开发者调试使用的。常见的响应代码有:

  • 响应代码:

    • 200 OK:表示成功;
    • 301 Moved Permanently:表示该URL已经永久重定向;
    • 302 Found:表示该URL需要临时重定向;
    • 304 Not Modified:表示该资源没有修改,客户端可以使用本地缓存的版本;
    • 400 Bad Request:表示客户端发送了一个错误的请求,例如参数无效;
    • 401 Unauthorized:表示客户端因为身份未验证而不允许访问该URL;
    • 403 Forbidden:表示服务器因为权限问题拒绝了客户端的请求;
    • 404 Not Found:表示客户端请求了一个不存在的资源;
    • 405 :请求方式不对,eg:get请求方式去访问doPost()
    • 500 Internal Server Error:表示服务器处理时内部出错,例如因为无法连接数据库;
    • 503 Service Unavailable:表示服务器此刻暂时无法处理请求。
  • content-encoding:响应的编码格式

  • content-type:响应内容的类型

  • date:响应的时间。此处使用的是GMT标准时间

  • server:处理请求的源头服务器所用到的软件相关信息

  • strict-transport-security:

HTTP Strict Transport Security(通常简称为HSTS)是一个安全功能,它告诉浏览器只能通过HTTPS访问当前资源, 禁止HTTP方式。

2.5 响应体

响应体就是服务器返回的HTML页面或者json数据

3.Servlet入门

3.1 Servlet介绍

3.1.1 什么是Servlet?

Servlet是Server Applet的简称,是用Java编写的是运行在 Web 服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。使用 Servlet,可以收集来自网页表单的用户输入,呈现来自数据库或者其他源的记录,还可以动态创建网页。

3.1.2 Servlet的使用方法

Servlet技术的核心是Servlet接口,定义了Servlet与Servlet容器之间的契约,Servlet容器将Servlet类载入内存,生成Servlet实例并调用它具体的方法,所以它是所有Servlet类必须直接或者间接实现的一个接口。

3.1.3 Servlet接口的继承结构

  • Servlet接口:只负责定义Servlet程序的访问规范;

  • GenericServlet抽象类:实现了Servlet接口,做了很多空实现,并持有一个ServletConfig类的引用,并提供了一些ServletConfig的使用方法;

  • HttpServlet抽象类:实现了service方法,并实现了请求分发处理;
    Selvlet继承结构

3.2 Servlet快速入门

3.2.1创建javaweb项目

3.2.1.1 创建maven工程

创建Maven项目

3.2.1.2 添加webapp目录
  1. 右击项目,选择Add Frameworks Support
    添加框架支持

  2. 选择Web Application,再点击OK 添加web应用

  3. 将web目录拖拽到main目录下,并改名为webapp
    webapp

    • webapp:静态资源比如 html css js jsp可以定义在web下面
    • WEB-INF:里面的资源不能直接被外界访问 web.xml 是web项目的核心配置文件
    • index.jsp:web项目的访问首页,在默认情况我们访问的首页就是index.jsp

3.2.2 添加依赖

<dependency>
    <groupId>javax.servlet</groupId>
	<artifactId>javax.servlet-api</artifactId>
	<version>3.1.0</version>
</dependency>

由于Servlet版本分为<=4.0和>=5.0两种,所以,要根据使用的Servlet版本选择正确的Tomcat版本。从Tomcat版本页可知:

  • 使用Servlet<=4.0时,选择Tomcat 9.x或更低版本;
  • 使用Servlet>=5.0时,选择Tomcat 10.x或更高版本。

3.2.3 创建servlet实例

package com.by.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;
    }

    @Override
    public void service(ServletRequest req, ServletResponse servletResponse) 
        									throws ServletException, IOException {
        servletResponse.setContentType("text/html;charset=utf-8");
        servletResponse.getWriter().write("<h1>hello<h1>");
    }

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

    @Override
    public void destroy() {

    }
}

3.2.4 配置servlet

  • web.xml中配置
<!--
   配置Servlet
   servlet-name:servlet的名称
   servlet-class:servlet的全类名
   url-pattern: 访问servlet的url
 -->
<servlet>
    <servlet-name>hello</servlet-name>
    <!--     servlet-name要和servlet-mapping所对应,映射的关系-->
    <servlet-class>com.by.servlet.HelloServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello</url-pattern>
</servlet-mapping>
  • 注解方式配置
@WebServlet("/hello")
public class HelloServlet implements Servlet {}

3.2.5 设置打包方式

  • 修改pom.xml
<!--打包方式-->
<packaging>war</packaging>

3.2.6 部署web项目

  1. 点击“Edit Configurations”

运行配置

  1. 点击"+"

添加配置

  1. 点击Tomcat Server中的Local

选择tomcat

  1. 配置Tomcat路径

配置tomcat

  1. 部署web项目

部署项目

  1. 启动tomcat

启动tomcat

  1. 查看是否部署成功

查看是否部署成功

3.2.7 测试

浏览器访问:http://localhost:8080/01_servlet_HelloWorld_war/hello

3.3 servlet的生命周期

3.3.1 什么是servlet的生命周期

Servlet的生命周期就是servlet类对象什么时候创建?什么时候调用对应的方法,什么时候销毁。

对象的生命周期:

Student student = new Student(); //创建对象
student.setName("eric"); // 使用对象
student.show();// 使用对象
student = null; // 销毁对象

也就是说自定义对象的生命周期由我们程序员自己手动控制。但是!!!Servlet它不是一个普通的java类。是一个被tomcat服务器调用的。所以Servlet是生命周期是被tomcat服务器去控制的。

3.3.2 servlet生命周期中重要的方法

  • 构造方法:创建servlet的时候调用。默认情况下,第一次访问servlet的时候,会创建servlet对象。此时会有且只会调用1次构造函数,证明了servlet对象是单实例的。

  • init方法:创建完servlet对象之后调用,也只是会调用1次。

  • service方法:提供服务的方法,接收用户的请求,并处理用户的请求,然后响应用户的请求。每次发送请求,都会调用service方法。调用几次,service方法会执行几次。

  • destroy方法:销毁的方法。销毁servlet对象的时候调用。比如我们停止tomcat服务器或者重新部署tomcat服务器,都会销毁servlet对象,只会调用1次。

3.3.3 tomcat服务器内部执行代码的原理

  1. 用户发送请求
    tomcat服务器会根据用户发送的请求,解析web.xml配置文件,获取servlet-class的全限定名路径(com.by.servlet.ServletDemo)

  2. 获取字节码对象,然后通过字节码对象获取对应的实例对象
    Class clazz = Class.forName(“com.by.servlet.ServletDemo”);
    Object o = clazz.newInstance();

  3. 创建ServletConfig对象,然后调用init方法
    Method method = clazz.getDeclaredMethod(“init”,ServletConfig.class);// 获取方法对象
    method.invoke(o,config);

  4. 创建request对象,创建response对象,然后调用service方法
    Method m = clazz.getDeclaredMethod(“service”,ServletRequest.class,ServletResponse.class);
    m.invoke(o,request,response);

  5. 销毁servlet实例对象,也是通过反射的机制实现的
    Method m1 = clazz.getDeclaredMethod(“destroy”,null);
    m1.invoke(o,null);

3.3.4 测试servlet的声明周期

public class LifeCycleServlet implements Servlet {

    public LifeCycleServlet(){
        System.out.println("LifeCycleServlet has run........");
    }

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("init method has run........");
    }

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

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("service method has run........");
    }

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

    @Override
    public void destroy() {
        System.out.println("destroy method has run........");
    }
}

4 创建servlet的三种方式

4.1 实现Servlet接口的方式

@WebServlet("/test1")
public class Servlet1 implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        //s使用ServletConfig对象初始化我们的Servlet
        //执行了,从这个地方可以说明一个问题 Servlet已经被实例化了
        System.out.println("init方法执行");
    }

    @Override
    public ServletConfig getServletConfig() {
        //获取servlet配置信息对象
        //没有执行
        System.out.println("getServletConfig方法执行");
        return null;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        //解决中文乱码问题
        servletResponse.setContentType("text/html;charset=utf-8");
        servletResponse.getWriter().append("我是Servlet接口创建的Servlet");
    }

    @Override
    public String getServletInfo() {
        //获取Servlet的详细信息
        //没有执行
        System.out.println("getServletInfo方法执行");
        return null;
    }

    @Override
    public void destroy() {
        //当tomcat关闭的时候,执行销毁这个servlet的方法
        System.out.println("destroy方法执行");
        //只有当tomcat关闭的时候,才会执行这个方法
        
    }
}

4.2 继承GenericServlet抽象类的方式

@WebServlet("/test2")
public class Servlet2 extends GenericServlet {
    //只有一个方法是必须重写的,抽象方法
    //为什么?service是核心方法,因为请求和响应就是执行这个方法
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        //解决中文乱码问题
        servletResponse.setContentType("text/html;charset=utf-8");
        servletResponse.getWriter().append("我是GenericServlet抽象类创建的Servlet");

    }
}

4.3 继承HttpServlet的方式

@WebServlet("/test3")
public class Servlet3 extends HttpServlet {
    //因为在前端的时候,有两种请求方式get和post
    //doGet和doPost方法写在了Service方法中了
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        resp.getWriter().println("我是HttpServlet创建的Servlet");
    }
}

HttpServlet抽象类使用HttpServletRequestHttpServletResponse继承并增强了ServletRequest和ServletResponse类

  • H t t p S e r v l e t R e q u e s t \boxed{HttpServletRequest} HttpServletRequest封装了一个HTTP请求,我们通过其实例req可以拿到HTTP请求的几乎全部信息,常用的方法有:

    • getMethod():返回请求方法,例如,GETPOST
    • getRequestURI():返回请求路径,但不包括请求参数,例如,“/hello”;
    • getQueryString():返回请求参数,例如,“name=Bob&a=1&b=2”;
    • getParameter(name):返回请求参数,GET请求从URL读取参数,POST请求从Body中读取参数;
    • getContentType():获取请求Body的类型,例如,“application/x-www-form-urlencoded”;
    • getContextPath():获取当前Webapp挂载的路径,对于ROOT来说,总是返回空字符串"";
    • getCookies():返回请求携带的所有Cookie;
    • getHeader(name):获取指定的Header,对Header名称不区分大小写;
    • getHeaderNames():返回所有Header名称;
    • getInputStream():如果该请求带有HTTP Body,该方法将打开一个输入流用于读取Body;
    • getReader():和getInputStream()类似,但打开的是Reader;
    • getRemoteAddr():返回客户端的IP地址;
    • getScheme():返回协议类型,例如,“http”,“https”;

可通过request.setCharacterEncoding(“utf-8”);解决从前端获取的中文数据乱码的问题

此外,HttpServletRequest还有两个方法:setAttribute()getAttribute(),可以给当前HttpServletRequest对象附加多个Key-Value,相当于把HttpServletRequest当作一个Map<String, Object>使用。

  • H t t p S e r v l e t R e s p o n s e \boxed{HttpServletResponse} HttpServletResponse封装了一个HTTP响应,提供了许多设置Header的方法,常用的设置Header的方法有:
    • setStatus(sc):设置响应代码,默认是200;
    • setContentType(type):设置Body的类型,例如,“text/html”;
    • setCharacterEncoding(charset):设置字符编码,例如,“UTF-8”,可解决浏览器响应内容中文乱码的问题;
    • setHeader(name, value):设置一个Header的值;
    • addCookie(cookie):给响应添加一个Cookie;
    • sendRedirect():重定向

这三个创建方式选择哪个?

最好的方式是继承HttpServlet

  1. 可以减少对其他方法的要求 init destroy

  2. 可以根据前端的要求进行分门别类 doGet doPost

5.重定向和转发

5.1 重定向

  • 什么是重定向

重定向是指当浏览器请求一个URL时,服务器返回一个重定向指令(302状态码),告诉浏览器地址已经变了,麻烦使用新的URL再重新发送新请求。

一个页面跳转到另外一个页面(应用场景)、登录页面跳转到主页面:
login.jsp====> LoginServlet====>main.jsp

  • 特征:

    1. 重定向的过程是浏览器(客户端)的行为
    2. 实际上浏览器做了2次请求(当点击登录按钮的时候做了两次请求)(分别是请求login和main.jsp)
    3. 注意上一次请求的request对象会丢失
    4. 重定向有一个非常明显的特征,即浏览器的url变化了
  • RedirectServlet

@WebServlet("/redirect")
public class RedirectServlet extends HttpServlet {
     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置字符编码
        request.setCharacterEncoding("utf-8");
        request.setAttribute("name", "二狗");

        response.sendRedirect("main.jsp");
    }
}
  • 重定向核心代码

response.sendRedirect(“main.jsp”);

两个请求

5.2 请求转发

  • 什么是请求转发

请求转发是指内部转发。当一个Servlet处理请求的时候,它可以决定自己不继续处理,而是转发给另一个Servlet处理。

  • 特征:

    1. 转发是服务器的行为
    2. 浏览器在这个过程中只有一次请求
    3. 可以传递带有数据的request
    4. url不会发生任何的变化
  • ForwardServlet

@WebServlet("/redirect")
public class ForwardServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置字符编码
        request.setCharacterEncoding("utf-8");
        request.setAttribute("name", "二狗");

        request.getRequestDispatcher("main.jsp").forward(request, response);
    }
}
  • 请求转发核心代码

request.getRequestDispatcher(“main.jsp”).forward(request,response);

6.Servlet自动加载

  • 为什么要用自动加载

默认情况下,第一次访问servlet的时候,创建servlet对象。如果servlet构造函数里面的代码或者init方法里面的代码比较多,就会导致用户第一次访问servlet的时候比较慢。

这个时候,我们可以改变servlet对象的创建时机:在启动服务器、加载web应用时创建servlet对象。在servlet的配置信息中,加上一个<load-on-startup>标签即可。

  • 如何设置自动加载
	<servlet>
        <servlet-name>forward</servlet-name>
        <servlet-class>com.by.servlet.ForwardServlet</servlet-class>
        
        <!--容器是否在启动时加载该servlet,数字越小优先级越高越高-->
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>forward</servlet-name>
        <url-pattern>/forward</url-pattern>
    </servlet-mapping>

这样配置之后,servlet的构造函数和init方法就会在web应用加载的时候就会执行。

7.ServletConfig对象

  • 是什么

ServletConfig是javax.servlet.包下的一个接口,ServletConfig它是Servlet的一个配置对象

ServletConfig是由tomcat容器创建,通过init方法传入给Servlet;

  • ServletConfig对象如何获取?
ServletConfig servletConfig = getServletConfig();

HttpServlet抽象类继承了GenericServlet抽象类
因此在继承Httpservlet或GenericServlet实现的servlet中,可直接调用getServletConfig()获取ServletConfig对象

  • 常用方法
getInitParameter(String parameterName); //根据参数名称获取指定的参数值
getInitParameterNames(); //获取所有的参数名称
  • 获取servlet里面定义的初始化参数
    <servlet>
        <servlet-name>servletConfig</servlet-name>
        <servlet-class>com.by.servlet.ServletConfigServlet</servlet-class>
        <!--Servlet的初始化参数-->
        <init-param>
            <param-name>username</param-name>
            <param-value>root</param-value>
        </init-param>
        <init-param>
            <param-name>password</param-name>
            <param-value>root123</param-value>
        </init-param>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>servletConfig</servlet-name>
        <url-pattern>/servletConfig</url-pattern>
    </servlet-mapping>
public class ServletConfigServlet extends HttpServlet {

    @Override
    public void service(ServletRequest servletRequest, 
                        ServletResponse servletResponse) throws ServletException {
        //1.获取ServletConfig对象
        ServletConfig servletConfig = getServletConfig();
        //2.获取Servlet中的初始化参数
        String username = servletConfig.getInitParameter("username");
        String password = servletConfig.getInitParameter("password");
		//3.输出数据
		System.out.println(username);
        System.out.println(password);

    }
}

8.ServletContext对象

  • 是什么

ServletContext是javax.servlet包下的一个接口,又称上下文对象,是配置对象也是一个域对象

当服务器启动时,会为服务器中的每一个web项目创建一个ServletContext对象;

在web应用中的servlet要想实现资源的共享,可以通过ServletContext来完成;

  • 如何获取这个对象
ServletContext servletContext = getServletContext();

HttpServlet抽象类继承了GenericServlet抽象类
因此在继承Httpservlet或GenericServlet实现的servlet中,可直接调用getServletContext()获取ServletConfig对象

  • 这个对象里面也有很多方法:
getInitParameter() //获取指定参数名称的全局参数值
getRealPath(String path) //获得当前项目的服务器磁盘路径
getContextPath() //获取项目的根路径
getAttribute(String parameterName) //获取ServletContext域中指定名称的参数值;
setAttribute(String paramterName,Object parameterValue) //存储参数到ServletContext域中;
removeAttribute(String parameterNam) //将ServletContext域中指定名称的参数移除;
  • 定义全局初始化参数
    <context-param>
        <param-name>username</param-name>
        <param-value>root</param-value>
    </context-param>
    <context-param>
        <param-name>password</param-name>
        <param-value>root456</param-value>
    </context-param>
  • 获取全局初始化参数

使用ServletContext对象可在该web项目中的任意servlet获取全局初始化参数

public class ServletContextServlet extends HttpServlet {

    @Override
    public void service(ServletRequest servletRequest, 
                        ServletResponse servletResponse) throws ServletException {
        //获取ServletContext对象
        ServletContext servletContext = getServletContext();
        //1.获取全局初始化参数
        String username = servletContext.getInitParameter("username");
        System.out.println(username);
        String password = servletContext.getInitParameter("password");
        System.out.println(password);
        //2.获取服务器真实路径
        String upload = servletContext.getRealPath("");
        System.out.println(upload);
        //3.获取项目的根路径
        String contextPath = servletContext.getContextPath();
        System.out.println(contextPath);

        //4.往ServletContext域中,存储一个名称为msg的属性,值为"hello"
        String str = "hello";
        servletContext.setAttribute("msg",str);
    }
}

8.Cookie和Seesion

8.1 Cookie

http协议是一个无状态的协议,你每一个跳转到下一个页面的时候都是需要先登录才能使用,这样就很麻烦比如淘宝,没有cookie和session的话,用户在首页已经登录上去了,但是需要再次登录才能选择商品,需要再次登录才能放到购物车,需要再次登录才能然后购买,这样用户的体验是相当差的。

  • 什么是Cookie?
  1. cookie是在浏览器中保存的
  2. 如果想要使用cookie要保证我们的浏览器是开启cookie,所以说有一定的弊端,如果浏览器没有开启cookie,就不能再使用cookie了
  3. cookie的大小是有限制的,通常是4096byte
  4. cookie的保存是以键值对的形式存在的
  • 使用方法
  1. 添加Cookie
//新建一个Cookie,通过构造方法直接设置key和value
Cookie msg = new Cookie("msg", "Hello World");
//设置cookie最大存活时间
msg.setMaxAge(60*60*24);
//将cookie添加到网页上
resp.addCookie(msg);
  1. 修改Cookie
 //从请求上获取Cookie数组
Cookie[] cookies = req.getCookies();
//遍历数组,找到要修改的cookie
for (Cookie cookie : cookies) {
    if (cookie.getName().equals("JSESSIONID")){
        //修改cookie的value值
        cookie.setValue("are_you_ok");
        //重新添加,覆盖原来的cookie使修改生效
        resp.addCookie(cookie);
    }
}
  1. 删除Cookie
//从请求上获取Cookie数组
Cookie[] cookies = req.getCookies();
//遍历数组,找到要删除的cookie
for (Cookie cookie : cookies) {
    if (cookie.getName().equals("msg")){
        //将存活时间设为0即为删除
        cookie.setMaxAge(0);
        //重新添加,覆盖原Cookie
        resp.addCookie(cookie);
    }
}

8.2 Session

  • 什么是Session
  1. 保存服务器中
  2. 当用户发送一个HTTP请求到服务器时,服务器会检查该请求是否包含session标识符(通常是存cookie),如果没有,则会创建一个新的session(存储区域),并将session标识符发送给客户端。浏览器再发送请求时会携带session标识符,此时服务器根据session标识符就可以找到对应的session(存储区域)
    使用session的时候一般要开启cookie如果浏览器没有开启cookie功能,我们可以通过html的url传参完后session的使用
  3. 没有大小的限制
  4. 信息的保存也是以键值对的形式存在的
  • 使用方法
  1. 添加Session
 //获取Session对象
HttpSession session = req.getSession();
//设置参数
session.setAttribute("msg","nb");
//设置最大未访问时长,超过则session失效
session.setMaxInactiveInterval(60*60*24);
  1. 获取Session
//获取Session对象
HttpSession session = req.getSession();
//获取参数
Object msg = session.getAttribute("msg");

//输出sessionId和msg参数
System.out.println(session.getId());
System.out.println("msg="+msg);
  1. 删除Session
//获取session对象
HttpSession session = req.getSession();
//删除参数
session.removeAttribute("msg");

//将session设为失效,再次发请求时服务器会再创建一个session,使用新的sessionID
session.invalidate();

8.3 四大作用域

四大作用域,也可以说是四种域对象的生效范围,从大到小分别是:

标识符作用域存活时间
ServletContexttomcat服务器运行期间
Session浏览器浏览器运行期间
Servlet一次请求请求存活期间
PageContext页面页面显示期间

9.过滤器和监听器

9.1 过滤器

  • 什么是过滤器

当浏览器向服务器发送请求的时候,过滤器可以将请求拦截下来,完成一些特殊的功能,比如:编码设置、权限校验、日志记录等。

  • 为什么要使用过滤器

从前台获取中文数据时如果不设置编码格式,则获取到的数据会乱码,为了解决乱码,每次编写新的servlet都需要设置一下编码格式,过于繁琐。

有没有什么方法可以只配置编码格式一次后,在所有的servlet都生效呢?

这时候filter就出来了,配置filter后可以将所有请求在执行对应的servlet之前,先过一遍filter,
如果在filter里边设置编码的话,那么经过filter的所有servlet就不用单独设置了。
Filter

  • Filter实例
public class CharEncodingFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain filterChain) throws IOException, ServletException {
        //请求进入,经过过滤器
        System.out.println("请求进入,经过过滤器");
       	//设置编码格式
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");

        //请求放行,调用servlet
        filterChain.doFilter(req,resp);

        //请求返回,经过过滤器
        System.out.println("请求返回,经过过滤器");
    }

    @Override
    public void destroy() {

    }
}
  • 使用过滤器需要注意的事项:
  1. 过滤器必须实现Filter接口
  2. 过滤器拦截的请求执行完毕之后,必须要放行,否则我们的请求就不会被执行。
 filterChain.doFilter(request,response); //过滤器放行
  1. 我们可以使用@WebFilter来配置过滤器要拦截的资源,当然我们也可以通过xml的方式配置过滤器。
    <filter>
        <filter-name>filter</filter-name>
        <filter-class>com.by.servlet.FilterDemo</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>filter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
  • Filter的拦截路径的配置
  1. 拦截具体的资源路径:/index.jsp,只有访问index.jsp的时候才会被拦截
  2. 目录拦截:/user/*,访问/user下的所有资源,都会被拦截
  3. 后缀名拦截:*.do 访问后缀名为do的资源,都会被拦截
  4. 拦截所有:/* 访问所有的资源,都会被拦截

9.2 监听器

  • 什么是监听器

\监听器可以监听ServletContext,session,request三个对象创建、销毁或者往其中添加修改删除属性时自动执行代码的功能组件。

监听器分类监听器名称作用
Servletcontext监听ServletContextListener 用于对Servletcontext对象进行监听(创建、销毁)
ServletContextAttributeListener对Servletcontext对象中属性的监听(增删改属性)
Session监听HttpSessionListener对session对象的整体状态的监听(创建、销毁)
HttpSessionAttributeListener对session对象中的属性监听(增删改属性)
HttpSessionBindingListener监听对象于Session的绑定和解除
HttpSessionActivationListener对session数据的钝化和活化的监听
Request监听ServletRequestListener对Request对象进行监听(创建、销毁)
ServletRequestAttributeListener对Request对象中属性的监听(增删改属性)
  • 使用方法
  1. 创建监听器
public class MyListener implements ServletContextListener, HttpSessionListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("tomcat启动,创建ServletContext对象");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("tomcat关闭,销毁ServletContext对象");
    }

    @Override
    public void sessionCreated(HttpSessionEvent se) {
        System.out.println("浏览器第一次访问tomcat,创建session");
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        System.out.println("session失效,销毁session");
    }
}

  1. 配置监听器
<listener>
    <listener-class>com.by.Listener.MyListener</listener-class>
</listener>

10.web三层架构

我们的开发架构一般都是基于两种形式,一种是 C/S 架构,也就是客户端/服务器,另一种是 B/S 架构,也就是浏览器服务器。在 JavaEE 开发中,几乎全都是基于 B/S 架构的开发。

那么在 B/S 架构中,系统标准的三层架构包括:表现层业务层持久层
三层架构

三层架构中,每一层各司其职,接下来我们就说说每层都负责哪些方面:

  • 表现层(web/servlet)

也就是我们常说的web层。它负责接收客户端请求,向客户端响应结果,通常客户端使用http协议请求web 层,web 需要接收 http 请求,完成 http 响应。

表现层包括展示层控制层:控制层负责接收请求,展示层负责结果的展示。

表现层依赖业务层,接收到客户端请求一般会调用业务层进行业务处理,并将处理结果响应给客户端。

表现层的设计一般都使用 MVC 模型。(MVC 是表现层的设计模型,和其他层没有关系)

MVC 全名是 Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,
是一种用于设计创建 Web 应用程序表现层的模式。MVC 中每个部分各司其职:

  • Model(模型):

通常指的就是我们的数据模型。作用一般情况下用于封装数据。

  • View(视图):

通常指的就是我们的 jsp 或者 html。作用一般就是展示数据的。
通常视图是依据模型数据创建的。

  • Controller(控制器):

是应用程序中处理用户交互的部分。作用一般就是处理程序逻辑的。

  • 业务层(service)

也就是我们常说的 service 层。它负责业务逻辑处理,和我们开发项目的需求息息相关。web 层依赖业务层,但是业务层不依赖 web 层。

业务层在业务处理时可能会依赖持久层,如果要对数据持久化需要保证事务一致性。(也就是我们说的,事务应该放到业务层来控制)

  • 持久层(dao)

也就是我们是常说的 dao 层。负责数据持久化,包括数据层即数据库和数据访问层,数据库是对数据进行持久化的载体,数据访问层是业务层和持久层交互的接口,业务层需要通过数据访问层将数据持久化到数据库中。通俗地讲,持久层就是和数据库交互,对数据库表进行增删改查的

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

这河里吗l

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值