servlet整体学习历程

目录

一、关于软件架构

二、访问网址的步骤

三、web服务器

四、idea集成tomcat

五、servlet的生命周期

六、servletConfig

七、servletContext应用域

八、http协议

九、HttpServlet

十、@webservlet注解

十一、三种方法应用

十二、web欢迎页面

十三、HttpServletRequst

十四、HttpServletResponse

十五、请求转发和重定向的区别

十六、session

十七、cookie

十八、session和cookie的区别

十九、过滤器

二十、监听器

二十一、mvc的设计模式


一、关于软件架构

1.软件架构分类

1.1 C/S结 构

客户端/服务器(client/server)

     例如: qq、英雄联盟
  • 优点:

速度快(大部分的数据都存储在客户端、只需要服务器传输少量的数据就行)、

用户体验好(页面美观,速度快)、

安全性高(大部分的数据是存储在客户端的,发生了地震的自然灾害,导致服务器摧毁了,但是由于大部分数据保存在客户端,影响不大)

  • 缺点:

需要下载客户端

难维护

1.2 B/S结构

浏览器/服务器(brower/server)

例如:百度、新浪微博网页版

  • 优点:

不需要下载客户端

容易维护

  • 缺点:

速度慢

用户体验不好

安全性不高

1.3 B/S开发

又称为网页开发,又称为web开发

web开发分为:

web前端开发:HTML、css、js

                 web后端开发:c、C++、**Java**、python、php、**servlet规范**

Java开发后端,又称为Java开发web,称为javaweb

二、访问网址的步骤

百度一下,你就知道 (网址)

www.baidu.com (域名)

1.步骤

  1. 打开浏览器,在浏览器输入域名

  2. 浏览器使用到域名解析器,把我们的域名解析成IP地址和端口号的方式。

  3. 通过IP地址定位到服务器,通过端口号定位到服务

2.名称解析

2.1 IP地址

  • 计算机在网络中的编号,在同一个网络中,IP地址是唯一的,定位服务器。两台计算机要互相通信,首先知道对方的IP地址。

2.2 端口号

  • 一个端口号就表示一个应用,比如打开MySQL就可以占用3306端口号

三、web服务器

1.浏览器

QQ浏览器、360浏览器、谷歌浏览器(推荐使用)

web服务器:tomcat(轻巧、免安装)

2.tomcat服务器的目录结构

  • bin目录:存放tomcat的相关的命令的

  • conf目录:存放tomcat配置文件

修改乱码:

  • lib目录:存放jar包的

  • logs:存放tomcat日志文件的

  • temp:存放临时文件的

  • work:存放编译后的文件的,有可能是编译后的jsp文件

  • webapps:存放web应用的目录的

3.tomcat关闭和开启命令

开启tomcat的指令:startup.bat

关闭tomcat的指令:shutdown.bat

四、idea集成tomcat

1.新建空的工程

  • file--->[new project] --->[empty project] --->输入以及目录--->finsh

2.在空的工程建立普通的Java模块

  • file--->[new module]--->[java]--->[模块的名称]--->finish

3.给Java添加框架支持,web

4.添加tomcat支持

5.配置tomcat环境

jdbc连接数据库的步骤:
*      1.加载驱动
*      2.创建连接
*      3.编写sql语句
*      4.执行SQL语句,获取结果集
*      5.处理结果集(select 情况下)
*      6.关闭流资源

6.启动tomcat

请求:浏览器向服务器发送数据。

响应:服务器向浏览器发送数据。

五、servlet的生命周期

Servlet 生命周期可被定义为从创建直到毁灭的整个过程。

1.Servlet 遵循的过程

  • Servlet 初始化后调用 init () 方法。

  • Servlet 调用 service() 方法来处理客户端的请求。

  • Servlet 销毁前调用 destroy() 方法。

  • 最后,Servlet 是由 JVM 的垃圾回收器进行垃圾回收的。

2.servlet什么时候被创建

tomcat启动的时候servlet没有被创建

第一次发送对应的请求的手被创建

2.1 问题1:

2.1.1tomcat启动的时候都做了什么?

在tomcat底层其实有一个hashmap,tomcat启动的时候会扫描web.xml文件,将路径和全类名放在map中.

2.1.2 为什么不提前创建servlet?

因为如果一开始就创建所有的servlet,如果用户打开我们的项目只想做一些简单的操作,只会用到少量的servlet。

2.1.3 我们可以自己指定servlet对象是不是在tomcat启动的时候创建。

在web.xml中设置0 <load-on-startup>1</load-on-startup>

1(自然数):表示创建的顺序,数字越小越先创建'

如果有多个servlet需要启动的时候创建,数字越小,越先启动。

 3.servlet什么时候被销毁

在tomcat服务器被关闭的搜被销毁

4.当我们发送请求的时候tomcat做了什么

  • http://localhost:8080/day01/test

  • 获取到/test

  • 回到hashmap中进行一个匹配。获取到servlet的全类名,通过反射的方式创建出对象

  • 调用init方法,调用service。

  • 最后关闭tomcat的时候就会销毁servlet

5.请求响应

请求:浏览器向服务器发送数据。

响应:服务器向浏览器发送数据。

原因:反射创建servlet的时候走的是无参构造方法。如果有有参构造方法就会导致默认的无参构造方法 消失。为了解决这一个问题,init方法就出现了。

5.1 init方法

/**
* 做初始化的事情
* 执行的时机实在servlet被创建的时候,其实等他于构造方法。
* 做缓存的时候用。
* init方法只在servlet被创建的时候执行一次
* @param servletConfig
* @throws ServletException
*/
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("init方法被执行。");
}
​

5.2 destroy方法

/*
* 这个是销毁方法,执行的时候servlet还没有被销毁
* 遗言方法。
* 也只调用一次,在tomcat服务器关闭的时候调用。
* 流资源的关闭。
* 资源的销毁。
* */
@Override
public void destroy() {
System.out.println("servlet即将被销毁");
System.out.println("destroy方法被执行了");
}

附五:GenericServlet

思考:在我们写的Servlet类中init方法和destory方法用的比较少,很多情况下都不用。 那我们这样直接实现Servlet接口是不是有弊端。

如何解决?

  • 通过jdk8的默认方法,也许但是不好。

  • 我们可以通过加一层的方式来解决这个问题。

说明继承了GenericServlet的类重写init方法是重写init的无参构造方法:

为什么重写的是这个方法?
1、我们在init方法中做的一般是初始化的操作,一比如数据库的连接,不会用到servletconfig对象
2、我们希望在其他类中也使用servletconfig这个对象。
3、在父类中带有参数的init方法有this.config = config;的操作,如果我们要重写这个方法也要把这个
补起来。
4、在父类中带有参数的init方法中会调用无参数的init方法。

六、servletConfig

1.servletconfig是由谁创建的??

  • 由tomcat容器创建的

2.servletconfig是什么?

  • 是servlet的配置

  • 在tomcat启动的时候,扫描web.xml文件,就会把对应的信息封装到servletconfig中

3.servletconfig是不是共享的?

  • 不是共享的,一个servlet对应一个servletconfig

api的讲解

七、servletContext应用域

1.servletContext对象是由谁创建的?

  • 由tomcat容器创建的

2.servletContext是什么? context(环境)

  • 是servlet环境

3.servletContext是所有servlet公用的还是servlet对应一个呢?

  • 是所有的servlet公用的

4.servletContext的api解释

5.servletContext的生命周期

  • 在容器启动的时候就创建

  • 在容器关闭的时候就被销毁了

  • 存活的时间比较长

6.servletContext又叫做应用域

  • 我们可以向应用域中放一些数据,这些数据就是所有的servlet共享的

  • 什么样的数据可以放在应用域中

  1. 所有servlet共享

    因为servletcontext的特效就是所有的servlet共享的

  2. 数据比较小

    因为servletContext存活时间很长,如果放在里面长期不用会导致空间浪费

  3. 数据不经常被修改

    因为共享数据据会修改,会产生问题?

    多线程情况下会导致数据不安全

7.如何向servlet应用域中存放数据

8.在实际开发中

我们都不直接实现servlet接口,也不继承GenericServlet。httpServlet,专门做HTTP协议请求和响应

servlet 爷爷

GenericServlet 父亲 实现servlet

httpServlet 儿子 继承GenericServlet

八、http协议

协议是什么?

  • 双方制定的规范,如果我们都遵守这个协议,就可以达成一致

HTTP协议

  • 超文本传输协议,由W3C制定的

  • 超文本,图片、视频、流媒体都是超文本

1.HTTP协议中的请求协议

1.1HTTP请求协议的组成

  • 请求行(请求方式 uri)

  • 请求头

  • 空白行

  • 请求体(post才有,get没有,存放需要传送的参数数据)

1.2 get

1.3post

2.uri和utl的区别

url:统一资源定位符

http://localhost:8080/day01_war_exploded/b

uri:同一资源标识符

/day01_war_exploded/b

3.HTTP协议中的响应协议

3.1 HTTP响应协议的组成

  • 响应行(协议版本号、状态码、响应状态)

  • 响应头()

  • 空白行

  • 响应体(服务器把数据发送给浏览器)

3.2状态码

4.get请求和post请求的区别

get请求:

  • 没有请求体,传输的数据放在地址栏上面的

  • 对传输的数据有所限制的,只能是字符串,长度也有限制,不超过2K

  • get请求是期望从服务器拿到数据

  • get请求比较安全

  • get请求时有缓存的

  • 回退:get请求是不会再次发送请求的

post请求:

  • 有请求体,传输的数据放在请求体中的。

  • 对数据没有限制,成都也没有限制,不单单是字符串

  • post请求时期望把数据传输给服务器。

  • post请求不太安全

  • post请求是没有缓存的

  • post请求会再次发送请求

九、HttpServlet

1.httpServlet是干什么的?

  • 专门为了处理http请求的类

  • 给大家演示一下具体的操作,说说直接重写doPost和doGet方法的坏处。

2.分析源码:

  • 首先回顾一下servlet的生命周期

    • 执行servlet的构造方法

    • 通过反射执行servlet的init方法。

    • 通过反射执行service方法。

protected void service(HttpServletRequest req, HttpServletResponse resp) throws
ServletException, IOException {
//获取发送请求的方法。
        String method = req.getMethod();
        long lastModified;
        if (method.equals("GET")) {
            lastModified = this.getLastModified(req);
            if (lastModified == -1L) {
                //如果是get请求走doGet的方法,由于子类重写了doGet方法,所以执行子类的doGet方法。
                this.doGet(req, resp);
            } else {
                long ifModifiedSince;
                try {
                ifModifiedSince = req.getDateHeader("If-Modified-Since");
                } catch (IllegalArgumentException var9) {
                    ifModifiedSince = -1L;
                }
                
                if (ifModifiedSince < lastModified / 1000L * 1000L) {
                    this.maybeSetLastModified(resp, lastModified);
                    this.doGet(req, resp);
                } else {
                    resp.setStatus(304);
                }
            }
        } else if (method.equals("HEAD")) {
            lastModified = this.getLastModified(req);
            this.maybeSetLastModified(resp, lastModified);
            this.doHead(req, resp);
        } else if (method.equals("POST")) {
            //如果是post请求走doPost的方法,由于子类重写了doPost方法,所以执行子类的doPost方法。
            this.doPost(req, resp);
            } else if (method.equals("PUT")) {
                this.doPut(req, resp);
            } else if (method.equals("DELETE")) {
                this.doDelete(req, resp);
            } else if (method.equals("OPTIONS")) {
                this.doOptions(req, resp);
            } else if (method.equals("TRACE")) {
               this.doTrace(req, resp);
            } else {
                String errMsg = lStrings.getString("http.method_not_implemented");
                Object[] errArgs = new Object[]{method};
                errMsg = MessageFormat.format(errMsg, errArgs);
                resp.sendError(501, errMsg);
        }
    }
解释为什么不建议同时重写doGet和doPost方法。 
1.如果为了避免405异常,我们可以直接重写Service的方法。
2.无法享受405异常,如果前端不按照要求来传数据,我们无法得知 
3.一个类只做和这个类有关的事情。比如登录页面,就做登录的功能,那么登录我们就必须要求通过、post请求的方式来传输数据。

十、@webservlet注解

//指定servlet的名字 
1. String name() default "";
	 @WebServlet(name = "AServlet",value = {"/abc"})

//请求路径,通过数组来接收,可以多个,如果只有value这个属性的话,就可以不写。如果只有一个地址,大括号可以不写,简化开发
   2. String[] value() default {};
     @WebServlet({"/aa","/bb","/cc"})
	 @WebServlet("/aa")

//请求路径,通过数组来接收,可以多个
   3. String[] urlPatterns() default {};
     @WebServlet(urlPatterns = {"/aa","/bb","/cc"})
    
//tomcat启动的时候是否创建servlet
   4. int loadOnStartup() default -1;
     @WebServlet(value = {"/abc"},loadOnStartup = 1)

//设置servlet的参数
   5. WebInitParam[] initParams() default {};
	 @WebServlet(value = "/abc",initParams = {@WebInitParam(name = "username",value = "admin") })

十一、三种方法应用

1.Servlet接口:应用

/**
 * 实现servlet接口,重写5个方法
 * 在service的方法中处理请求
 * 注册servlet,在web.xml中
 */


package test;

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

/**
 * 实现servlet接口,重写5个方法
 * 在service的方法中处理请求
 * 注册servlet,在web.xml中
 */
public class Demo1 implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {

    }

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

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        //设置响应格式,设置返回到浏览器的数据类型
        servletResponse.setContentType("text/html;charset=utf-8");

        //获取流对象,主要是显示数据到浏览器
        PrintWriter out = servletResponse.getWriter();

        //在浏览器输出hello servlet
        out.write("hello");
        System.out.println("hello");
    }

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

    @Override
    public void destroy() {

    }
}
<?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_4_0.xsd"
         version="4.0">
    
    <servlet>
        <servlet-name>Demo1</servlet-name>
        <servlet-class>test.Demo1</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Demo1</servlet-name>
        <url-pattern>/demo1</url-pattern>
    </servlet-mapping>
</web-app>

和数据库进行交互:

package servletimp;

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

public class Demo2 implements Servlet {

    Connection conn;
    PreparedStatement pre;
    ResultSet res;

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {

    }

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

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {

        try {
            Class.forName("com.mysql.jdbc.Driver");

            String url = "jdbc:mysql://localhost:3306/javaweb?useSSL=true&amp;useUnicode=true&amp;characterEncoding=utf8&amp;serverTimezone=Asia/Shanghai";
            String name = "root";
            String password = "123456";
            conn = DriverManager.getConnection(url,name,password);

            String sql = "select * from user";

            pre = conn.prepareStatement(sql);
            res = pre.executeQuery();

            while (res.next()){
                servletResponse.setContentType("text/html;charset=utf-8");
                PrintWriter out = servletResponse.getWriter();

                out.write(res.getString("id"));
                out.write(res.getString("username"));
                out.write(res.getString("password"));
                out.write(res.getString("dept"));
                out.write(res.getString("sex"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {

            try {
                if (res != null){
                    res.close();
                }
                if (pre != null){
                    pre.close();
                }
                if (conn != null){
                    conn.close();
                }
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }

    }

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

    @Override
    public void destroy() {

    }
}
 <servlet>
        <servlet-name>Demo2</servlet-name>
        <servlet-class>servletimp.Demo2</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Demo2</servlet-name>
        <url-pattern>/demo2</url-pattern>
    </servlet-mapping>

GenericServlet:应用

package GenericServlet;

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

public class Gemo1 extends GenericServlet {
    /*
    重写无参的init方法,尽量不重写有参init,因为有限制,否则要加上this指向
     */

    @Override
    public void init() throws ServletException {
        super.init();
        System.out.println("重写无参的构造方法");
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        servletResponse.setContentType("text/html;charset=utf-8");

        //验证servletconfig能不能在service使用
        ServletContext servletContext = getServletContext();
        PrintWriter out = servletResponse.getWriter();
        out.write("GenericServlet      ");
        out.write(getServletContext().toString());

    }
}
<?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_4_0.xsd"
         version="4.0">

    <servlet>
        <servlet-name>Gemo1</servlet-name>
        <servlet-class>GenericServlet.Gemo1</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Gemo1</servlet-name>
        <url-pattern>/gemo1</url-pattern>
    </servlet-mapping>

</web-app>

获取全局变量:

package GenericServlet;

import javax.servlet.*;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;

public class Gemo2 extends GenericServlet {


    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {

        /*   获取全局环境变量 */

        ServletContext servletContext = getServletContext();
        Enumeration<String> initParameterNames = servletContext.getInitParameterNames();
        while (initParameterNames.hasMoreElements()){
            String key = initParameterNames.nextElement();
            String value = servletContext.getInitParameter(key);

            PrintWriter out = servletResponse.getWriter();
            out.write(key+"="+value);
            System.out.println(key+"="+value);
        }
    }
}
<?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_4_0.xsd"
         version="4.0">

<!--    全局环境变量-->
    <context-param>
        <param-name>username</param-name>
        <param-value>admin</param-value>
    </context-param>
    <context-param>
        <param-name>password</param-name>
        <param-value>123</param-value>
    </context-param>

    
    <servlet>
        <servlet-name>Gemo2</servlet-name>
        <servlet-class>GenericServlet.Gemo2</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Gemo2</servlet-name>
        <url-pattern>/gemo2</url-pattern>
    </servlet-mapping>
</web-app>

通过service方法设置全局变量(servletContext)

package GenericServlet;

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

public class setCon extends GenericServlet {

    //获取servletContext对象
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {

        //向应用域中存放数据
        ServletContext servletContext = getServletContext();

        //第一个参数:标识符,第二个参数:具体存放的数据:又见map
        servletContext.setAttribute("username","admin");

  System.out.println("在应用域中的数据:"+servletContext.getAttribute("username"));

    }
}


 

HttpServlet:应用

package GenericServlet;

import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;

@WebServlet(value = "/gemo3",initParams = {@WebInitParam(name = "username",value = "admin")})
public class Gemo3 extends HttpServlet {

    @Override
    public void init() throws ServletException {
        System.out.println("Gemo3被创建了");
        System.out.println(getServletConfig().getServletName());
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("执行了Servlet");

        Enumeration<String> initParameterNames = getServletConfig().getInitParameterNames();
        while (initParameterNames.hasMoreElements()){
            String key = initParameterNames.nextElement();
            String value = getServletConfig().getInitParameter(key);
            System.out.println(key+"="+value);
        }
    }

    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        super.service(req, res);
    }


}

十二、web欢迎页面

1.改变web欢迎页面

方式一:

在conf目录下web.xml文件中有配置web欢迎页面的规则

  //从下往下找,全局设置,不要改
  <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>

方式二:

在WEB-INF下的web.xml中配置,添加welcome-file-list

<!--    配置我们的欢迎页面-->
    <welcome-file-list>
<!--        不要以“/”开头-->
        <welcome-file>login.jsp</welcome-file>
    </welcome-file-list>

注意:局部和全局同名时,局部生效

十三、HttpServletRequst

1.是由谁创建的?

  • 是由tomcat容器创建的

2.httpServletRequest是用来做什么的?

  • 是一个请求对象,使用接收HTTP请求的,浏览器向服务器传输数据,tomcat会把数据封装到Request对象中。因为我们发送的数据满足HTTP协议。

3.封装的数据结构

如果你是tomcat开发人员你会采用什么样的数据结构来封装这些数据。

  • 使用map对数据进行封装,map<String,String[]>

4.如何获取request对象中的数据

//也是根据key获取value,返回的类类型是String,如果key对应的value是单个值,就获取到这个值,如果是多个值,就获取到第一个值   


1.String getParameter(String var1);
 

   //获取浏览器传过来的参数,最常用的方法
        String username = request.getParameter("username");
        System.out.println(username);
*********************


   
2.Enumeration<String> getParameterNames();

//通过key获取value,返回String类型的字符串


3.String[] getParameterValues(String var1);

  

 String[] hobbies = request.getParameterValues("hobby");
           for (String hobby:hobbies){
                      System.out.println(hobby);
          }、
//获取存放参数的map


4.Map<String, String[]> getParameterMap();

     

 Map<String, String[]> parameterMap = request.getParameterMap();
          parameterMap.forEach((k,v)-> System.out.println(k+"="+v[0]));
*********************   

5.数据格式:

map<key,value>,map<String,String[]> username=admin&password=123&hobby=xy&body=wd

面试题:补充快速异常和安全异常

问题:迭代器中删除元素,使用了list的remove方法报错

解决方法:使用迭代器的remove方法

解释:

6.request又叫请求域。

请求域中的生命周期。

一个service方法结束,请求域的生命周期就结束了。

一次请求结束,请求域的生命周期就结束了

通过向其中一个servlet的请求域中放数据,另一个servlet得不到数据,所以请求域不是全局的,一个servlet对应一个请求域。

通过内存地址可以验证

6.1往我们的请求域中添加数据api

//向请求域中存放数据
        request.setAttribute("username","admin");

        //获取请求域中的数据
        Object username = request.getAttribute("username");

        //设置返回数据的格式
        response.setContentType("text/html;charset=utf-8");

        //获取流对象,输出到页面上
        PrintWriter out = response.getWriter();
        out.write(request.toString());
//设置返回数据的格式
        response.setContentType("text/html;charset=utf-8");

        //获取流对象,输出到页面上
        PrintWriter out = response.getWriter();
        out.write(request.toString());

6.2关于request的其他api

 //其他qpi
        //获取虚拟地址,/day03_war_exploded
        String contextPath = request.getContextPath();
        System.out.println(contextPath);

        //获取请求方式,GET
        String method = request.getMethod();
        System.out.println(method);

        //获取url,url=http://localhost:8080/day03_war_exploded/c
        StringBuffer requestURL = request.getRequestURL();
        System.out.println("url="+requestURL);

        //获取uri,urI=/day03_war_exploded/c
        String requestURI = request.getRequestURI();
        System.out.println("urI="+requestURI);

7.不同的servlet共享数据怎么办

  • 把数据放在应用域中

  • 把数据放在请求域中,通过请求转发的方式让数据共享

方式1:通过请求转发的方式让数据共享

DServlet:

@WebServlet("/d")
public class DServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //向请求域中存放数据
        request.setAttribute("username","admin");

        //获取请求域中的数据
        String  username = (String) request.getAttribute("username");

        //请求转发
        // 到Eservlet,让EServlet使用到DServlet的请求对象
        //参数是我们想要去的地址
        //和@WebServlet("/路径")是一个地址。
        RequestDispatcher requestDispatcher = request.getRequestDispatcher("/e");
        //前往,把request和response传过去
        requestDispatcher.forward(request,response);

    }
EServlet:

@WebServlet("/e")
public class EServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        String username = (String) request.getAttribute("username");

        //设置返回数据的格式
        response.setContentType("text/html;charset=utf-8");

        //获取流对象,输出到页面上
        PrintWriter out = response.getWriter();
        if (username != null) {
            out.write(username);
        }
    }

十四、HttpServletResponse

常用api

1.设置返回数据的格式

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

2.获取流对象

//获取流对象
PrintWriter out = response.getWriter();

3.重定向,发送重定向

//重定向,发送重定向
        //参数表示我们要去往的地址,加上项目的虚拟地址
        response.sendRedirect(req.getContextPath()+"/main.jsp");

十五、请求转发和重定向的区别

1.地址栏的区别:

  • 请求转发不会导致地址栏发生变化

  • 重定向会导致地址栏发生变化

2.实质的区别:

  • 请求转发的资源跳转是在服务器之间进行资源跳转的

  • 重定向的资源跳转就是在浏览器和服务器之间

3.速度区别

  • 请求转发的速度比重定向的速度快

4.参数区别

  • 请求转发不需要到虚拟路径

  • 重定向需要虚拟路径

5.资源跳转 请求转发和重定向怎么选择

  • 什么时候使用请求转发

    • 如果是希望使用请求域中的数据可以选择请求转发

    • 对速度要求比较快的情况下可以使用请求转发,情况比较少

    • 请求转发存在的问题:

      • 如果不消息刷新了页面,可能会导致数据重复提交

  • 什么时候使用重定向

    • 除了请求转发的以上两种情况外都可以使用重定向

十六、session

1.session是什么

  • session是会话

  • 用户打开浏览器,发送一系列的请求。然后最后到关闭浏览器的过程,这个过程可以称为一次会话。

2.session的出现是为了解决什么问题?

  • 解决保持某种状态,保存我们的登录状态。(也就是说,访问其他的页面之前需要先判断是否登录了,做个登录的记录)

  • session的出现可以解决HTTP协议无状态的问题

  • session可以看作是一个令牌,到了某个地方,就可以获取令牌。从而证明来过此地

3.HTTP协议是无状态的。

  • 在发送一次请求后,浏览器和服务器的连接就断开了,服务器做的一系列的事情,浏览器都是不知道的,只有最后返回响应数据的时候,浏览器才知道做了什么。

4.HTTP协议无状态的原因

  • 这个时间点,同时有100W人访问了百度。100W个请求和服务器相连,导致服务器压力大,容易崩溃。

  • 减小服务器的压力

5.关于session获取的例子

@WebServlet("/s1")
public class SessionServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //获取session的api
        HttpSession session = request.getSession();

        //session是多个servlet共享的吗?结论:session是多个servlet共享的
        //session也是一个域对象,会话域。可以向会话域中添加数据
        session.setAttribute("username","admin");

    }
}
@WebServlet("/s2")
public class SessionServlet1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //获取session的api
        HttpSession session = request.getSession();

        //session是多个servlet共享的吗
        //从会话域中获取数据
        Object  username = session.getAttribute("username");
        System.out.println(username);

    }
}

6.应用域和会话域的区别

  1. 会话域的生命周期比较短,是在浏览器打开到关闭的过程中(简单理解)

  • 如果关闭浏览器再重新打开,想从应用域中获取这个数据可以获取到吗?

    • 在应用域中可以获取到这个数据。

  • 如果关闭浏览器再重新打开,想从会话域中获取这个数据可以获取到吗?

    • 在会话域中不可以获取这个数据,为null

    • 因为关闭浏览器的时候session对象被销毁了,重写打开浏览器又是新的session

运行时的地址

关闭浏览器重新打开的地址:

7.session的原理

8.做一个简易的登录拦截

目的:必须要先登录,才能进行数据添加。

9.sessio什么时候被销毁

  • 浏览器关闭的时候销毁

  • 如果很久不用到这个session,也会被销毁

    • 如何设置session存活时间

      • 在web.xml中可以或设置,单位是分钟

      • <!--    设置session存活时间-->
            <session-config>
        <!--        单位是分钟-->
                <session-timeout>60</session-timeout>
            </session-config>

10.总结一下写到的三个域

  • 应用域

  • 请求域

  • 会话域

  1. 大小关系

    • 请求域<会话域<应用域

  2. 用共同的api的

    • XX.setAttribute:向域中存放数据

    • XX.GetSttribute:从域中取数据

  3. 使用频率

    • 请求域>会话域>应用域

十七、cookie

1.cookie是什么

cookie:JSESSIONID=29AEFDCF8E95EA9943B644500006A28,username=admin,password=123

2.cookie是做什么的

和session一起保存某种状态

举例:

  • cookie充当会员卡;

  • session可以看作保险柜的密码;

  • JSESSIONID对应是哪个保险柜;

  • 29AEFDCF8E95EA9943B644500006A28对应的是保险柜的密码

3.如何获得cookie,如果向cookie中存数据

存入数据:

@WebServlet("/c1")
public class CookieServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //创建cookie
        Cookie cookie = new Cookie("username","admin");
        Cookie cookie1 = new Cookie("password","123");

        //将cookie放在响应对象中
        response.addCookie(cookie);
        response.addCookie(cookie1);

    }
}

取出数据:

@WebServlet("/c2")
public class CookieServlet1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取cookie
        Cookie[] cookies = request.getCookies();
        for (Cookie cookie:cookies){
            System.out.println(cookie.getName()+"="+cookie.getValue());
        }


    }
}

4.cookie可以保存在哪里

  • cookie可以保存在浏览器,但是浏览器关闭的时候cookie就消失

  • cookie可以保存在本地

    • 如何保存在本地

    • 使用setMaxAge()方法

    • //把cookie保存在本地,参数需要保存的时间,单位是秒,浏览器关闭的时候并没有销毁这个cookie‘
           //参数为正数的时候
      		cookie.setMaxAge(60*60);
      
          //参数为负数的时候,设置负数和不设置没有区别
              cookie.setMaxAge(-3600);
              
          //参数为0 的情况,为了去除同名的cookie
              cookie.setMaxAge(0);

十八、session和cookie的区别

  • 1.存储位置

    • session是存储在服务器中;底层是map

    • cookie是存储在浏览器中

  • 2.存储数据格式

    • session通过setAttibute()来存储任意数据

    • cookie是通过new Cookie()来存储数据,只能存储字符串

  • 3.安全性

    • session的安全性比cookie高,session是存储在服务器中的。

  • 4.存储个数

    • cookie的存储个数是有限制的,每个浏览器不一样

    • session的存储数量更多

十九、过滤器

1.过滤器是什么?

  • 饮水机过滤器

  • 空气净化器

2.servlet的过滤器

  • 登录过滤器

3.如何使用过滤器

  • 实现过滤器的步骤:

    • *  1.实现filter接口
      *  2.重写doFilter方法
      *  3.注册过滤器(@webFilter)

4.如何拦截请求?怎么设置拦截哪些请求

@WebFilter("/user/*")
public class AFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("A过滤器开始执行");
        //做逻辑判断
        //放行操作,走到下一个过滤器,如果没有过滤器就执行目标方法,就走到下一个方法
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("A过滤器执行结束");
    }
}

5.过滤器有哪些过滤路径

4种情况:

1.精准匹配,只可以过滤单个路径,/a.do

@WebFilter("/a.do")

2.后缀匹配,格式: .do ,.XXX

注意前面不要加/

@WebFilter("*.do")

3.前缀匹配,格式: /user/*

@WebFilter("/user/*")

4.全部匹配:/*

@WebFilter("/*")

6.过滤器的执行顺序

1.情况1

过滤器如果采用注解的方式进行注册,就会依据字典顺序,按拼音顺序

2.情况2

在web.xml中进行注册

过滤器执行的顺序就是注册的顺序

<!--测试过滤器B-->
<filter>
        <filter-name>BFilter</filter-name>
        <filter-class>filter.BFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>BFilter</filter-name>
        <url-pattern>*</url-pattern>
    </filter-mapping>

<!--测试过滤器A-->
<filter>
        <filter-name>AFilter</filter-name>
        <filter-class>filter.AFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>AFilter</filter-name>
        <url-pattern>*</url-pattern>
    </filter-mapping>

6.登录拦截

package filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/**
 * 做登录拦截
 *
 *什么资源进行放行?登录页面,成功登录后,发起请求的资源
 *登录请求
 *
 *什么资源要进行拦截?其他页面,没有登录成功后发起的资源
 */

@WebFilter("/*")
public class LoginFilter implements Filter {

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
       //登录页面的地址是怎么样的?
        //转换类型
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;


        //获取uri,放行登录页面、放行登录请求

        String uri = request.getRequestURI();
        //逻辑   获取虚拟路径/day03_war_exploded
        String contextPath = request.getContextPath();
        if ( (contextPath+"/login.jsp").equals(uri)|| (contextPath+"/").equals(uri) || (contextPath+"/login").equals(uri)){
            filterChain.doFilter(request,response);
            return;
        }



        //放行 成功登录后的页面
        HttpSession session = request.getSession();
        String ident = (String) session.getAttribute("login");
        if (ident != null){
            //说明登录过了,进行放行
            filterChain.doFilter(request,response);

        }else {
            //还未登录,跳转回登录页面
            //提示请先登录
            request.setAttribute("msg","请先登录");
            request.getRequestDispatcher("/login.jsp").forward(request,response);
        }
    }
}


二十、监听器

1.监听器的作用

监听一些行为和事件

2.servlet中的监听器

监听某些对象是否创建,是否销毁。有没有向域中放数据

3.监听器的种类(6种)

3.1 ServletContextListener

监听servletContext对象的创建和销毁的监听器

实现监听器的步骤:
*    1.实现对应的监听器接口ServletContextListener
*    2.根据需要重写方法
*    3.注册监听器 
@WebListener
public class ContextListener implements ServletContextListener {
    //此方法监听context对象什么时候被创建
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("Context对象被创建了");
    }
    //此方法监听context对象什么时候被销毁
    @Override
    public void contextDestroyed(ServletContextEvent sce) {

        System.out.println("Context对象被销毁了");

    }
}

3.2 HttpSessionListener

监听HttpSession对象的创建和销毁的监听器
实现监听器的步骤:
*    1.实现对应的监听器接口HttpSessionListener
*    2.根据需要重写方法
*    3.注册监听器
@WebListener
public class SessionLisstener  implements HttpSessionListener {
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        System.out.println("session对象被创建了");
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        System.out.println("session对象被销毁了");

    }
}

4.实现监听器的步骤

1.实现具体的监听器接口

2.选择重写的方法,如sessionCreated

3.注册监听器,@WebListener

5.练习

util.MySessioncontext:存储session

package listener;

import utils.MySessionContext;

import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

/**
 * 监听session什么时候被创建,创建好后,放在map中,
 */

@WebListener
public class SessionListener implements HttpSessionListener {

    //此方法表示监听session什么时候被创建
    //把session对象放在map中
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        //获取session对象
        HttpSession session = se.getSession();
        //把session放入map中
        //MySessionContext.getInstance();保存单例
        MySessionContext instance = MySessionContext.getInstance();
        instance.addSession(session);

    }
}

升级案例:解决cookie被禁用的问题

二十一、mvc的设计模式

1.在经典的mvc设计模式中,三层的意义

  • M表示业务模型

  • V表示视图模型

  • C表示控制层

2.分层有什么好处

  • 可以减少不同模块之间的依赖

  • 实现代码分离,解耦合

  • 利用排错

3.具体分层(3层)

  • 控制层Controller

    • 接收前端传输过来的数据

    • 返回数据给前端

    • 调用业务处理业务逻辑

  • 业务层Service

    • 处理业务逻辑*****

    • 调用持久层,查询数据

    • 返回数据到控制层

  • 持久层Mapping/Dao

    • 和数据库进行交互

    • 把结果返回给业务层

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值