Servlet的详细使用(上)

简介: Servlet的详细使用(上)



Servlet体系结构


我们将来开发B/S架构的web项目,都是针对HTTP协议,所以我们自定义Servlet,会继承HttpServlet

@WebServlet("/demo4")
    public class ServletDemo2 extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("get......");
        }
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("post......");
        }
    }

运行之后我们访问请求路径,从代码可以看出我们这个Servlet里面有两个方法,一个doGet()和doPost()方法,当我们直接输入访问路径,默认的是执行get方法


运行结果:



对于post请求来说,我们得写一个表单来请求当前Servlet资源



运行结果:

1)页面跳转


2)


HttpServlet中为什么要根据请求方式的不同,调用不同方法?
post和get请求参数的位置不一样,post请求参数的位置在请求体里面,get请求参数在请求行里面,当我们继承Servlet接口里面,需要根据请求的方式不同,来进行分别的处理,需要在service方法里面先获取请求方式




Servlet urlPattern配置

Servlet想要被访问,必须配置其访问路径(urlPattern)

1.一个Servlet,可以配置多个urlPattern

WebServlet(urlPatterns = {"/demo4","/demo5"})
    public class ServletDemo4 extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("demo4 get......");
        }
    }

2.urlPattern配置规则

1)精确匹配


2)目录匹配


注意:当一个路径同时满足精确匹配和目录匹配的时候,精确匹配的优先级大于目录匹配*

3)扩展名匹配


4)任意匹配


/*的优先级高于/

/和/的区别
当我们项目中的Servlet配置了“/”会覆盖掉tomcat中的DefaultServlet,当其他的url-pattern都匹配不上时都会走这个Servlet
当我们的项目中配置了“/”,意味着匹配任意访问路径
配置任意访问路径会导致我们的任意访问资源无法使用,所以一般不要去配置它
优先级:精确路径>目录路径>扩展名路径>/>/


Request和Response介绍

Request:获取请求数据
Response:设置响应数据

示例代码:

@WebServlet("/demo2")
    public class ServletDemo2 extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("get......");
        }
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //使用request对象,获取请求数据
            String name = req.getParameter("name");
            //使用response对象,设置响应数据
            resp.setHeader("content-type","text/html;charaset=utf-8");
            resp.getWriter().write("<h1>"+name+",欢迎您!</h1>");
            System.out.println("post......");
        }
    }

Request

Request继承体系



Request获取请求数据

请求数据分为3部分:

1.请求行:


2.请求体:


字符输入流:一般用于文本的情况下
字节输入流:一般用于文件和图片的情况下

示例代码:

第一步:创建表单

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Title</title>
  </head>
  <body>
    <form action="/req1" method="post">
      <input type="text" name="username">
      <input type="password" name="password">
      <input type="submit">
    </form>
  </body>
</html>

第二步:编写dopost请求

@Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取post 请求体:请求参数
        //1.获取字符输入流
        BufferedReader br = req.getReader();
        //2.读取数据
        String line = br.readLine();
        System.out.println(line);
    }

运行结果:

3.请求头:



Request通用方式获取请求参数

GET请求方式和POST请求方式 区别主要在于获取请求参数的方式不一样,可以提供一种获取请求参数的方式,从而同一doGet和doPost方法
假设我们现在按原来的方法接收到了数据,但是数据时一条长长的字符串,我们还要拆分,这样是不是,有些麻烦


于是request就很贴心的为我们提供了一种方法


示例代码:

@Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //GET请求限制
        System.out.println("get....");
        //1.获取所有参数的Map集合
        Map<String,String[]> map = req.getParameterMap();
        for(String key:map.keySet()){
            System.out.print(key+":");
            //获取值
            String[] values = map.get(key);
            for (String value:values){
                System.out.print(value+" ");
            }
            System.out.println();
        }
        //根据key获取参数值,数组
        String[] hobbies = req.getParameterValues("hobby");
        for(String hobby:hobbies){
            System.out.println(hobby);
        }
        //根据key,获取单个参数值
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        System.out.println(username);
        System.out.println(password);
    }

同样的方法也能在doPost里面,我们完全可以在post请求里面填写一句this.doGet(req,resp);

请求参数中文乱码–post解决方案

当我们从表单post发送请求提交表单后的时候,request接收数据会乱码


(tomcat8及以后的版本,get方式不会乱码,post方式会乱码)
原因:post底层是通过getReader获取一个字符输入流,通过流的方式读取信息,该流的编码形式不是utf-8,但页面是utf-8的
解决方案:在请求里设置字符输入流的编码为UTF-8



请求参数中文乱码–get解决方案

get请求方式乱码不能用post乱码方式解决
乱码原因:
编码和解码不一致
拿一个代码举例

public class URLDemo {
    public static void main(String[] args) throws UnsupportedEncodingException {
        String username = "张三";
        //1.URL编码
        String encode = URLEncoder.encode(username, "utf-8");
        System.out.println(encode);
        //URL解码
        String decode = URLDecoder.decode(encode,"gbk");
        System.out.println(decode);
    }
}

运行结果:

*

由此可以看出因为编码和解码的不一致,导致我们运行结果不是我们想看到的

解决办法:

因为tomcat底层的方法是写死的,我们没有办法改变,但是我们可以想到它两个数据间的字节是一样的(二进制),我们可以把乱码数据转成二进制数据,再把二进制字节数据变成我们想要的数据*

public class URLDemo {
    public static void main(String[] args) throws UnsupportedEncodingException {
        String username = "张三";
        //1.URL编码
        String encode = URLEncoder.encode(username, "utf-8");
        System.out.println(encode);
        //URL解码
        String decode = URLDecoder.decode(encode,"ISO-8859-1");
        System.out.println(decode);
        //3.转为字节数据
        byte[] bytes = decode.getBytes("ISO-8859-1");
        for(byte b:bytes){
            System.out.print(b+" ");
        }
        System.out.println();
        //4.将字节数组转为字符串
        String s = new String(bytes, "utf-8");
        System.out.println(s);
    }
}

运行结果:



目录
相关文章
|
安全 关系型数据库 MySQL
【Python】已解决:pymysql.err.OperationalError:(2003 “Can’t connect to MySQL server on ‘localhost’ ([WinEr
【Python】已解决:pymysql.err.OperationalError:(2003 “Can’t connect to MySQL server on ‘localhost’ ([WinEr
2084 1
|
设计模式 网络协议 Java
【十五】设计模式~~~行为型模式~~~状态模式(Java)
文章详细介绍了状态模式(State Pattern),这是一种对象行为型模式,用于处理对象在其内部状态改变时的行为变化。文中通过案例分析,如银行账户状态管理和屏幕放大镜工具,展示了状态模式的应用场景和设计方法。文章阐述了状态模式的动机、定义、结构、优点、缺点以及适用情况,并提供了Java代码实现和测试结果。状态模式通过将对象的状态和行为封装在独立的状态类中,提高了系统的可扩展性和可维护性。
【十五】设计模式~~~行为型模式~~~状态模式(Java)
|
Web App开发 JavaScript 前端开发
XSS利器之BeEF
XSS利器之BeEF
Unity精华☀️一、从旋转到万向锁之:Unity的旋转
Unity精华☀️一、从旋转到万向锁之:Unity的旋转
|
存储 JavaScript 前端开发
【MySQL】MySQL9.0发布,有点小失望
本文介绍了MySQL 9.0新版本的更新情况及其主要特性,包括JavaScript存储过程、VECTOR类型支持、内联和隐式外键约束等。作者详细讲解了如何在官网上查找新特性,并提供了两种下载方法:官网下载和Docker镜像。此外,文章还探讨了老版本是否需要升级至MySQL 9.0的问题,最终认为新特性并不足以成为升级的必要理由。适合对MySQL新版本感兴趣的读者参考。
2540 1
【MySQL】MySQL9.0发布,有点小失望
|
Kubernetes 调度 数据中心
在K8S中,Pod中关于资源有request和limit两个字段?这么设计的原因是什么?
在K8S中,Pod中关于资源有request和limit两个字段?这么设计的原因是什么?
|
JavaScript 前端开发 API
vue使用element plus组件上传服务器
vue使用element plus组件上传服务器
369 1
|
弹性计算 Java 应用服务中间件
复制已有的Tomcat作为新的Tomcat,只需修改三个配置文件,五步操作,保证能正常运行!
复制已有的Tomcat作为新的Tomcat,只需修改三个配置文件,五步操作,保证能正常运行!
cnpm i安装报错-Install fail! Error: Unsupported URL Type: npm:vue-loader@^15.9.7
cnpm i安装报错-Install fail! Error: Unsupported URL Type: npm:vue-loader@^15.9.7
1037 1
|
Kubernetes 应用服务中间件 网络安全
Kubernetes证书类型和适用场景
Kubernetes证书类型和适用场景