4.Servlet

Servlet

一、Servlet基础

servlet是什么

其实就是一个Java程序,运行在web服务器上,用于接收和响应客户端的http请求.

更多的是配合动态资源来做.当静态资源也需要使用带servlet,只不过是Tomcat里面已经定义好的一个DefaultServlet.

Hello Servlet

1.写一个web工程,要有一个服务器

2.测试运行web工程

        1.创建一个类,实现servlet接口
        2.配置servlet,用意 : 告诉服务器,我们的引用有这么些个servlet
        
            再webContent/WEB-INF/web.xml里卖弄写下以下内容.
            
              <!--   向tomcat报告,引用里面有一个servlet,名字叫做HelloServlet,具体的路径是com.firstweb.HelloServelet -->
              <servlet>
                   <servlet-name>HelloServlet</servlet-name>
                   <servlet-class>com.firstweb.HelloServelet</servlet-class>
              </servlet>

              <!--   注册servlet的映射,servletName : 找到赏面注册的具体servlet,url-pattern : 在地址栏上的path,一定要以/打头 -->
              <servlet-mapping>
                    <servlet-name>HelloServlet</servlet-name>
                    <url-pattern>/hello</url-pattern>
              </servlet-mapping>
         3.在地址栏上输入http://localhost:8080/项目名称

Servlet执行过程

在这里插入图片描述

Servlet通用写法

      Servlet (接口)
          |
          |
    GenericServlet
          |
          |
     HttpServlet (用于处理http的请求)

1.定义一个类,继承HttpServlet,复写doGet和doPost

在这里插入图片描述

Servlet的生命周期

  • 生命周期

从创建到销毁的一段时间

  • 生命周期方法

从创建到销毁所调用的那些方法

  • 主要方法
    • init方法

        1.在创建该Servlet的是历史,就执行该方法
        2.一个servle只会初始化一次init方法
        3.默认情况下,初次访问该servlet才会创建实例
      
    • service方法

        1.只要客户端来了一个请求,那么就执行一次该方法
        2.该方法可以被执行多次
      
    • destory方法

        1.servlet销毁的时候,就会执行该方法
            ①该项目冲tomcat里里面移出
            ②正常关闭tomcat就会执行shutdown.bat
      

doGet和doPost不算生命周期方法,所谓生命周期方法是指,冲对象的创建到销毁一定会执行的方法,但是这两个方法不一定会被执行.

让servlet创建实例的时机提前

1.默认情况下,只有在初次访问servlet的时候,才会执行init方法,有时候我们可能需要在这个方法里执行一些初始化工作,甚至是做一些比较耗时的逻辑.
2.那么这个时候,初次访问,可能会在init方法中逗留较旧的时间,所以需要使初始化的时间提前一点.
3.在配置的时候,使用load-on-start元素来指定,给定的数字越小,启动的时机就越早,一般不写负数,从2开始即可.

       <servlet>
             <servlet-name>HelloServlet</servlet-name>
             <servlet-class>com.firstweb.HelloServelet</servlet-class>
             <load-on-startup>2</load-on-startup>
        </servlet>

二、ServletConfig

    //1.得到servlet配置对象,专门用于在配置servlet的信息
    ServletConfig config = getServletConfig();
    
          //获取道德是配置servlet里面的servlet-name的文本内容
          String servletName = config.getServeletName();
          System.out.println("servletName=" + servletName);
    
    //2.可以获取具体的某一个参数
    String address = config.getInitParameter("address");
    System.out.println("address=" + address);
    
    //3.获取所有参数的名称
    Enumeration<String> names = config.getInitParameterNames();
          //遍历所有的参数名称
          while(name.hashMoreElements()){
                  String key = (String) names.nextElement();
                  String value = config.getInitParameter(key);
                  System.out.println("key=" + key + " value=" + value);  
          }  

使用他人开发的servlet,如果刚好这个servlet里面需要一个数字或者变量,我们在注册servlet时,需要在web.xml里生命init-params.

三、HttpServletRequest和HttpServletResponse

Servlet配置方式

  • 1.全路径匹配

    • 以 / 开始 /a /aa/bb

    • localhost:8080/项目名称/aa/bb

  • 2.路径匹配,前半段匹配

    • 以 / 开始,以 * 结束 /a/*

    • *其实时一个配符,匹配任意文字

    • localhost:8080/项目名称/*

  • 3.以扩展名匹配

    • 写法: /*.扩展名 /*.aa /*.bb

四、ServletContext

  • Servlet 上下文

每个java虚拟机中的每个web工程只有一个ServletContext对象

ServletContxet的作用

1.可以获取全局变量

2.可以获取web应用中的资源

3.存取数据,servlet间共享数据 域对象

1.可以获取全局变量
  • 声明
        <context-param>
                <param-name>address</param-name>
                <param-name>北京</param-name>
        </context-param>
  • 获取
      //强制类型转换
      String address = (String)getServletContext().getInitParameter("address");

      ServeletContext context = getServletContext();
      String address = context.getInitParameter("address");
2.可以获取web应用中的资源
  • 获取资源在tomcat里面的绝对路径

    • 到的是项目在tomcat里面的根目录

      ontext.getRealpath("");
    • 这里得到的是文件的绝对路径

      String path = context.getRealPath("file/config.properties");
         //1.ServletContext对象
         ServletContext context = getServletContext();
         //获取给定文件在服务器上的绝对路径
         String path = context.getRealPath("file/config.properties");
    
         //2创建属性对象
         Properties properties = new Properties();
         InputStream is = new FileInputStream(path);
         properties.load(is);
    
         //3.获取name属性的值
         String naem = properties.getProperty("name");
    
  • getResourceAsStream获取资源流对象

在这里插入图片描述

  • 根据classloader去获取工程下的资源 加载器(JDBC)<

在这里插入图片描述

3.存取数据,servlet间共享数据 域对象

在这里插入图片描述

  • ①定义一个html页面,定义一个form表单

    •  login.html
      
             <body>
                  <h2>请输入以下内容,完成登录</h2>
      
                   <form action="LoginServlet" method="get">
                       账号: <input type="text" name="username"/><br> 
                       密码: <input type="password" name="password"/><br>
                       <input type="submit" value="登录"/>
                   </form>
      
             </body>
      
    • 细节处理
                 <!--      A路径:Servlet的路径: -->
                 <!--             http:localhost:8080/Demo04/LoginServlet -->
                 <!--      B路径:当前这个html的路径 -->
                 <!--              http:localhost:8080/Demo04/login.html -->
      
                  <!-- 所以action的值为servlet的路径 -->
                  <form action="LoginServlet" method="get">
      
                   <!-- 也可以写绝对路径路径 -->
                   <form action="/Demo04/LoginServlet" method="get">
      
  • ②定义一个Servlet,名为LoginServlet


LoginServlet.java

      protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.获取数据
        String userName = request.getParameter("username");
        String password = request.getParameter("password");

        //2.校验数据
       }
  • ③针对成功或者失败,进行判断,然后跳转新页面
LoginServlet.java

     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
       //1.获取数据
       String userName = request.getParameter("username");
       String password = request.getParameter("password");

       //2.校验数据

       //向客户端输出内容
       PrintWriter pw = response.getWriter();

       if("admin".equals(userName) && "123".equals(password)){
        //跳转到成功得界面
       
        //设置状态码 重新定位 状态码
        response.setStatus(302);
        //定位跳转到得页面
        response.setHeader("Location", "login_success.html");
       }
       else{
        pw.write("login failed!");
       }
      }
  • ④统计成功登录次数
       if("admin".equals(userName) && "123".equals(password)){
          //1.成功的次数累加

          //获取以前的数据,在旧值得基础上加1
          Object obj = getServletContext().getAttribute("count");
          //默认就是0
          int totalCount = 0;
          if(obj != null) {
           totalCount = (int)obj;
          }
          //累加
          getServletContext().setAttribute("count", totalCount + 1);


            //2.跳转到成功得界面
          }

  • ⑤在界面上显示成功登录数量

    在这里插入图片描述
       <body>
            <h2>登录成功</h2>
            <a href="CountServlet">获取网站登陆成功总数</a>
       </body>
          protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                PrintWriter pw = response.getWriter();
                int Count = (int)getServletContext().getAttribute("count");
                pw.write("登录人数:" + Count);
           }

Servlet何时创建,何时销毁

创建:服务器启动的时候,会为托管得每一个web应用程序创建一个servletContext对象。
销毁:从服务器移除托管,或者是关闭服务器。

  • ServletContext 的作用范围

只要在这个项目里面都可以取数据

五、HttpServletRequest

这个对象封装了客户端提交过来的所有数据。

1.获取头信息
     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     
          //1.取出请求里面的所有头信息,得到一个枚举集合
           Enumeration<String> headerNames = request.getHeaderNames();
           while(headerNames.hasMoreElements()) {
                String name = (String)headerNames.nextElement();
                String value = request.getHeader(name);
                System.out.pr intln(name + " = " + value);
            }  
     }
得到的头数据
  accept = image/gif, image/jpeg, image/pjpeg, application/x-ms-application, application/xaml+xml, application/x-ms-xbap, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
  accept-language = zh-Hans-CN,zh-Hans;q=0.8,en-US;q=0.5,en;q=0.3
  cache-control = no-cache
  ua-cpu = AMD64
  accept-encoding = gzip, deflate
  user-agent = Mozilla/5.0 (Windows NT 6.2; Win64; x64; Trident/7.0; rv:11.0) like Gecko
  host = localhost:8080
  connection = Keep-Alive
  accept = image/gif, image/jpeg, image/pjpeg, application/x-ms-application, application/xaml+xml, application/x-ms-xbap, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*
  accept-language = zh-Hans-CN,zh-Hans;q=0.8,en-US;q=0.5,en;q=0.3
  cache-control = no-cache
  ua-cpu = AMD64
  accept-encoding = gzip, deflate
  user-agent = Mozilla/5.0 (Windows NT 6.2; Win64; x64; Trident/7.0; rv:11.0) like Gecko
  host = localhost:8080
  connection = Keep-Alive
2.获取请求体信息
      protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
             //2.获取请求体数据,即客户端提交的数据
             String name = request.getParameter("name");
             String address = request.getParameter("address");

             //获取所有参数,得到一个枚举集合
             Enumeration<String> parameterNames = request.getParameterNames();

             //获取所有参数,得到一个枚举集合,一个key可以对应多个值
             Map<String, String[]> parameterMap = request.getParameterMap();
             Set<String> keySet = parameterMap.keySet();
             Iterator<String> iterator = keySet.iterator();
             while(!iterator.hasNext()) {
              String key = (String)iterator.next();
              String value = parameterMap.get(key)[0]; //对应第一个值
             //String value1 = parameterMap.get(key)[1];
             }
       }
3.获取中文数据

客户端提交给服务器端的数据中如果带有中文,有可能出现乱码情况,可以参照一下的方法解决。

  • 如果是GET方式

    • 1.编码转换
            protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                   String userName = request.getParameter("username");
    
                   //GET请求过来的数据,在rul地址栏上就已经经过编码了,所有我们得到的是乱码
                   //tomcat收到了这批数据,getParameter默认使用ISO-8859-1去解码,XXX.getBytes("ISO-8859-1")
                   //先让文字回到ISO-8859-1对应的字节数组,然后再按utf-8编码
    
                   userName = new String(userName.getBytes("ISO-8859-1"),"UTF-8");
            }
    
    • 2.直接在tomcat里面做配置(conf/server.xml,加上URIEncoding=“utf-8”),以后get请求的数据就都用utf-8编码
      在这里插入图片描述
  • 如果是POST方法


      //doPost调用DoGet方法
      protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

             //这个说的是设置请求体里面的文字编码,对get方式无效
             request.setCharacterEncoding("UTF-8"); 
             //这行设置一定要写在getParameter之前

             String userName = request.getParameter("username");
        }

六、HttpServletResponse

负责返回数据给客户端。

1.返回数据

  • 输出数据到页面上
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
               //以字符流的方式写数据
               response.getWriter().write("<h1>hello response...</h1>");
               //以字节流的方式写数据,注意getBytes()
               response.getOutputStream().write("<h1>hello response...222</h1>".getBytes());
               //设置当前请求的处理状态码
               response.setStatus("");
               //设置一个头
               response.setHeader(name, value);
               //设置响应的内容类型,以及编码
               response.setContentType(type);
         }
    
  • 响应的数据中有中文,那么可能出现乱码
    • 以字符流输出
          //这里写出去的文字,默认使用的是ISO-8859-1,我们可指定编码类型
          //1.指定输出到客户端的时候,文字使用UTF-8编码
          response.setCharacterEncoding("UTF-8");
          
          //2.指定浏览器得到数据时,使用UTF-8解码
          response.setHeader("Content-Type", "text.html;charset=UTF-8");
          
          //以字符流的方式写数据
          response.getWriter().write("<h1>你好响应</h1>");
    
    • 以字节流输出
           //1.指定浏览器得到数据时,使用的码表
           response.setHeader("Content-Type", "text.html;charset=UTF-8");
           //2.指定输出中文使用的码表,默认为UTF-8
           // response.getOutputStream().write("你好,响应".getBytes("UTF-8"));
           response.getOutputStream().write("你好,响应".getBytes());
    
    • 不管是字节流还是字符流,可直接使用一行代码,然后写数据即可
         //设置响应的数据类型是UTF-8,并且告知浏览器使用UTF-8来编码
         response.setContentType("text.html;charset=UTF-8");
    

2.下载文件

  • 使用Tomcat的默认servlet去提供下载
    index.html
    
         让Tomcat的默认servlet去提供下载<br>
               <a href="download/aa.jpg">aa.jpg</a><br>
                <a href="download/bb.txt">bb.txt</a><br>
                 <a href="download/cc.rar">cc.rar</a><br>
    
  • 手动编码提供下载
    • index.html
          手动编码提供下载<br>
             <a href="Demo01?filename=aa.jpg">aa.jpg</a><br>
             <a href="Demo01?filename=bb.txt">bb.txt</a><br>
             <a href="Demo01?filename=cc.rar">cc.rar</a><br>
    
    • Demo01.java
         protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
          //1.获取需要下载的文件名字 ----inputStream
          String fileName = request.getParameter("filename");
    
          //2.获取该文件在tomcat下的绝对路径
          //注意download后面的斜杠
          String path = getServletContext().getRealPath("download/"+fileName);
    
         //3.让浏览器收到资源时,一下在的方式提醒用户,而不是直接展示
          response.setHeader("Content-Disposition", "attachment;filename="+fileName);
        }
    
    • 以流的形式输出
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                String fileName = request.getParameter("filename")
                String path = getServletContext().getRealPath("download/"+fileName);
                 response.setHeader("Content-Disposition", "attachment;filename="+fileName);
                //转化成输出流
                InputStream is = new FileInputStream(path);
                OutputStream os = response.getOutputStream();
    
                int len = 0;
                byte[]buffer = new byte[1024];
                while((len = is.read(buffer)) != -1) {
                 os.write(buffer,0,len);
                }
                os.close();
                is.close();
      }
    

3.中文名文件下载

  • 手动编码提供下载
      <a href="Demo01?filename=张三.txt">张三.txt</a><br>
    
  • 对中文进行编码
    • 对得到的文件名进行重新编码
           fileName = new String(fileName.getBytes("ISO-8859-1"),"UTF-8");	  
    
    • 根据浏览器类型编码
           /*
            * 如果是IE、Chrome浏览器,使用URLEncoding编码
            * 如果是Firefox,使用Base64编码
            */
           //获取来访的而客户端类型
           String clientType = request.getHeader("User-Agent");
    
           if(clientType.contains("Firefox")) {
              fileName = DownLoadUtil.base64EncodeFileName(fileName);
           }else {
            fileName = URLEncoder.encode(fileName, "UTF-8");
           }
    
    • base64编码
      • Java如何进行Base64的编码(Encode)与解码(Decode)
      • DownLoadUtil类的实现
            import java.io.UnsupportedEncodingException;
            import java.util.Base64;
        
            public class DownLoadUtil {
               public static String base64EncodeFileName(String fileName) {
                     Base64.Encoder base64Encoder = Base64.getEncoder(); 
                     try {
                         return "=?UTF-8?B?" + new String(base64Encoder.encode(fileName.getBytes("UTF-8"))) + "?=";
                     }catch(UnsupportedEncodingException e) {
                         e.printStackTrace();
                      throw new RuntimeException();
                     }
                 }
            }
        
        

七、重定向和请求转发

重定向

  • 代码
   	//以前的写法
	response.setStatus(302);
	response.setHeader("Location", "login_success.html");
	// 重定向的写法:参数--跳转的位置
	response.sendRedirect("login_success.html");
  • 特点
    • 1.地址上显示的是最后那个资源的路径地址
    • 2.请求的次数至少有两次,服务器在一次请求后,会返回一个302以及一个地址,浏览器根据这个地址执行第二次访问。
    • 3.可以跳转到任意路径
    • 4.效率稍微低一点,执行两次请求。
    • 5.后续的请求,没法使用上一次的request存储的数据,或者没法使用上一次的request对象,因为两次的请求不同。

请求转发

  • 代码
    //请求转发的写法:参数--跳转的位置
    request.getRequestDispatcher("login_success.html");
  • 特点
    • 1.地址栏上显示的是请求servlet的地址
    • 2.请求次数只有一次,服务器内部版客户执行了后续的操作
    • 3.只能跳转自己项目的资源路路径
    • 4.效率稍微搞一单,执行一次请求
    • 5.可以使用上一次的request对象

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值