Java Web

Servlet入门

1 Servlet介绍

1.1 什么是Servlet

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

1.2 Servlet的使用方法

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

1.3 Servlet接口的继承结构
  • Servlet接口:只负责定义Servlet程序的访问规范;

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

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

2 Servlet快速入门

2.1 创建javaweb项目
2.1.1 创建maven工程

在这里插入图片描述

2.1.2 添加webapp目录
  1. 右击项目,选择Add Frameworks Support
    在这里插入图片描述

  2. 选择Web Application,再点击OK

    在这里插入图片描述

  3. 将web目录拖拽到main目录下,并改名为webapp
    在这里插入图片描述

    • webapp:静态资源比如 html css js可以定义在web下面
    • WEB-INF:里面的资源不能直接被外界访问 web.xml 是web项目的核心配置文件
    • index.jsp:web项目的访问首页,在默认情况我们访问的首页就是index.jsp
2.2 添加依赖
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>servlet-api</artifactId>
    <version>2.5</version>
</dependency>
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() {

    }
}
2.3 配置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 {}
2.4 设置打包方式
  • 修改pom.xml
<!--打包方式-->
<packaging>war</packaging>
2.5 部署web项目
  1. 点击“Edit Configurations”

  1. 点击"+"

  1. 点击Tomcat Server中的Local
    在这里插入图片描述

  2. 配置Tomcat路径

在这里插入图片描述

  1. 部署web项目

在这里插入图片描述

  1. 启动tomcat

在这里插入图片描述

  1. 查看是否部署成功

在这里插入图片描述

2.6 测试

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

在这里插入图片描述

3 servlet的生命周期

3.1 什么是servlet的生命周期

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

对象的生命周期:

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

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

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

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

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

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

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.4 测试servlet的声明周期
public class LifeCycleServlet implements Servlet {

    public ServletDemo(){
        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接口的方式

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

@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 {
        //核心方法  类似于我们的doGet()方法,和doPost()方法 请求和响应
        //一定执行的
        System.out.println("service");
    }

    @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抽象类的方式

import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;
/*
* 第二种方式:继承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("我是第二种创建Servlet的方法");

    }
}

4.3 继承HttpServlet的方式

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

@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

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

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

5 Servlet获取前端提交的参数

学好Servlet必须紧紧围绕着请求和响应这两个概念
以上写的代码只是进行请求,然后再响应到客户端。请求的时候没有带数据给Servlet
下面开始写在请求的时候前端带数据到servlet里面,我们servlet要接收前端给我们的这个数据

  • login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
  <form action="user/login" method="post">
    <input type="text" name="username"/><br>
    <input type="text" name="password"/><br>
    <input type="submit" value="提交">
  </form>
  </body>
</html>
  • servlet实例
public class LoginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        request.setCharacterEncoding("utf-8");
		//html页面中  input标签发送的数据,都会存到HttpServlet这个对象里面
		//通过前端input标签name的属性值获取前端发送的数据
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        System.out.println("username: " + username+"===password"+password);
        
        //Servlet响应数据到客户端的时候,如果是中文的话,会乱码
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().write("username: " + user+"===password"+password);
    }
}
  • web.xml
    <servlet>
        <servlet-name>login</servlet-name>
        <servlet-class>com.by.servlet.LoginServlet</servlet-class>
    </servlet>

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

6 中文乱码的解决方案

请求时候的乱码问题:

//前端发送数据到Servlet,如果是post请求的话,input输入中文数据的时候,Servlet接到的数据是乱码的。
request.setCharacterEncoding("utf-8");

响应时候中文乱码的问题:

//Servlet响应数据到客户端的时候,如果是中文的话,会乱码
response.setContentType("text/html;charset=utf-8");

7 重定向和转发

web网站上面有一些跳转按钮。比如登录成功以后跳转到主页面!!!

7.1 重定向

  • 是什么

用户通过浏览器发送一个请求,Tomcat服务器接收这个请求,会给浏览器发送一个状态码302,并设置一个重定向的路径,浏览器如果接收到了这个302的状态码以后,就会去自动加载服务器设置的路径

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

  • 特征:

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

  • 重定向就一句核心代码:
response.sendRedirect("main.jsp"); //就这一行代码,但是这一行代码必须写在doGet或者doPost方法中
  • login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%--请求RedirectServlet--%>
<form action="redirect" method="post">
    <input type="text" name="username"/><br>
    <input type="text" name="password"/><br>
    <input type="submit" value="提交">
</form>
</body>
</html>
  • RedirectServlet
package com.by.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 RedirectServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置字符编码
        request.setCharacterEncoding("utf-8");

        String username = request.getParameter("username");
        String password = request.getParameter("password");
        request.setAttribute("username", username);
        request.setAttribute("password", password);

        //登录以后跳转到主页
        //重定向
        //这个TestLoginServlet里面的数据是不能传给target.html的
        response.sendRedirect("main.jsp");
    }
}
  • web.xml
    <servlet>
        <servlet-name>redirect</servlet-name>
        <servlet-class>com.by.servlet.RedirectServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>redirect</servlet-name>
        <url-pattern>/redirect</url-pattern>
    </servlet-mapping>
  • main.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
这是main页面<br>
<%--
<%=request.getAttribute("username")%>
<%=request.getAttribute("password")%>
--%>

${username}
${password}
</body>
</html>
  • 测试

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

7.2 转发

  • 是什么

用户发送数据请求到服务器,服务器接收当前请求,会调用内部方式(转发)处理该请求,最终把响应给客户端

  • 特征:

①转发是服务器的行为
②浏览器在这个过程中只有一次行为
③转发可以带有数据 request对象中
④url不会发生任何的变化

  • 核心代码也只有一行
request.getRequestDispatcher(“main.jsp”).forward(request,response);
//这一行代码就表示进行了转发,url没有变,但是响应的结果却是一次请求干了两个活
  • login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%--请求ForwardServlet--%>
<form action="forward" method="post">
    <input type="text" name="username"/><br>
    <input type="text" name="password"/><br>
    <input type="submit" value="提交">
</form>
</body>
</html>
  • ForwardServlet
package com.by.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 ForwardServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置字符编码
        request.setCharacterEncoding("utf-8");

        String username = request.getParameter("username");
        String password = request.getParameter("password");
        request.setAttribute("username", username);
        request.setAttribute("password", password);

        //登录以后跳转到主页
        //重定向
        //这个TestLoginServlet里面的数据是不能传给target.html的
        request.getRequestDispatcher("main.jsp").forward(request, response);
    }
}
  • web.xml
    <servlet>
        <servlet-name>forward</servlet-name>
        <servlet-class>com.by.servlet.ForwardServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>forward</servlet-name>
        <url-pattern>/forward</url-pattern>
    </servlet-mapping>
  • main.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
这是main页面<br>
${username}
${password}
</body>
</html>
  • 测试

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

8 Servlet的自动加载

默认情况下,第一次访问servlet的时候,创建servlet对象。如果servlet构造函数里面的代码或者init方法里面的代码比较多,就会导致用户第一次访问servlet的时候比较慢。这个时候,我们可以改变servlet对象的创建时机:提前到加载web应用的时候。在servlet的配置信息中,加上一个<load-on-startup>标签即可。

<servlet>
    <servlet-name>loadOnStartup</servlet-name>
    <servlet-class>com.by.servlet.LoadOnStartupServlet</servlet-class>
    <!--容器是否在启动时加载该servlet,数字越小优先级越高越高-->
    <load-on-startup>1</load-on-startup>
</servlet>

servlet实例:

public class LoadOnStartupServlet implements HttpServlet {
    public LoadOnStartupServlet(){
        System.out.println("LoadOnStartupServlet constructor method has run....");
    }
}

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

9 ServletConfig对象

  • 是什么

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

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

  • ServletConfig对象如何获取?

    在GenericServlet里面定义了:

public ServletConfig getServletConfig() {
    return this.config;
}
  • 常用方法
getInitParameter(String parameterName); //根据参数名称获取指定的参数值
getInitParameterNames(); //获取所有的参数名称
  • 需求:

获取servlet里面定义的参数

    <servlet>
        <servlet-name>demo2</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>demo2</servlet-name>
        <url-pattern>/demo2</url-pattern>
    </servlet-mapping>
package com.by.servlet;

import javax.servlet.*;
import javax.servlet.http.HttpServlet;

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");
        System.out.println(username);
        String password = servletConfig.getInitParameter("password");
        System.out.println(password);

        //3.获取ServletContext对象(域对象)
        ServletContext servletContext = servletConfig.getServletContext();
    }
}

思考:param参数可不可以在另外的Servlet中获取? 不能

public class ServletConfigServlet2 extends HttpServlet {

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

        //3.获取ServletContext对象(域对象)
        ServletContext servletContext = servletConfig.getServletContext();
    }
}

10 ServletContext对象

  • 是什么

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

    当服务器启动时,会为服务器中的每一个web应用程序创建一个ServletContext对象;

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

  • 如何获取这个对象:

public ServletContext getServletContext() {
    //获取ServletContext对象
    return this.getServletConfig().getServletContext();
}
  • 这个对象里面也有很多方法:
getInitParameter() //获取指定参数名称的全局参数值
getRealPath(String path) //获得当前项目的服务器磁盘路径
getContextPath() //获取项目的根路径
getAttribute(String parameterName) //获取ServletContext域中指定名称的参数值;
setAttribute(String paramterName,Object parameterValue) //存储参数到ServletContext域中;
removeAttribute(String parameterNam) //将ServletContext域中指定名称的参数移除;
  • 需求

获取servlet里面定义的参数

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

import javax.servlet.*;
import javax.servlet.http.HttpServlet;

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);
    }
}

思考:param参数可不可以在另外的Servlet中获取? 不能

package com.by.servlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;

public class ServletContextServlet2 extends HttpServlet {

    @Override
    public void doGet(ServletRequest servletRequest, 
                      ServletResponse servletResponse) throws ServletException {
        //从ServletContext域中取出msg的值
        ServletContext servletContext = getServletContext();
         //1.获取全局初始化参数
        String username = servletContext.getInitParameter("username");
        System.out.println(username);
        String password = servletContext.getInitParameter("password");
        System.out.println(password);
        
        //2.获得msg属性
        Object msg = servletContext.getAttribute("msg");//能获取
        System.out.println(msg);
    }
}
package com.by.servlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;

public class ServletContextServlet3 extends HttpServlet {

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException {
        //1.获取ServletContext对象
        ServletContext servletContext = getServletContext();
        //将ServletContext域中的msg参数移除
        servletContext.removeAttribute("msg");
    }
}
    <servlet>
        <servlet-name>context3=</servlet-name>
        <servlet-class>com.by.servlet.ServletContextServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>context3=</servlet-name>
        <url-pattern>/context=</url-pattern>
    </servlet-mapping>
    

    <servlet>
        <servlet-name>context2</servlet-name>
        <servlet-class>com.by.servlet.ServletContextServlet2</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>context2</servlet-name>
        <url-pattern>/context2</url-pattern>
    </servlet-mapping>
    

    <servlet>
        <servlet-name>context3</servlet-name>
        <servlet-class>com.by.servlet.ServletContextServlet3</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>context3</servlet-name>
        <url-pattern>/context3</url-pattern>
    </servlet-mapping>

11 Request对象

  • 是什么

ServletRequest是一个接口,用户访问服务器,服务器会生成一个对象包含了http所有请求头,由于使用的是http协议,所以该对象的名字叫HttpServletRequest

  • 常用的方法
getRequestURL() //获取的完整的URL,即统一资源定位符
getRequestURI() //获取资源的名字,即统一资源标识符
getQueryString() //获取一个url参数部分
getRemoteAddr() //返回的是客户端的ip地址
getRemoteUser() //返回的是客户端的用户
getRemotePort() //返回的是客户端的主机的端口号
getRemoteHost() //返回的是客户端的主机地址
getCookie() //获取Cookie对象
getSession() //获取Session对象
getLocalName() //获取Web服务器主机的名字
getServletContext() //获取上下文对象的
setCharacterEncoding() //设置编码集的
getParameter() //获取前端传过来的数据
setAttribute() //将数据设置给request对象
geAttribute() //获取request对象中的数据
  • servlet实例
package com.by.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 RequestServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, 
                          HttpServletResponse response) throws Exception {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, 
                         HttpServletResponse response) throws Exception{
        //获取一个完整的url
        //http://localhost:8080/01_servlet_HelloWorld_war/request1
        System.out.println(request.getRequestURL());
        //获取资源的名字
        //比如:http://localhost:8080/day42_xkh/request1
        System.out.println(request.getRequestURI());///01_servlet_HelloWorld_war/request1
        //获取一个url的参数部分
        //比如 http://localhost:8080/01_servlet_HelloWorld_war/request1?username=goudan
        System.out.println(request.getParameter("username"));

        //获取前端传送过来的数据
        request.setCharacterEncoding("utf-8");//设置请求的编码集
        //给request这个对象设置数据
        request.setAttribute("name","狗蛋");
        //获取request对象的值
        request.getAttribute("name");
        //获取上下文对象
        ServletContext servletContext = request.getServletContext();
        //转发
        request.getRequestDispatcher("target.jsp").forward(request,response);
    }
}
    <servlet>
        <servlet-name>request</servlet-name>
        <servlet-class>com.by.servlet.RequestServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>request</servlet-name>
        <url-pattern>/context</url-pattern>
    </servlet-mapping>

12 Response对象

  • 是什么

响应对象,把数据给客户端
我们的Servlet紧紧围绕着两个点(Request,Response)请求和响应

  • 常用方法
setHeader() //设置响应头的参数
setContentType() //设置字符编码集
getWriter() //获取字符输出流对象
addCookie() //对浏览器新增一个Cookie
sendRedirect() //重定向
  • servlet实例
package com.by.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 ResponseServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, 
                         HttpServletResponse response) throws Exception{
        /**************乱码问题*****/
        //方式一
        response.setCharacterEncoding("utf-8");//设置 HttpServletResponse使用utf-8编码
        response.setHeader("Content-Type", 
                           "text/html;charset=utf-8");//通知浏览器使用utf-8解码
        //方式二
        response.setContentType("text/html;charset=utf-8;aaa=bbb");    //包含方法一的两个功能

        //向客户端发送响应数据
        response.getWriter().write("<h1>hello<h1>");

        /************重定向***********/
        //方式一
        //在响应头中添加302状态码,告诉浏览器需要进行重定向
        response.setStatus(302);
        //在响应头中添加Location,指定重定向的位置
        response.setHeader("Location", "http://www.baidu.com");
        //方式二
        response.sendRedirect("http://www.baidu.com");  //包含方法一的两个功能
    }
}
    <servlet>
        <servlet-name>response</servlet-name>
        <servlet-class>com.by.servlet.ResponseServlet</servlet-class>
    </servlet>

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

13 Cookie和Session

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

13.1 cookie

  • 是什么
  1. 浏览器保存的内容,通常cookie是在浏览器中保存的,每一次访问服务器的时候,浏览器会自动的把cookie带到下一个页面的

  2. 如果想要使用cookie要保证我们的浏览器是开启cookie,所以说有一定的弊端,如果浏览器没有开启cookie,就不能再使用cookie了

  3. cookie的大小是有限制的,通常是4096byte

  4. cookie的保存是以键值对的形式存在的

  • 常用方法
//1.cookie的构造方法,目的是实例化出来cookie对象
Cookie(String name,String value)
//2.设置cookie的方法
setValue(String value) //修改cookie的值
setMaxAge(int time) //设置cookie的有效时间
setPath(String path) //设置当前cookie的有效路径
//3.要将cookie发送到浏览器
response.addCookie(Cookie cookie);
  • servlet实例一
package com.by.servlet;

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

public class SetCookieServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request,
    			HttpServletResponse response) throws Exception {
        /**
         * 1.创建cookie对象
         *     将键:java2311 值:sb ,存到cookie对象中
         */
        Cookie cookie = new Cookie("msg", "sb");
        /**
         * 2.设置有效时间
         *    正数:表示当前cookie的有效时间
         *    负数:表示当前浏览器打开的时候存在,关闭的时候没了
         *     0:销毁当前的cookie
         */
        cookie.setMaxAge(60*60*24);//设置了有效期是个正数,
        //3.把cookie发送到浏览器
        response.addCookie(cookie);
    }
}
    <servlet>
        <servlet-name>setCookie</servlet-name>
        <servlet-class>com.by.servlet.SetCookieServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>setCookie</servlet-name>
        <url-pattern>/setCookie</url-pattern>
    </servlet-mapping>
  • servlet实例二
package com.by.servlet;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class GetCookieServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) {
        //获取浏览器中cookie,返回值是一个数组
        Cookie[] cookies = request.getCookies();
        for (Cookie cookie : cookies) {
            System.out.println("==============");
            System.out.println(cookie.getName());//获取键
            System.out.println(cookie.getValue());//获取值
        }
    }
}
    <servlet>
        <servlet-name>getCookie</servlet-name>
        <servlet-class>com.by.servlet.GetCookieServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>getCookie</servlet-name>
        <url-pattern>/getCookie</url-pattern>
    </servlet-mapping>
  • 实例三
@WebServlet("/destroyCookie")
public class DestroyCookieServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) {
        //退出登录
        Cookie[] cookies = request.getCookies();
        for (Cookie cookie : cookies) {
            if (cookie.getName().equals("msg")){
                cookie.setMaxAge(0);//销毁cookie
                //重新发送给浏览器
                response.addCookie(cookie);
            }
        }
    }
}
    <servlet>
        <servlet-name>destroyCookie</servlet-name>
        <servlet-class>com.by.servlet.DestroyCookieServlet</servlet-class>
    </servlet>

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

13.2 session

  • 为什么使用session?
  1. cookie保存数据类型是单一的,只能保存字符串类型的数据
  2. cookie的大小由限制
  • 是什么?
  1. 保存服务器中,每一个session在我们当前的服务器会有一个标识号

  2. 使用session的时候一般要开启cookie如果浏览器没有开启cookie功能,我们可以通过html的url传参完后session的使用

  3. 没有大小的限制

  4. 信息的保存也是以键值对的形式存在的

  • 实例一
package com.by.servlet;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.Date;

public class SetSessionServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response){
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) {
        //1.获取session对象
        HttpSession session = request.getSession();
        System.out.println(session);
        //获取的是JSESSIONID 服务器唯一的标识
        System.out.println(session.getId());
        //给session设置一个时间,有效果的,里面放的是秒
        session.setMaxInactiveInterval(60*60*24);

        User user = new User();
        user.setUsername("张5丰");
        user.setBirthday(new Date());
        user.setSex("1");
        session.setAttribute("user",user);
    }
}
    <servlet>
        <servlet-name>setSession</servlet-name>
        <servlet-class>com.by.servlet.SetSessionServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>setSession</servlet-name>
        <url-pattern>/setSession</url-pattern>
    </servlet-mapping>
  • 实例二
package com.by.servlet;

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

public class GetSessionServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response){
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) {
        //1.获取Session对象
        //第一次创建session的时候默认为true
        //false的话,这个session使用的是已经创建好的session对象
        HttpSession session = request.getSession(false);
        //2.获取session,通过键取值
        Object user = session.getAttribute("user");
        System.out.println(user);
    }
}
    <servlet>
        <servlet-name>getSession</servlet-name>
        <servlet-class>com.by.servlet.GetSessionServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>getSession</servlet-name>
        <url-pattern>/getSession</url-pattern>
    </servlet-mapping>
  • 实例三
package com.by.servlet;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class DestroySessionServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response)  {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response)  {
        //1.获取session对象
        HttpSession session = request.getSession(false);
        //销毁当前的session
        session.invalidate();
    }
}
    <servlet>
        <servlet-name>destroySession</servlet-name>
        <servlet-class>com.by.servlet.DestroySessionServlet</servlet-class>
    </servlet>

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

14 过滤器和监听器

14.1 过滤器

  • 什么是过滤器

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

  • 过滤器执行流程

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • Filter实例
package com.by.servlet;

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

public class FilterDemo implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    //真正执行过滤业务的方法
    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain filterChain) throws ServletException, IOException {
        //获取前端传送过来的数据
        request.setCharacterEncoding("utf-8");//设置请求的编码格式
        response.setContentType("text/html;charset=utf-8"); //设置相应的编码格式
        
        System.out.println("请求进来,经过过滤器...");
        //一个web路径,可以配置多个过滤器,这多个过滤器就被称为过滤器链
        filterChain.doFilter(request,response);
        System.out.println("相应返回,经过过滤器...");
    }

    @Override
    public void destroy() {

    }
}
  • 使用过滤器需要注意的事项:

1.过滤器必须实现Filter接口。

2.过滤器拦截的请求执行完毕之后,必须要放行,否则我们的请求就不会被执行。

 filterChain.doFilter(request,response); //过滤器放行

3.我们可以使用@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.后缀名拦截:*.jsp 访问后缀名为jsp的资源,都会被拦截

4.拦截所有:/* 访问所有的资源,都会被拦截

  • 测试

1.创建servlet

package com.by.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 FilterTestServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置字符编码
        //request.setCharacterEncoding("utf-8");

        String username = request.getParameter("username");
        String password = request.getParameter("password");
        System.out.println("username: " + username+"===password"+password);

        //设置字符编码
        //response.setContentType("text/html;charset=utf-8");

        response.getWriter().write("username: " + username+"===password"+password);
    }
}

2.配置servlet

    <servlet>
        <servlet-name>filterTest</servlet-name>
        <servlet-class>com.by.servlet.FilterTestServlet</servlet-class>
    </servlet>

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

3.创建filter_test.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<form action="filterTest" method="post">
    <input type="text" name="username"/><br>
    <input type="text" name="password"/><br>
    <input type="submit" value="提交">
</form>
</body>
</html>

14.2 监听器

  • 是什么?

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

  • Listener分类:Javaweb提供了8个监听器(接口)
    在这里插入图片描述

  • listen实例

package com.by.servlet;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class MyListener implements ServletContextListener {

    //监听Servlet上下文对象创建的方法
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        System.out.println("============tomcat启动(create servletContext)========");
    }

    //监听Servlet上下文对象销毁的方法
    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        System.out.println("============tomcat关闭(destroyed servletContext)==========");
    }
}
    <!--配置监听器-->
    <listener>
        <listener-class>com.by.listen.MyListener</listener-class>
    </listener>

15 web三层架构

分层的目的是为了解耦。解耦就是为了降低代码的耦合度。方便项目后期的维护和升级。

  • web层

    com.by.web/servlet/controller:servlet包

  • service 层

    com.by.service:Service接口包

    com.by.service.impl:Service接口实现类

  • dao 持久层

    com.by.dao:Dao接口包

-mapping>
filterTest
/filterTest


3.创建filter_test.jsp

```jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<form action="filterTest" method="post">
    <input type="text" name="username"/><br>
    <input type="text" name="password"/><br>
    <input type="submit" value="提交">
</form>
</body>
</html>

14.2 监听器

  • 是什么?

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

  • Listener分类:Javaweb提供了8个监听器(接口)

[外链图片转存中…(img-xYGbxh9a-1703592679782)]

  • listen实例
package com.by.servlet;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class MyListener implements ServletContextListener {

    //监听Servlet上下文对象创建的方法
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        System.out.println("============tomcat启动(create servletContext)========");
    }

    //监听Servlet上下文对象销毁的方法
    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        System.out.println("============tomcat关闭(destroyed servletContext)==========");
    }
}
    <!--配置监听器-->
    <listener>
        <listener-class>com.by.listen.MyListener</listener-class>
    </listener>

15 web三层架构

[外链图片转存中...(img-R1UFDrZB-1703592679783)].png)

分层的目的是为了解耦。解耦就是为了降低代码的耦合度。方便项目后期的维护和升级。

  • web层

    com.by.web/servlet/controller:servlet包

  • service 层

    com.by.service:Service接口包

    com.by.service.impl:Service接口实现类

  • dao 持久层

    com.by.dao:Dao接口包

    com.by.dao.impl: Dao接口实现类

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值