• Servlet原理及应用


    本文详尽的介绍了servlet的相关知识,包含servlet基础与tomcat相关知识、servlet声明周期原理及其应用、servlet多请求携带数据、以及单个servlet如何处理多请求的相关知识!

    一、servlet基础-tomcat

    1、Servlet是什么?

    • Servlet是什么
      • servlet 接口定义的是 一套处理网络请求的规范,所有实现servlet的类,都需要实现它的那五个方法,其中最主要的是两个声明周期方法init()和destory(),还有一个处理请求的service()。
    • Servlet请求处理
      • servlet是一个规范,那实现了servlet的类,就能处理请求了吗?
        • 不能
      • 请求是怎么来到servlet的呢?
        • 答案是web服务器,比如我们最常用的Tomcat。servlet都是部署在一个容器中的,不然你的servlet根本不起作用。
      • Tomcat才是与客户端直接打交道的家伙
        • 它监听了端口,请求过来后,根据URL等信息(),确定要将请求交给哪个servlet去处理,然后调用那个servlet的service方法,service方法返回一个response对象,Tomcat再把这个respond返回给客户端。

    2、安装配置tomcat

    2.1 tomcat目录结构

    • bin: 该⽬录存放的是可执⾏的⼆进制⽂件(startup.bat⽤于启动Tomcat、shutdown.bat⽤于停⽌Tomcat)
    • conf :存放的是Tomcat的配置⽂件(server.xml可以配置Tomcat的端⼝,web.xml)
    • lib 此⽬录存放了Tomcat服务器运⾏web项⽬所需的基础类库(jar包)
    • logs : 存放Tomcat服务器的运⾏⽇志、记录了服务器启动、运⾏异常及关闭等操作的记录
    • webapps: 存放Tomcat管理的web项⽬的⽬录,此⽬录中默认部署了Tomcat管理器等⼏个web项⽬
    • work: 运行时生成的文件,最终运行的文件都在这里。
      • (当客户端用户访问一个JSP文件时,Tomcat会 通过JSP生成Java文件,然后再编译Java文件生成class文件,生成的java和class文件都会存放到这个目录下。)

    2.2 重装Tomcat

    • tomcat 基于jdk运行的

      • java_home
      • classpath
      • path
    • 需要清理操作系统的环境变量 catalina字样 (重新安装时需要清除)

    • 关于服务:ip地址+端口号 端口唯一必须遵守规则

    • tomcat默认端口:8080 代表 tomcat-HOME/webapps/ROOT(没有指定具体项目名时,默认访问ROOT项目)

    2.3 部署一个web项目

    • 手工部署一个静态网站
      • 在tomcat/webapps目录下新建应用目录(应用名);
      • 在该目录下建/images、/js、/css
      • 将写好的html文件放置于该目录下
    • 打包war包-项目部署
      • 可以将web程序打包为war包,将其放置到tomcat/webapps
      • 启动tomcat后,即可以进行访问(tomcat会默认将其解压缩为文件夹)

    3、Servlet规范的引入

    • jdk版本支持
      • javaEE7支持servlet3.1规范
      • javaEE8支持servlet4.0规范
      • 以前的版本 2.0、2.1\2.2.\2.3\2.4\2.5\3.0\3.1
    • 应用程序中配置文件web.xml 因为规范版本不同,也有不同的设置
    • servlet编写规则也因为选择的servlet规范版本变化
    • 不同版本的tomcat支持的servlet规范不同

    4、如何编写一个servlet类

    4.1 作用

    • 相比于套接字网络编程,其更方便的处理http请求

    4.2 规范

    • 首先,一个Servlet类必须继承HttpServlet(接口或抽象类)

    • 其次,重写其service方法(doGet\doPost)

    • 再次,将servlet在web.xml注册

    • 
          
          <servlet>
              <servlet-name>myservlet-name>
      
              <servlet-class>com.xcu.web.MyFirstServletservlet-class>
          servlet>
      
          <servlet-mapping>
      
              <servlet-name>myservlet-name>
      
              <url-pattern>/loginurl-pattern>
          servlet-mapping>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14

      注意:servlet与servlet-mapping 不能交叉

    • 最后,编写html页面表单 发请求

    5.难点

    • servlet中的处理方法
      • 方法名固定:doGet、doPost、service
      • 方法的入参固定: 第一个参数类型:HttpServletRequest对象;第二参数类型:HttpServletResponse对象
      • 方法的抛出异常:ServletException 和IOException
      • 方法的返回值是:void

    二、Servlet生命周期原理及其应用

    1、servlet处理请求的流程

    1. 启动工程,系统会使用该工程的web.xml初始化此项目(包括外部访问url,创建一个servlet对象的名称的引用(句柄))
    2. 当浏览器访问本服务器上的应用时,应用会自动调用默认的欢迎页面呈现客户
    3. 用户点击欢迎页面提交表单按钮(以添加新用户信息为例)
    4. 浏览器会调用该表单的onsubmit方法(进行校验) ,并向由( url地址 +form.action组成)的新url(ip:端口/应用名/请求path)发出请求
    5. tomcat服务器接收请求,并解析它,
    6. 在web.xml的servlet-mapping中查找和请求path路径匹配的 url-pattern节点
    7. 再继续找url-pattern的兄弟 servlet-name的值(对象名)
    8. 如果servlet-name所指的对象不存在,则再去servlet节点中查找同名项的兄弟节点servlet-class
    9. 拿到servlet-class的文本值 使用反射创建此对象,并将其以servlet-name 对象名
    10. 系统再调用其service方法处理请求,并响应之;
    11. 如果第二次对此服务path进行请求,则因为以servlet-name为名称的对象已存在(唯一实例),则直接调用其service方法处理请求;

    2、servlet对象产生过程

    • servlet对象由web容器(tomcat、weblogic、websthere、jboss)负责产生
    • 使用load-on-startup节点可以设置servlet创建的时机,含有load-on-startup节点则在服务器启动时创建servlet对象;如果不含有,则会在首次请求时创建对象
    • 再由容器调用init方法初始化servlet对象
    • 容器调用service方法提供服务(如果没有(重写)service,则实际是执行父类的service方法(子类继承过来的service方法),在其中会根据请求的method调用doGet或doPost方法服务(实际上调用的是子类的)
    • 下次,请求来时,直接对外提供服务,不会创建servlet对象(唯一实例)
    • 最后,当容器关闭时,容器会先调用servlet的destroy方法再关闭

    3、servlet处理请求多个场景

    • 请求数字

      • 所有的表单提交的数据均是字符。因此,必须要进行类型转换(常见的有Integer.parseInt\Doble.parseDouble\Long.parseLong\Float.parseFloat)
      • 需要判空,应为“”或null无法转数字(可以使用三元运算符)
    • 请求日期

      • 服务端获取日期字符串,需要使用SimpleDateFormat类的函数转换
    • 请求中文

      • req.setCharacterEncoding(“UTF-8”); //上行编码
      • resp.setContentType(“text/html;charset=UTF-8”);//下行转码
      • 请求的method=POST
    • 在不同请求模式下中文转码

      • get请求乱码必须使用String构造手动转码

    4、响应方式

    • 请求转向
      • 携带数据,整个过程只有一次浏览器请求
      • 由req进行处理req.getRequestDispatcher("页面或servlet").forward(req,resp);
    • 重定向
      • 不携带数据,整个过程有两次浏览器请求
      • 由resp进行处理resp.sendRedirect("页面或servlet");
      • servlet经过重定向告诉浏览器一个新地址,浏览器重新请求新地址(地址栏发生变化)
    • 注意事项:
      • 在添加、修改、删除之后只能是重定向,不能使用请求转发,否侧刷新时会重复执行上一步操作(可能会抛出异常)
      • 原因(以插入servlet转向查询servle为例):
        • 使用重定向在整个业务流程中会触发两次浏览器请求,刷新时只会出触发后一次查询的浏览器请求
        • 请求转发在整个业务流程中只会触发一次浏览器请求,刷新时会触发整个业务流程(包括插入和查询)

    5、EL表达式与JSTL表达式特性

    1. EL表达式特性

    • EL表达式取数据自动探空
    • EL表达式只简化了输出,没有提供任何逻辑代码功能(if、for、while都不含有)

    2. JSTL表达式特性

    • 自动类型转换
    • 自动探空
    • 提供任何逻辑代码功能(if、for、while都含有,常配合EL表达式配合使用)

    6、浏览器请求注意事项

    • 浏览器会将页面所有标签,按照层级将其构成一个对象树,每一个标签节点时一个对象,其每个对象还有属性和方法,js可以对其进行操作
    • 表单提交的任何数据都是string类型(eg: text文本框提交的数据是string类型)
    • get请求会将地址后携带的值清除,并携带自己本身的表单值

    三、Servlet进阶应用

    1、jsp-servlet 处理逻辑

    请添加图片描述

    2、get-post携带数据请求

    • 代码示例:
    	<form action="teacher?method=addTeacher" method="post">
            姓名:<input type="text" name="tname" /><br/>
            性别:<input type="radio" name="gender" value="" /><input type="radio" name="gender" value=""/><br/>
            入职日期:<input type="text" name="workDate"/><br/>
            教授年级:<input type="text" name="workGrade"/><br/>
            <input type="submit" value="添加"/>
        form>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 请求:
      • 表单属性action="teacher?method=addTeacher"的请求url携带参数,可以看作是get方式请求,而其属性method="post"提交方式为post请求,所以此种请求方式可以看作是get-post携带数据请求
    • 数据获取:
      • get-post携带数据请求的方式,在被请求的servlet中无论是url后携带的参数(get请求携带参数),还是通过post请求携带参数(请求体中携带的参数),均可以使用getParamter("xxx")获取参数

    3、一个servlet处理多个请求

    • 核心思想

      • 在请求的url后携带参数method=xxx,并在所请求的servlet中编写相同参数值名称的方法,处理相应的请求
      • 在后端的servlet的service方法中获取method参数值,并通过反射获取到方法对象
      • 通过反射调用执行相应的方法
    • 示例

    1. 请求
     <form action="teacher?method=addTeacher" method="post">
          姓名:<input type="text" name="tname" /><br/>
          性别:<input type="radio" name="gender" value="" /><input type="radio" name="gender" value=""/><br/>
          入职日期:<input type="text" name="workDate"/><br/>
          教授年级:<input type="text" name="workGrade"/><br/>
          <input type="submit" value="添加"/>
      form>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    1. 反射获取方法对象
      @Override
      protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //        1.设置编码格式
          req.setCharacterEncoding("UTF-8");
          resp.setContentType("text/html;charset=UTF-8");
    
    //        利用反射执行对应的请求方法
          String methodName = req.getParameter("method");
          try {
              Method method = this.getClass().getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
    //        执行方法
              method.invoke(this, req, resp);
          } catch (NoSuchMethodException e) {
              e.printStackTrace();
          } catch (InvocationTargetException e) {
              e.printStackTrace();
          } catch (IllegalAccessException e) {
              e.printStackTrace();
          }
    
      }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    1. 处理请求对应的方法
    
    //    增加
      private void addTeacher(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
          //        2.
          String tname = req.getParameter("tname");
          String gender = req.getParameter("gender");
          String workDate = req.getParameter("workDate");
          String workGrade = req.getParameter("workGrade");
    
          Teacher teacher=new Teacher(0,tname,gender,workDate,workGrade);
    //        3.
          TeacherService teacherService=new TeacherServiceImpl();
          boolean b = teacherService.addTeacher(teacher);
    //        4.
          if (b){
              resp.sendRedirect("teacher?method=findAll");
          }else {
              resp.sendRedirect("error.jsp");
          }
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
  • 相关阅读:
    deepin-anything 源码刨析
    操作系统面试集锦
    kafka生产者源码精华总结
    electron使用electron-builder macOS windows 打包 签名 更新 上架
    理想汽车有增长潜力,但风险也很大
    这份阿里巴巴 Java 架构六大专题面试宝典值得你刷一刷
    OpenCV的石头检测~
    通过chatgpt 学习React的useEffect
    网关与auth微服务缓存打通
    MySQL基础
  • 原文地址:https://blog.csdn.net/weixin_43715360/article/details/126255722