Servlet的详细教程


一、Servlet的简介

Servlet ===>server applet
java服务器的小程序,是javaweb非常重要的环节。主要作用是完成html和java后台代码的交互(请求 《=》响应)
servlet是需要运行在Java服务器(Tomcat)中的,符合http协议的servlet的核心类接口的

javax.servlet和javax.servlet.http
javax.servlet.ServerException
javax.servlet.http.HttpServlet
javax.servlet.http.HttpServletRequest
javax.servlet.http.HttpServletResponse
javax.servlet.http.Session
javax.servlet.http.Cookie

二、Servlet的入门案例

代码如下(示例):

package com.qfedu.a_servelt;

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(name = "HelloServlet")
 *
 * 告诉服务器这个是我的servlet
 * @webServlet  是我们请求servlet的入口
 *  把name去掉 然后加一个斜线,如果这个斜线没有带会报错 404
 * 请求这个servlet这个资源的时候
 * url : http://localhost:8080/day39_xkh/HelloServlet
 * */
@WebServlet("/HelloServlet")//这个是注解,是修饰下面的HelloServlet
//如果想要初始化这个类,必须写这个入口
public class HelloServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //我不管你的请求方式是get还是post请求
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置网页字符编码集
        response.setContentType("text/html;charset=utf-8");
        //请求和响应PrintWriter  打印写入  这种写法会在浏览器中显示出来
        response.getWriter().append("我的第一个web程序");
        System.out.println("hello,world");
    }
}



结果如下(示例):
在这里插入图片描述
红色的是日志信息
在这里插入图片描述

三、创建Servlet的三种方式

①实现Servlet接口的方式

① 返回值:void 方法名: init(ServletConfig servletConfig)throws ServletException : 使用ServletConfig对象初始化我们的Servlet ,这个方法执行
②返回值:ServletConfig 方法名: getServletConfig() :获取配置信息对象的方法,这个方法不执行
③void service(ServletRequest servletRequest,ServletResponse servletResponse) throws ServletException,IOException :核心方法,这个里面类似于我们的doget方法和dopost方法,这个方法一定执行
④String getServlrtInfo() :获取Servlet详细信息的方法,不执行
⑤void destory() : 在tomcat关闭的时候,进行销毁这个servlet,只有在tomcat关闭的时候执行

init(ServletConfig servletConfig)throws ServletException : 使用ServletConfig对象初始化我们的Servlet ,这个方法执行
getServletConfig() :获取配置信息对象的方法,这个方法不执行
service(ServletRequest servletRequest,ServletResponse servletResponse) throws ServletException,IOException :核心方法,这个里面类似于我们的doget方法和dopost方法,这个方法一定执行
getServlrtInfo() :获取Servlet详细信息的方法,不执行
destory() : 在tomcat关闭的时候,进行销毁这个servlet,只有在tomcat关闭的时候执行

②继承GenericServlet抽象类

service(ServletRequest servletRequest,ServletReponse servletresponse)throws ServletException,IOException

③继承HttpServlet抽象类

3.1实现Servlet接口的方式

代码如下(示例):

package com.qfedu.a_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关闭的时候,才会执行这个方法
        
    }
}

结果如下(示例):
在这里插入图片描述

在这里插入图片描述

3.2继承GenericServlet抽象类的方式

代码如下(示例):

package com.qfedu.a_servlet;

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的方法");

    }
}

结果如下(示例):
在这里插入图片描述

3.3继承HttpServlet的方式

代码如下(示例):

package com.qfedu.a_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 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

四、Servlet注解和配置文件的写法

1.上面采用的都是注解的写法,对Servlet的版本有要求,servlet3.0及以上的版本才可以使用注解
2.还有一种写法是配置文件的写法。对文件没有要求

4.1配置文件的写法

① 需要在web.xml文件写配置
web.xml文件代码如下
代码如下(示例):

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

<!--    servlet配置文件的写法-->
    <servlet>
        <display-name>WebXMLServlet</display-name>
<!--     servlet-name要和servlet-mapping所对应,映射的关系-->
        <servlet-name>WebXMLServlet</servlet-name>
<!--      servlet-class 是servlet所对应的类-->
        <servlet-class>com.qfedu.b_servlet.WebXMLServlet</servlet-class>
<!--      只要tomcat服务器一启动就会加载这个类-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>WebXMLServlet</servlet-name>
        <url-pattern>/Webxml.do</url-pattern>
    </servlet-mapping>
</web-app>

java代码:
代码如下(示例):

package com.qfedu.b_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 WebXMLServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置网页的编码格式
        resp.setContentType("text/html;charset=utf-8");
        resp.getWriter().append("我这个是配置文件的写法");
    }
}

结果如下(示例):
在这里插入图片描述

4.2注解的写法

代码如下(示例):

package com.qfedu.b_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 java.io.IOException;
/**
 * name是Servlet的名字  对应配置文件中的servlet-name
 * value 是servlet程序对应的url  只能写一个
 * loadOnStartup  tomcat启动的时候会不会自动加载这个servlet类
 *                  默认为 -1 (不加载)   1(自动加载)
 * urlPatterns对应配置文件中的url-pattern  可以写多个url,都可以访问
 *
 * */
@WebServlet(name = "AnnotionServlet",urlPatterns = {"/as","/as.do","/as.action"},loadOnStartup = 1)
public class AnnotionServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("这个是注解的写法");
        //设置网页的编码格式
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().append(
                "<div style=\"width: 300px;height: 200px;background-color: red\"><font style=\"color: blue;font-size: 30px\">仰天大笑出门去</font></div>");
        response.getWriter().append("<br><font style='color: red;font-size: 30px'>我辈岂是蓬蒿人</font>");
    }

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


结果如下(示例):
在这里插入图片描述
【注意事项】:每一个servlet的名字(注解中的name属性或配置文件的servlet-name标签)都是唯一的,不同的servlet对象的名字不能相同,如果相同,访问的时候会报404的错误
前提:配置文件的写法的servlet-name和注解写法的name属性相同
在这里插入图片描述
在这里插入图片描述

结果:
在这里插入图片描述

五、Servlet的生命周期

在这里插入图片描述
详情请看:http://www.51gjie.com/javaweb/847.html

整个servlet在执行的过程中

1.constructor
2.init
3.service
4.destroy
阶段1:
servlet整个类对象进行实例化(在tomcat服务器中),提供给tomcat使用
阶段2:
servlet类对象的初始化
阶段3:
servlet对外提供服务,相当于我们的doGet和doPost
阶段4:
servlet进行销毁,可以主动申请关闭servlet,但是一般tomcat一关闭,servlet就自动销毁了

代码如下(示例):

package com.qfedu.b_servlet;

import javax.servlet.ServletConfig;
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;
//loadOnStartup  tomcat启动的时候是否会自动加载这个servlet这个实体类,1代表自动加载,-1不会自动加载(默认)
@WebServlet(value = "/life.do" , loadOnStartup = 1)
public class LifeCycleServlet extends HttpServlet {

    public LifeCycleServlet(){
        System.out.println("我是LifeCycleServlet的无参构造方法在执行");
    }

    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        System.out.println("init方法进行初始化servlet类对象");
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        resp.getWriter().append("service在对外提供服务");
        System.out.println("service在对外提供服务");

    }

    @Override
    public void destroy() {
        System.out.println("destroy在执行servlet的销毁");
    }
}

结果如下(示例):

前提:我把loadOnStartup的值设置为1(看上面的代码),就是tomcat一启动,servlet就会被加载
刚启动的时候
construct构造方法就已经执行
init初始化这个servlet类对象已经执行
在这里插入图片描述

html页面对servlet发出请求

在这里插入图片描述
servlet开始响应
service方法开始执行
在这里插入图片描述
关闭程序,tomcat关闭
destroy方法开始执行
在这里插入图片描述

六、Servlet获取前端请求的参数

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

第一步写一个html前端页面,在web文件夹中直接创建一个html,名字叫做Login
在这里插入图片描述

代码如下(示例):

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="LoginServlet" method="get">
        姓名:<input type="text" name="user" /><br>
        密码:<input type="password" name="password" /><br>
        <input type="submit" value="登录">
    </form>
</body>
</html>

第二步创建一个Servlet类
在这里插入图片描述

代码如下(示例):

package com.qfedu.c_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 java.io.IOException;

@WebServlet("/LoginServlet")
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 {
        /*
        * html页面中  input标签发送的数据,都会存到HttpServlet这个对象里面
        * 通过这个对象获取input输入框中的值user 是input标签中name属性的属性值
        * */
        *//这个getParameter方法就是获取请求对象的参数的,通过前端input标签name的属性值获取的
        //获取前端的数据,要注意中文乱码,当是post请求的时候,会出现乱码
        //设置字符编码
        request.setCharacterEncoding("utf-8");


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

    }
}

结果如下(示例):

首先启动服务器,然后在url后面输入Login.html
进入登录页面,输入账号和密码(谁便写)
在这里插入图片描述
点击登录
在这里插入图片描述
结果:
在这里插入图片描述

七、通过前端发送数据到servlet,然后存入到数据库

类似于注册功能

1.先写一个html页面,主要发送数据给Servlet
2.写一个RegisterServlet,这个Servlet的目的获取前端传过来的数据
3.我们想办法把获取的数据存入到数据库
4.封装的JDBCUtil和BaseDao这里可以拿来使用,使用c3p0连接池还是druid连接池
5.复制粘贴过来
6.我想使用这个BaseDao这个类方法update
7.需要再写一个类去继承BaseDao,这个类(UserDao)是专门写sql处理的相关的类
8.在Servlet里面实例化UserDao调用UserDao下面的方法即可。

①先写一个注册页面register.html
代码如下(示例):

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--提交到一个Servlet中不用带斜线-->
<!--如果是get请求,给Servlet的时候中文不会乱码
    但是是post请求的时候,中文会乱码
-->
    <form action="RegisterServlet" method="post">
        姓名:<input type="text" name="user"><br>
        密码:<input type="password" name="password"><br>
        <input type="submit" value="注册">
    </form>
</body>
</html>

②再写一个UserDaot类去继承我们封装的BaseDao
代码如下(示例):

package com.qfedu.a_servlet;

import com.qfedu.util.BaseDao;

import java.sql.SQLException;

//采用MVC的架构思想
//dao层都是写sql处理增删改查的
public class UserDao extends BaseDao {
    
    public int addUser(Object[] objs) throws SQLException {
        String sql = "insert into user(name,password) values(?,?)";
        return super.update(sql,objs);
    }
}

③写一个RegisterServlet类继承HttpServlet类
代码如下(示例):

package com.qfedu.a_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 java.io.IOException;
import java.sql.SQLException;

@WebServlet("/RegisterServlet")
public class RegisterServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取前端传过来的数据
        //因为采取的是post请求,所以首先更改编码格式
        req.setCharacterEncoding("utf-8");
        String user = req.getParameter("user");
        String password = req.getParameter("password");

        //现在拿到了user,和password,把这两个数据存到数据库中
        //BaseDao baseDao = new BaseDao();
        //准备一个sql语句,还有准备参数,参数是一个吧数组
        //一般Servlet里面不让写sql语句 怎么办?这个确实能实现数据库数据的添加n
        //但是不规范,sql单独放在另外一个类中

//        String sql = "insert into user(name, password) values(?,?)";
//        Object[] objs = {user, password};
//        try {
//            baseDao.update(sql, objs);
//        } catch (SQLException e) {
//            e.printStackTrace();
//        }
        
        //把sql语句写在了另外一个类中
        UserDao userDao = new UserDao();
        Object[] objs = {user,password};
        try {
            userDao.addUser(objs);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

④在java2109这个数据库中建一个user表
在这里插入图片描述

结果如下(示例):
第一步先启动程序,在url后面输入register.html,进入注册页面
在这里插入图片描述
输入姓名和密码,谁便输,点击注册
页面跳转到RegisterSevlet页面
在这里插入图片描述
打开数据库,查看user数据表
此时前端发送的数据就存入到数据库中了
在这里插入图片描述

八、中文乱码的解决方案

请求时候的乱码问题:

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

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

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

九、重定向和转发【重要】

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

9.1重定向

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

一个页面跳转到另外一个页面(应用场景)、登录页面跳转到主页面
denglu.html====>TestLoginServlet====>target.html

特征:
①重定向的过程是浏览器(客户端)的行为
②实际上浏览器做了2次请求(当点击登录按钮的时候做了两次请求)(分别是请求TestLoginServlet和target.html)
③注意上一次请求的request对象会丢失
④重定向有一个非常明显的特征,即浏览器的url变化了
⑤重定向可以重定向到网络的任意资源(比如京东淘宝等资源)

重定向就一句核心代码:
response.sendRedirect(“target.html”);就这一行代码,但是这一行代码必须写在doGet或者doPost方法中

1.先写一个登录页面,denglu.html
代码如下(示例):

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="TestLoginServlet" method="post">
        姓名:<input type="text" name="user"><br>
        密码:<input type="password" name="password"><br>
        <input type="submit" value="登录">
    </form>
</body>
</html>

2.写一个重定向的目标页面target.html
代码如下(示例):

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    我是主页
</body>
</html>

3.写Servlet类TestLoginServlet.java
代码如下(示例):

package com.qfedu.b_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 TestLoginServlet extends HttpServlet {

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置编码,因为前端页面采用的是post请求
        req.setCharacterEncoding("utf-8");

        //获取前端发送过来的数据
        String user = req.getParameter("user");
        String password = req.getParameter("password");

        //登录以后跳转到主页
        //重定向
        //这个TestLoginServlet里面的数据是不能传给target.html的
        resp.sendRedirect("target.html");

    }
}

结果如下(示例):
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
url发生了变化

9.2转发

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

特征:
①转发是服务器的行为
②浏览器在这个过程中只有一次行为
③转发可以带有数据 request对象中
④url不会发生任何的变化
⑤转发只能在当前项目中进行转发,不能转发外部资源

核心代码也只有一行

request.getRequestDispatcher(“TestServlet2”).forward(request,response);
这一行代码就表示进行了转发,url没有变,但是响应的结果却是另外一个Servlet里卖的东西
一次请求干了两个活

1.创建一个Servlet类,TestServlet1.java
代码如下(示例):

package com.qfedu.b_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 java.io.IOException;

@WebServlet("/TestServlet1")
public class TestServlet1 extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req,resp);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("用户请求TestServlet1");
        //给当前的request对象设置一些数据,request对象带有数据
        //name = 猪肉形
        req.setAttribute("name","猪肉邢");
        /**
         * 可以通过request对象转发到其它资源(另外一个Servlet)里面
         * */
        //转发会将一个servlet里面数据带到另外一个Servlet里面
        req.getRequestDispatcher("TestServlet2").forward(req,resp);
    }
}

2.创建第二个Servlet类,TestServlet2.java
代码如下(示例):

package com.qfedu.b_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 java.io.IOException;

@WebServlet("/TestServlet2")
public class TestServlet2 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 {
        //TestServlet1里面转发过来的数据
        Object name = request.getAttribute("name");
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().append("这个是转发到TestServlet2里面的name值:" + name);
    }
}

在弹出的网页中的url后面输入目标资源TestServlet1,点击回车键
结果如下(示例):
在这里插入图片描述

十、URL匹配规则

@WebServlet(“/test”) 中/test就是我们某一个资源的路径的写法
用户申请了一个资源:http://localhost:8080/day41_xkh/LoginServlet
①http协议
②localhost本地服务器主机的名字
③8080端口号
④day_xkh/LoginServlet是我们所申请的资源
day_xkh/当前应用程序目录,就是程序的绝对路径
LoginServlet申请的资源
URL匹配原则:
1.精准匹配
比如 /资源名字@WebServlet(“test/do”)
2.模糊匹配
在这里插入图片描述
精准匹配:
代码如下(示例):

package com.qfedu.a_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 java.io.IOException;

//精准匹配,通过你写的@WebServlet真实的值,去找到你所对应的资源
@WebServlet("/testServlet1")
public class TestServlet1 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 {
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().append("这个是精准匹配");
    }
}

结果如下(示例):
在这里插入图片描述

模糊匹配:
第一种 以.do后缀的模糊匹配

代码如下(示例):

package com.qfedu.a_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 java.io.IOException;

//这个模糊匹配是以后缀是.do的资源
//进行匹配的时候在web应用程序下面,.do以前可以随意的填写,这样就可以找到这个资源了
//比如:
//注意*前面没有加斜线
//@WebServlet("*.do")
public class TestServlet2 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 {
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().append("这个是模糊匹配的一种,以.do后缀的匹配");
    }
}

结果如下(示例):
注意我的url中day42_xkh后面随便写的,最后是以.do结尾的就行

在这里插入图片描述

模糊匹配的另外一种写法,就是在/后面随意写就可以了!!!
//以后会用,在将过滤器的时候使用。

代码如下(示例):

package com.qfedu.a_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 java.io.IOException;

@WebServlet("/*")
public class TestServlet3 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 {
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().append("我这个是随意的资源访问五,url不管写什么都可以匹配到");
    }
}

结果如下(示例):
在这里插入图片描述

十一、ServletContext【重要】

ServletContext接口,实例化以后是一个对象,是我们当前应用程序可以使用的唯一对象
在一个Servlet里面,使用另外一个Servlet里提供的数据,怎么办?转发,但是不用转发怎么办?需要使用ServletContext对象,是全局的。比如,你在一个Servlet里面设置一个数据,想要在另外一个Servlet里面使用这个数据,没办法。但是可以通过ServletContext这个接口,这个对象是全局的。如果你在一个Servlet里面使用Servlet里面使用ServletContext对象设置一个数据,在另外一个Servlet里面也可以通过Servlet里面也可以通过ServletContext这个对象获取这个数据

两个Servlet依靠ServletContext对象进行通信,分享一些数据

代码如下(示例):

Servlet对象1

package com.qfedu.b_servletContext;

import javax.servlet.ServletContext;
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("/context1.do")
public class ContextServlet1 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 {
        //要使用一个对象,这个对象可以实现Servlet之间的共享数据
        //1.获取servletContext对象即当前上下文对象 request.getServletContext()
        ServletContext servletContext = request.getServletContext();

        //2.给当前上下文对象设置一部分数据 setAttribute("键","值")
        servletContext.setAttribute("msg","我是context1对象");
        servletContext.setAttribute("person",new Person("张三",32));

        //返回当前Servlet的详细信息  getServletInfo()
        String serverInfo = servletContext.getServerInfo();

        //返回项目的根目录(以后出现404可以先找这个根目录然后再一点一点的找)
        //servletContext.getContextPath()
        String contextPath = servletContext.getContextPath();

        System.out.println(serverInfo);
        System.out.println(contextPath);

    }
}

Person类:

package com.qfedu.b_servletContext;

public class Person {
    private String name;
    private int age;

    public Person(){

    }
    public Person(String name,int age){
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

Servlet对象2

package com.qfedu.b_servletContext;

import javax.servlet.ServletContext;
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("/context2.do")
public class ContextServlet2 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 {
        response.setContentType("text/html;charset=utf-8");//处理响应时候乱码的问题
        //这个Servlet是获取当前上下文对象存放的数据
        //1.获取当前上下文对象
        ServletContext servletContext = request.getServletContext();
        Object msg = servletContext.getAttribute("msg");
        System.out.println(msg);

        Person person = (Person) servletContext.getAttribute("person");
        System.out.println(person);
        response.getWriter().append(" "+msg);

    }
}

结果如下(示例):
在这里插入图片描述
在这里插入图片描述

十二、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对象中的数据

代码如下(示例):

package com.qfedu.c_request;

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("/request1")
public class RequestServlet1 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 {
        //获取一个完整的url
        System.out.println(request.getRequestURL());//http://localhost:8080/day42_xkh/request1
        //获取资源的名字
        //比如:http://localhost:8080/day42_xkh/request1
        System.out.println(request.getRequestURI());//day42_xkh/request1
        //获取一个url的参数部分
        //比如 http://localhost:8080/day42_xkh/request1?user=goudan&password=123456
        System.out.println(request.getQueryString());

    }
}

结果如下(示例):
在这里插入图片描述
在这里插入图片描述

代码如下(示例):

package com.qfedu.c_request;

import javax.servlet.ServletContext;
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("/request2")
public class RequestServlet2 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 {
        //获取客户端的ip地址
        System.out.println(request.getRemoteAddr());
        //获取客户端的主机地址
        System.out.println(request.getRemoteHost());
        //获取客户端的用户
        System.out.println(request.getRemoteUser());
        //获取客户端的主机的端口号
        System.out.println(request.getRemotePort());
        //以上代码如果你们在同一个网段是可以测试的
        //写完这个代码以后,你把ip地址告诉你室友,让他去访问你写的这个资源
        //http://10.8.199:8080/day41_wb/request2
        //发现打印的都是别人访问的东西。意味着从这地方知道,
        //你想黑军方的网站,是不可能,你在哪都能找到你,让后关起来,审判,枪毙
        //以后开发必用的!!!是以下的方法

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

结果如下(示例):

在这里插入图片描述

十三、Response对象

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

setHeader();设置响应头的参数
setContentType();设置字符编码集
getWriter();获取字符输出流对象
addCookie();对浏览器新增一个Cookie
sendRedirect();重定向

十四、Cookie和Session

http是一种无状态的访问
浏览器发送请求到服务器,服务器给与一定的响应,但是断开连接以后,如果服务器没有发送任何请求,是没有任何响应的
这个就是无状态的访问:
实际操作中存在一定的问题:
比如登录一个网站以后,再次跳转到这个网站的其它页面,他是不会保存第一个页面的状态的,这叫无状态的。
登录一个页面的话,他不会保证上一页面的状态,如何来保持上一个页面的状态的呢?靠下面将要讲的会话技术(Cookie和Session),才能保持上一个页面的状态!!
如果没有cookie和session的话,http协议是一个无状态的协议,你每一个跳转到下一个页面的时候都是需要先登录才能使用,这样就很麻烦

比如淘宝(没有cookie和session的话),登录上去了,(需要登录才能)选择商品,(需要登录才能)放到购物车,(需要登录才能)然后购买,这样用户的体验是相当差的然后才有咱们即将要讲的会话控制。会话控制的目的就是为了点击页面的时候,保持上面一个页面的状态

14.1会话技术

Cookie:

浏览器保存的内容,通常cookie是在浏览器中保存的,每一次访问服务器的时候,浏览器会自动的把cookie带到下一个页面的
cookie的大小是有限制的,通常是4096byte
cookie信息中不能有中文
cookie的保存是以键值对的形式存在的

Session:

保存服务器中,每一个session在我们当前的服务器会有一个标识号
会保存浏览器访问服务器的一些记录信息,没有大小的限制
可以保存中文
信息的保存也是以键值对的形式存在的

14.2Cookie

如果想要使用cookie要保证我们的浏览器是开启cookie,所以说有一定的弊端,如果浏览器关了,关了就不能再使用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);

先给浏览器设置cookie,获取cookie,销毁cookie,获取cookie,销毁cookie
设置cookie

package com.qfedu.d_cookie;

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;

@WebServlet("/cookie")
public class CookieServlet 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 {
        //1.创建cookie对象
        //将键:java2109 值:shabi 实例出来,存到cookie对象中
        Cookie cookie = new Cookie("java2109", "shabi");
        //2.设置有效时间,如果不设置有效时间,没有关闭浏览器,cookie会一直存在的
        /*
        * 正数:表示当前cookie的有效时间
        * 负数:表示当前浏览器打开的时候存在,关闭的时候没了
        * 0:销毁当前的cookie
        * */
        cookie.setMaxAge(60*60*24);//设置了有效期是个正数,
        // 即使关闭了浏览器,也可以获取cookie,可以自动登录的东西
//        cookie.setPath("day42_xkh");//当前项目,所有的Servlet都有这个cookie
        //3.把cookie发送到浏览器
        response.addCookie(cookie);

    }
}

获取cookie

package com.qfedu.d_cookie;

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;

@WebServlet("/getCookie")
public class GetCookieServlet 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 {
        //获取浏览器中cookie,返回值是一个数组
        Cookie[] cookies = request.getCookies();
        for (Cookie cookie : cookies) {
            //两个
            //JSESSION
            //java2109
            //浏览器一旦关闭cookie就没了
            System.out.println(cookie.getName());//获取键
            System.out.println(cookie.getValue());//获取值
            System.out.println("==============");
        }
    }
}

销毁cookie

package com.qfedu.d_cookie;

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;

@WebServlet("/destroyCookie")
public class DestroyServlet 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 {
        //退出登录
        Cookie[] cookies = request.getCookies();
        for (Cookie cookie : cookies) {
            //JSESSION
            //java2109
            if (cookie.getName().equals("java2109")){
                cookie.setMaxAge(0);//销毁cookie
                //重新发送给浏览器
                response.addCookie(cookie);
            }
        }
    }
}

14.3Session

为什么使用session?
1.cookie保存数据类型是单一的,只能保存字符串类型的数据,不能有中文
2.cookie的大小由限制
session可以解决以上cookie的问题
在java中session一般结合cookie使用
①使用session的时候一般要开启cookie
②如果浏览器没有开启cookie功能,我们可以通过html的url传参完后session的使用

getSession();获取session对象的
getId();JSESSIONID(在cookie里面)服务器下面一个标识号,session存在服务器中其中JSESSION是服务器下面的一个标识
invalidate();销毁session
setMaxInactiveInterval();设置过期时间
setAttribute();设置session的内容
getAttribute();获取session的内容

往session里面存值;取值,销毁,再取值。让下一页面可以获取到session里面来保持下一个页面的状态
比如登录以后,用户名存到session,在我们跳转到主页,在主页里面可以把session里面用户名字取出来展示到我们的主页上
1.创建Session:

package com.qfedu.a_session;

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;

@WebServlet("/setSession")
public class SessionTestServlet 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 {
        //1.获取session对象
        HttpSession session = request.getSession();
        System.out.println(session);
        //获取的是JSESSIONID  服务器唯一的标识
        System.out.println(session.getId());
        //给session设置一个时间,有效果的,里面放的是秒
        session.setMaxInactiveInterval(60*60*24);
        session.setAttribute("name","张三");

    }
}

2.获取Session:

package com.qfedu.a_session;

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;

@WebServlet("/getSession")
public class GetSessionServlet 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 {
        //1.获取Session对象
        //第一次创建session的时候默认为true
        //false的话,这个session使用的是已经创建好的session对象
        HttpSession session = request.getSession(false);
        //2.获取session,通过键取值
        Object name = session.getAttribute("name");
        System.out.println(name);
    }
}

3.销毁Session:

package com.qfedu.a_session;

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;

@WebServlet("/destroySession")
public class DestroySessionServlet 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 {
        //1.获取session对象
        HttpSession session = request.getSession(false);
        //销毁当前的session
        session.invalidate();
    }
}

总结

提示:这里对文章进行总结:没有总结

  • 9
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小yu别错过

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

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

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

打赏作者

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

抵扣说明:

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

余额充值