Javaweb | Servlet编程

目录:

    • 1.认识Servlet
    • 2.编写Servlet
    • 3.Servlet的运行机制
    • 4.Servlet的生命周期
      • 4.1 Servlet生命周期图
      • init()方法
      • doGet()
      • doPost()
      • service()
      • destroy()方法
    • 5.解决“控制台”打印中文乱码问题
    • 6.Servlet 和 JSP内置对象 (常用对象)
      • 获得out对象
      • 获得request 和 response对象
      • 获得session对象
      • 获得application对象
    • 7.设置欢迎页面
    • 8.在Servlet中设置/获取参数 :
      • 8.1 设置参数
      • 8.2 获取参数
    • 9.过滤器
      • 9.1 过滤器的定义
      • 9.2 使用过滤器的三种情况 :
        • 情况一
        • 情况二
        • 情况三
      • 9.3 编写过滤器 :
        • 编写过滤器的步骤
      • 9.4 配置过滤器 :
        • 配置 “过滤器” 过滤所有文件
        • 配置 “过滤器” 过滤一个或多个Servlet对象/JSP文件
        • 配置 “过滤器” 过滤一个或多个文件目录
      • 9.5 过滤器的例子
          • 过滤器解决中文乱码问题
    • 10.异常处理

1.认识Servlet

  • Servlet 是运行在 Web服务器端Java应用程序,可以生成动态Web页面,属于客户服务器响应的 中间层JSP底层 就是一个Servlet,也可以说 JSP 就是 Servlet

  • 运行JSP时,服务器底层 会将 JSP 编译成一一个 Java类,这个类就是 Servlet

  • JSPServlet 都能实现同样的页面效果,不过编写JSP编写Servlet 相比,前者 ( JSP )的成本低得多。既如此 为什么还要学Servlet?

    Servlet属于JSP底层,学习它有助于了解底层细节;另外,Servlet毕竟是一个Java类适合纯编程如果是纯编程,比将Java代码混合在HTML中的JSP要好得多

2.编写Servlet

  • 编写Servlet的步骤

  • 第一步编写一个类,该类继承 HttpServlet

    public class myServlet extends HttpServlet {}
    
  • 第二步重写HttpServletdoGet( ) 或 doPost( )方法。 ( 也可以重写HttpServle的其他方法,根据需要来重写。)

    public class myServlet extends HttpServlet {
    
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
     response.setContentType("text/html;charset=gb2312"); //设置HTTP响应的内容类型
            /*
              PrintWriter对象可以用于向"客户端浏览器"输出响应数据。
              通过这个PrintWriter对象,你可以将数据以"文本形式"写入到“HTTP响应”中。
             */
            PrintWriter out = response.getWriter();
            out.println("欢迎来到本系统!");
        }
    }
    
  • 第三步配置Servlet

    • 编写完一个Servlet后还不能直接访问,需要配置Servlet才能通过URL映射到与之对应的Servlet 中,用户才能对它进行访问
      ( 配置好Servlet后,客户端浏览器才能通过url/ 网址访问到服务器端Servlet类)

    • Servlet配置是通过 web.xml 文件来实现的。web.xml文件位于 “WebRoot/WEB-INF” 下面。

    • 客户端浏览器访问该Servlet的url路径,如客户端浏览器访问 :
      http://localhost:8080/servlets/MyServlet 就能访问到 MyServlet.java 类。

      
      <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_4_0.xsd"
               version="4.0">
      
          
          <servlet>
              <servlet-name>MyServletservlet-name>
              <servlet-class>com.servlets.MyServletservlet-class>
          servlet>
      
          <servlet-mapping>
              <servlet-name>MyServletservlet-name>
              
              <url-pattern>/servlets/MyServleturl-pattern>
          servlet-mapping>
      
      web-app>
      

      <servlet-name>MyServletservlet-name>
      

      servlet-name 中的名字用户可以自己命名不一定要和原文件名一样但两个servlet-name名字必须要相同

           <url-pattern>/servlets/MyServleturl-pattern>
      

      url-pattern不一定Servlet 类的 包路径,只是为方便,一般都用包路径来表示。(可自定义访问Servlet类的 url 路径

  • 第四步部署Servlet。如:设置好Tomcat服务器

  • 第五步测试Servlet。在浏览器上输入 http://localhost:8080/servlets/MyServlet 即可访问 Servlet

3.Servlet的运行机制

  • Servlet类设置 构造函数,只有 初次运行时,系统才会初始化Servlet / 访问Servlet的构造函数。再次运行Servlet时,不会再访问构造函数

    ( 在Web应用程序中,Servlet类只会在它第一次被访问时初始化 / 访问构造函数。这意味着,当一个请求来到服务器,服务器会判断该Servlet类是否已经被加载

    如果 (构造函数) 没有被加载 ,服务器会加载初始化Servlet类,然后处理请求如果 (构造函数) 有被加载,服务器会直接使用已经加载和初始化的 (Servlet )实例来处理请求不会再访问Servlet的构造函数

  • Servlet构造函数只在Servlet类首次被加载初始化时被调用, 之后的请求不会再访问Servlet构造函数。 这是Servlet的 生命周期 行为的一部分。 )

    public class MyServlet extends HttpServlet {
    
        public MyServlet() { //构造函数
     //Servlet的构造函数,只有Servlet第一次启动时才会访问,之后的请求不会再访问Servlet
            System.out.println("MyServlet构造函数");
        }
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //如果"控制台"输出有中文乱码问题,下面有解决方案。
            System.out.println("MyServlet.doGet函数");
        }
    }
    

    访问路径 :

在这里插入图片描述

第一次访问Servlet“控制台”打印的信息 :
在这里插入图片描述

第二次访问Servlet“控制台”打印的信息 :

在这里插入图片描述

第三次访问Servlet“控制台”打印的信息 :

在这里插入图片描述

(除第一次访问Servlet会访问构造函数外,之后的请求不会再访问Servlet的构造函数。)

  • 创建了一个Servlet对象,那么很多用户同时访问的时候会不会造成等待?

    实则是不会的。因为Servlet采用的是多线程机制,每一次请求,系统就分配一个线程运行doGet( )函数。但是这样也会带来安全问题,一般来说,不要在Servlet内定义成员变量,除非这些成员变量是所有用户共用的

4.Servlet的生命周期

4.1 Servlet生命周期图

  • 客户端向Web服务器提出第1次Servlet请求时,Web服务器会实例化一个Servlet,并且调用init( )方法;
    构造函数init( )函数只会被访问一次,后续的请求不会再访问这两个函数
  • 如果Web服务器中已经存在了一个Servlet实例,将直接使用此实例;然后调用service()方法,service(方法将根据客户端的请求方式来决定调用对应的doXXX0方法;当Servlet从Web服务器中消亡时,Web服务器将会调用Servletdestroy() 方法。
  • Javaweb | Servlet编程_第1张图片

init()方法

init()方法 :

  • Servlet生命周期中,第一次访问Servlet时,利用构造函数创建Servlet对象后,立即调用init( )方法来进行初始化构造函数init( )方法都只会在第一次访问时被调用后续的请求中,两者不会被再次调用。
  • init( )方法用于执行一些特定的初始化操作,例如加载配置文件连接数据库等。

doGet()

  • Servlet有两个处理方法之一。
  • doGet()get方式请求Servlet时运行 。常见的get请求方式有 : 链接get方式表单提交直接访问Servlet

doPost()

  • Servlet有两个处理方法之一。
  • doPost()post方式请求Servlet时运行。常见的post请求为 :为 post方式表单提交

service()

  • 客户端Servlet发送一个请求时,服务器端将会开启一个线程线程会调用service()方法
  • service()方法会根据收到的客户端请求类型来决定是调用doGet()还是调用doPost()。但一般情况下不用覆盖service()方法,直接使用doGet()与doPost()方法一 样可以达到处理的目的。

destroy()方法

  • destroy() 方法在Servlet实例消亡自动调用。(Servlet消亡时会调用destroy( )方法)
  • 在Web服务器运行Servlet实例时会因为一些原因,Servlet对象会消亡。但是在Servlet消亡之前还必须进行某些操作,比如释放数据库连接以节省资源等,这个时候我们就要重写destroy()方法

5.解决“控制台”打印中文乱码问题

第一步

Javaweb | Servlet编程_第2张图片

第二步-encoding utf-8

Javaweb | Servlet编程_第3张图片

第三步-Dfile.encoding=UTF-8 (配置后,要重启tomcat服务器)

Javaweb | Servlet编程_第4张图片

每个项目都要在tomcat这么配置,比较麻烦。可通过设置环境变量来解决这个问题。
(配置环境变量后,就不需要每次都在 tomcat里面配置 -Dfile.encoding=UTF-8

第三步的更好的解决替代方案 : 配置环境变量
JAVA_TOOL_OPTIONS
-Dfile.encoding=UTF-8

Javaweb | Servlet编程_第5张图片

6.Servlet 和 JSP内置对象 (常用对象)

  • 因为JSPServlet等价,在JSP中可以使用内置对象,那么Servlet中也可以使用内置对象
  • 这里讲述常用ServletJSP内置对象

获得out对象

  • JSP中的out对象 对应于Servlet 中的javax.servlet.jsp. JspWriter。通过以下代码可获得out对象

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletExcept ion, IOException {
            PrintWriter out = response. getWriter();//获得out对象
            //使用Out对象
    }
    
  • 默认情况下,out对象无法打印中文的。因为out对象输出流中有中文没有设置编码

        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletExcept ion, IOException {
            //设置编码,打印中文
            response.setContentType("text/html;charset=gb2312");
            PrintWriter out = response. getWriter();//获得out对象
            //使用Out对象
        }
    

获得request 和 response对象

  • Servlet中获得JSP页面中的request对象response对象是很容易的,因为这两个对象已经被作为参数传给了 doXXX( ) 方法。

  • doXXX( )方法中的 requestresponse 参数可直接当 request对象、response 对象使用

  • public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
           //将request参数当做request对象使用
          //将response参数当做response对象使用
        }
    

获得session对象

  • session对象对应的是HttpSession接口,在 Servlet 中它可以通过以下代码获得。

      public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //session对应的是HttpSession接口
            HttpSession session = request.getSession();
            //把该session当session对象来使用
        }
    

获得application对象

  • application对象对应的是ServletContext接口,在Servlet中可以通过以下代码获得。

      public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            ServletContext application = this.getServletContext();
            //把此application当application对象使用
        }
    
  • 使用 application 可以实现 服务器内跳转

      ServletContext application = this.getServletContext();
      RequestDispatcher rd = application.getRequestDispatcher("URL地址");
      rd.forward(request,response);
    
  • 由于ServletJSP具有同质性,常用的 Servlet内跳转有以下 两种方法:

    重定向。 (对应JSP隐含对象中的sendRedirect( ))

    response.sendRedirect("URL地址");
    

    服务器内跳转。(对应JSP隐含对象中的forward( ))

    ServletContext application = this.getServletContext();
    RequestDispatcher rd = application.getRequestDispatcher("URL地址");
    rd.forward(request,response);
    

    (这两种Servlet内的跳转JSP中提到的跳转都是等效的)

7.设置欢迎页面

  • 在设置完欢迎页面之后,用户登录时输人的URL只需要是该门户网站的虚拟目录就可以自动访问欢迎页面

  • 可通过在web.xml中设置 “欢迎页面”。

    web.xml

    
    <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_4_0.xsd"
             version="4.0">
        
        <welcome-file-list>
            
            <welcome-file>welcome.jspwelcome-file>
        welcome-file-list>
    
    web-app>
    

    welcome.jsp

    <%@ page language="java" import="java.util.*" pageEncoding="gb2312" %>
    <html>
    <body>
    欢迎来到本系统<br>
    body>
    html>
    
  • web.xml可以同时设置多个欢迎页面web容器默认设置的第一个页面为欢迎页面,如果找不到最前面的页面Web容器将会依次选择后面的页面作为欢迎页面

    <welcome-file-list>
            
      
            <welcome-file>firstWelcome.jspwelcome-file>
            <welcome-file>secongdWelcome.jspwelcome-file>
        welcome-file-list>
    

8.在Servlet中设置/获取参数 :

8.1 设置参数

  • 有些和系统有关的信息最好保存在配置文件内,例如系统中的字符编码数据库连接的信息(driverClassName、url、username、password),在使用这些配置时从配置文件中读,但是读取配置文件的代码必须用户自己来写,比较麻烦。

  • 那么才能比较方便的获得参数 可在web.xml中设置参数。

  • 设置全局参数 :该参数所有的Servlet都可以访问。

    
        <context-param>
            <param-name>参数名param-name>
            <param-value>参数值param-value>
        context-param>
    
  • 设置局部参数 :该参数只有对应的Servlet都可以访问。此时设置的参数只在该Servlet中有效,其他的Servlet得不到该参数。

        
        <servlet>
            <servlet-name>Servlet名称servlet-name>
            <servlet-class>类路径servlet-class>
            
              <init-param>
                  <param-name>参数名param-name>
                  <param-value>参数值param-value>
              init-param>
        servlet>
    
  • web.xml

     
    <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_4_0.xsd"
             version="4.0">
    
    
    <context-param>
        <param-name>encodingparam-name>
        <param-value>gb2312param-value>
    context-param>
    
    <servlet>
        <servlet-name>InitServletservlet-name>
        <servlet-class>com.servlets.InitServletservlet-class>
         
        <init-param>
            <param-name>driverClassNameparam-name>
            <param-value>com.mysql.jdbc.Driverparam-value>
        init-param>
    servlet>
       
      
    <servlet-mapping>
        <servlet-name>InitServletservlet-name>
        <url-pattern>/servlets/InitServleturl-pattern>
    servlet-mapping>
    
    
    <welcome-file-list>
        <welcome-file>welcome.jspwelcome-file>
    welcome-file-list>
    
    web-app>
    

8.2 获取参数

  • 获取全局参数的方法 :

     //获得application对象
     ServletContext application = this.getServletContext();
     //获得全局参数
     application.getInitParameter("参数名称");
    
  • 获取局部参数的方法 :

    this.getInitParameter("参数名");
    
  • InitServlet.java

    public class InitServlet extends HttpServlet {
        public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //获得application对象
            ServletContext application = this.getServletContext();
            //获得全局参数
            String encoding = application.getInitParameter("encoding");
            System.out.println("encoding参数是: "+encoding);
    
            //获得局部参数
            String driverClassName = this.getInitParameter("driverClassName");
            System.out.println("driverClassName的参数是: "+driverClassName);
        }
    }
    

    InitServlet中可以获得web.xml设置的参数的值,不过,在一般情况下不使用web.xml来设置参数,因为web.xml通常用来设置很基本的Web配置,设置太多参数会使文件过于臃肿。实际用于设置参数的文件与所选取的参数有关。

9.过滤器

9.1 过滤器的定义

  • 过滤器 属于一种小巧的可插入Web组件,它能够对Web应用程序的前期处理后期处理进行控制可以拦截请求和响应查看提取或者以某种方式操作正在客户端和服务器之间进行交换的数据
  • 过滤器doFilter( )函数Servlet被访问/调用之前被调用(★★★)

9.2 使用过滤器的三种情况 :

以下三种情况遇到的问题可以 过滤器 可以解决。

情况一
  • 为了 解决中文乱码问题,经常需要有如下设置

    request.setCharacterEncoding("gb2312");
    response.setContentType(" text/ html;charset = gb2312");
    
  • 这是Servlet用来设置编码的,如果Servlet处理方法的最前面没有加入这段代码,则很可能会出现乱码问题。如果是一个大工程会有很多的Servlet,这样就要写很多重复的代码。同时如果需要换成另外的编码,这也是一件烦琐的事情。

    —此时可用 过滤器 来解决

情况二
  • 很多门户网站都会有登录页面,这是为了业务需求,同时也是为了使用户控制更加安全。如果客户没有登录访问网站的某一受限页面,在很多情况下会引发安全问题。那么应该如何避免这种情况? 在一般情况下可以使用session检查来完成,但是在很多页面上都添加session检查代码会比较烦琐

    —此时可用 过滤器 来解决

情况三
  • 许多网站存在着各种不同的权限,通常只有它的管理员才可以对网站进行维护和修改,一般的普通用户是无法完成该功能的。登录后,网页如何区分普通用户还是管理员? 如果是每一个页面写一个判断用户类型的代码,这是非常烦琐。

    —此时可用 过滤器 来解决

9.3 编写过滤器 :

编写过滤器的步骤
  • Servlet过滤器可以被当作一个只需要在web. xml文件中配置就可以灵活使用重用的模块化组件。它能够对JSPHTMLServlet文件进行 过滤

  • 编写过滤器的需要如下两个步骤

    第一步实现Filter接口

    javax.servlet.Filter;
    

    第二步、实现init()destroy()doFilter()三个方法

    init()初始化方法, 它表示的是 过滤器初始化时的动作

    //初始化方法 
    public void init(FilterConfig filterConfig) throws ServletException {
       };
    

    destroy()消亡方法,它表示的是 过滤器消亡时的动作

    public void destroy() { //消亡方法
        };
    

    doFilter() : 过滤函数 ,它表示的是 过滤器过滤时的动作

     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        };
    

9.4 配置过滤器 :

  • web.xml配置此过滤器 。可在 过滤器添加/配置过滤器参数

  • 过滤器的doFilter( )函数在Servlet被访问/调用之前被调用(★★★)

    
    <filter>
        <filter-name>EncodingFilterfilter-name>
        <filter-class>com.filter.EncodingFilterfilter-class>
         
          <init-param>
            <param-name>paramNameparam-name>
            <param-value>paramValueparam-value>
        init-param>
    filter>
    
    
    <filter-mapping>
        <filter-name>EncodingFilterfilter-name>
        <url-pattern>对象/文件/目录的路径url-pattern>
    filter-mapping>
    

    过滤器的配置Servlet的配置有相似之处。

配置 “过滤器” 过滤所有文件
        
<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_4_0.xsd"
         version="4.0">
 
 
<filter>
    <filter-name>EncodingFilterfilter-name>
    <filter-class>com.filter.EncodingFilterfilter-class>
filter>
    

<filter-mapping>
    <filter-name>EncodingFilterfilter-name>
    
    <url-pattern>/*url-pattern>
filter-mapping>

web-app>
配置 “过滤器” 过滤一个或多个Servlet对象/JSP文件
        
<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_4_0.xsd"
         version="4.0">
 
 
<filter>
    <filter-name>EncodingFilterfilter-name>
    <filter-class>com.filter.EncodingFilterfilter-class>
filter>
    

<filter-mapping>
    <filter-name>EncodingFilterfilter-name>
    
    
    <url-pattern>/PATh/ServletName1( 或JSPName1 )url-pattern>
filter-mapping>

web-app>
配置 “过滤器” 过滤一个或多个文件目录
        
<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_4_0.xsd"
         version="4.0">
 
 
<filter>
    <filter-name>EncodingFilterfilter-name>
    <filter-class>com.filter.EncodingFilterfilter-class>
filter>
    

<filter-mapping>
    <filter-name>EncodingFilterfilter-name>
    
     
    
    <url-pattern>/PATh1/*url-pattern>
filter-mapping>

web-app>

9.5 过滤器的例子

过滤器解决中文乱码问题
  • EncodingFilter.java

    public class EncodingFilter implements Filter {
    
        //初始化方法
        public void init(FilterConfig filterConfig) throws ServletException {
        }
    
        //消亡方法
        public void destroy() {
        }
    
        //过滤函数
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            //设置“字符编码”
            request.setCharacterEncoding("gb2312");
            chain.doFilter(request,response);
        }
    }
    
  • web.xml (配置过滤器)

            
    <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_4_0.xsd"
             version="4.0">
     
     
    <filter>
        <filter-name>EncodingFilterfilter-name>
        <filter-class>com.filter.EncodingFilterfilter-class>
    filter>
        
    
    <filter-mapping>
        <filter-name>EncodingFilterfilter-name>
        
        <url-pattern>/*url-pattern>
    filter-mapping>
        
        
    
    <filter-mapping>
        <filter-name>EncodingFilterfilter-name>
    
    
        <url-pattern>/PATh/ServletName1( 或JSPName1 )url-pattern>
    filter-mapping>
        
        
    
    <filter-mapping>
        <filter-name>EncodingFilterfilter-name>
        
         
        
        <url-pattern>/PATh1/*url-pattern>
    filter-mapping>   
    
    web-app>
    

10.异常处理

  • Web应用程序中总会发生各种各样的异常,例如数据库连接失败、0被作为除数、得到的值是空、数组溢出等。如果出现了这些异常,系统不做任何处理显然是不行的。一般情况下都是通过自定义一个公共的error.jsp页面来实现统的异常处理。

  • error.jsp

    <%@ page language="java" pageEncoding="gb2312" isErrorPage="true" %>
    <html>
    <head>
        <title>error.jsptitle>
    head>
    <body>
       对不起,你的操作有误
    body>
    html>
    
  • web.xmlweb.xml注册该页面

    
    
    <error-page>
        <exception-type>java.lang.Exceptionexception-type>
        <location>/error.jsplocation>
    error-page>
    
  • makeErrorTest.jsp

    <%@ page language="java" pageEncoding="gb2312" %>
    <html>
    <head>
        <title>makeErrorTest.jsptitle>
    head>
    <body>
    <%
        String account =(String)session.getAttribute("account");
        out.print(account.length());
        //运行该页面,会报一个异常,Servlet容器会自动根据web.xml中的配置找到异常对应的页面
        //这样所有的Exception就被error.jsp统一处理了
    %>
    body>
    html>
    

你可能感兴趣的:(JavaWeb,servlet,Javaweb,Java)