Servlet原理及应用

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

一、servlet基础-tomcat

1、Servlet是什么?

  • Servlet是什么
    • Servlet(Server Applet)是Java Servlet的简称,称为小服务程序或服务连接器,泛指用 Java编写的服务器端程序。在编程过程中也指一切 实现了Servlet接口的类(约定以Servlet结尾命名)
    • servlet 接口定义的是 一套处理网络请求的规范,所有实现servlet的类,都需要实现它的那五个方法,其中最主要的是两个声明周期方法init()和destory(),还有一个处理请求的service()。
  • Servlet请求处理
    • servlet是一个规范,那实现了servlet的类,就能处理请求了吗?
      • 不能
    • 请求是怎么来到servlet的呢?
      • 答案是web服务器,比如我们最常用的Tomcat。servlet都是部署在一个容器中的,不然你的servlet根本不起作用。
    • Tomcat才是与客户端直接打交道的家伙
      • 它监听了端口,请求过来后,根据URL等信息(<url-pattern>),确定要将请求交给哪个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>
            <servlet-name>my</servlet-name>
    <!--        全限定路径名-->
            <servlet-class>com.xcu.web.MyFirstServlet</servlet-class>
        </servlet>
    
        <servlet-mapping>
    <!--        servlet在web容器中的对象名 (必须与上面完全一致)-->
            <servlet-name>my</servlet-name>
    <!--        本servlet对外暴露的请求path-->
            <url-pattern>/login</url-pattern>
        </servlet-mapping>
    

    注意: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无法转数字(可以使用三元运算符)
  • 请求日期

    • <input type="datetime-local" name="birthday" />
    • 服务端获取日期字符串,需要使用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>
  • 请求:
    • 表单属性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. 反射获取方法对象
  @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. 处理请求对应的方法

//    增加
  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");
      }
  }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值