JavaWeb——Servlet

          • 请求转发是一次转发
          • 请求转发URL地址不会发生变化,会保留当前Servlet的资源访问路径
          • 共享同一个Request作用域,可用于多页面之间传递数据
    • getServletContext()
      • 返回一个ServletContext()对象
    • 获取请求头信息
      • getHeader(String key)根据key获取value
        • 例如 request.getHeader("User-Agent")
      • getHeaderNames()获取所有请求头名称
        • 返回一个Enumeration<String>对象
          • 类似集合迭代器的对象
            • hasMoreElements()
              • 返回boolean值
              • 判断是否有下一个元素
            • nextElement()
              • 返回下一个元素

      @Override
      protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      response.setContentType("text/html;charset=UTF-8");
      PrintWriter out = response.getWriter();
      Enumeration<String> headerNames = request.getHeaderNames();
      out.println("

      ");
      //Enumeration是一个类似集合迭代器的对象,可以存放多个数据,需要循环获取每个元素对象
      while (headerNames.hasMoreElements()) {
      String head = headerNames.nextElement();
      out.println( head + "=" + request.getHeader(head) + "
      ");
      }
      out.println("

      ");
      }

    • 获取请求网络数据
      • getMethod()
        • 获取网络请求的请求方式
      • getProtocol()
        • 获取网络协议
      • getLocalPort()
        • 获取请求的端口
      • getServletPath()
        • 获取请求资源的路径
        • 如:/servlet
      • getRequestURI()
        • 获取请求的资源路径,包括应用上下文访问路径+请求的资源路径
        • 应用上下文访问路径/请求资源的路径
        • /web01/servlet
      • getRequestURL()
      • getContextPath()
        • 获取应用上下文访问路径
        • /web01
        • 在请求资源路径之前动态获取应用上下文访问路径,避免因为应用上下文访问路径问题导致资源无法访问
          • <a href = "<%=request.getContextPath()%>/servlet">超链接</a>

      //获取请求方式
      String method = request.getMethod();
      out.println("请求方式 =" + method + "
      ");//请求方式 =GET
      //获取请求协议
      String protocol = request.getProtocol();
      out.println("请求协议 =" + protocol + "
      ");//请求协议 =HTTP/1.1
      //获取请求资源的路径
      String servletPath = request.getServletPath();
      out.println("servletPath = " + servletPath + "
      ");//servletPath = /servlet
      //获取请求URI 包括应用上下文对象+请求的资源路径
      String requestURI = request.getRequestURI();
      out.println("URI =" + requestURI + "
      ");//URI =/web01/servlet
      //获取请求URL地址栏完整路径 包括 协议+ip+端口+应用上下文访问路径+请求的资源路径
      StringBuffer requestURL = request.getRequestURL();
      out.println("URL =" + requestURL + "
      ");//URL =http://localhost:8080/web01/servlet
      //获取请求的应用上下文访问路径
      String contextPath = request.getContextPath();
      out.println("contextPath = " + contextPath);//contextPath = /web01

HttpServletResponse用户响应对象

  • 常用方法
    • setCharacterEncoding(String charSet)设置输出编码格式
      • 传入一个String类型的编码格式
    • setContextType("text/html;charset=UTF-8")
      • 设置响应数据的数据类型为html字符串,编码格式为UTF-8
    • getWriter() 返回一个Writer类型的字符输出流对象,利用该对象可以向页面输出文本或Html
      • 不推荐Servlet中进行数据输出,Servlet主要负责逻辑处理
    • setContentLength()
      • 设置响应时的响应数据大小
    • 设置响应头
      • 不支持中文
      • setHeader(String key,String value)
      • setDateHeader(String key,Date value)
      • setIntHeader(String key,int value)
    • sendRedirect(String url)重定向
      • 可以跳转到某url
      • 重定向是2次请求,地址栏会保留重定向的资源地址,不会共享同一个Request Scope(请求作用域)
      • 可以写uri,但是可能会出问题,建议使用url

请求转发与重定向

  • 区别
    • 转发地址栏不变,转发请求1次,转发时不写工程虚拟路径
      • 地址栏不变可防止重复发送请求
    • 重定向地址栏变化,请求2次,重定向要写工程虚拟路径

      protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      //请求转发
      request.getRequestDispatcher("/servlet03");
      }

      @Override
      protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
      //重定向
      resp.sendRedirect(req.getContextPath() + "/servlet03");
      }

  • 应用场景

    • 重定向
      • 登录、购物车结算
    • 请求转发
      • 其余
  • setHeader("Content-Disposition","attachment;filename=" + file.getName())
    • 设置响应头,请求以下载的方式处理,以及下载文件时的默认文件名称
  • response.setContentLength((int)file.length());
    • 设置响应时的响应数据大小(利用文件大小设置)
  • Servlet与JSP的跳转
    • jsp跳Servlet
      • a标签
      • js(location.href='xxx')
      • form表单action属性
    • Servlet跳jsp
      • 重定向:response.sendRedirect(String url)
      • 请求转发: request.getRequestDispatcher(String uri).forward(request,response)
    • servlet跳servlet
      • 推荐重定向

下载功能的实现

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置响应输出编码格式,避免文件名中文乱码
        response.setContentType("text/html;charset=UTF-8");
        //获取输入流
        //获取响应输出流
        BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());

        File file =new  File(request.getServletContext().getRealPath("/images/img.png"));
        //获取输入流
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));

        //设置响应头,请求以下载的方式处理,以及下载文件时的默认文件名称
        response.setHeader("Content-Disposition","attachment;filename=" + file.getName());

        //设置响应时的响应数据大小(利用文件大小设置)
        response.setContentLength((int)file.length());

        byte[] bytes = new byte[1024];
        int length = 0;
        while ((length = bis.read(bytes)) != -1) {
            bos.write(bytes, 0,length);
        }
        //刷新缓存,数据推送
        bos.flush();
    }

图片验证码的实现

  • 引入的包
    • Hutool

      <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.26</version> </dependency>
  • 后端

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //定义图形验证码的父接口
    ICaptcha lineCaptcha = null;

      /**创建一个图形验证码对象
       * param1:宽度
       * param2:高度
       * param3:字符数量
       * param4:干扰线条数量
       */
      lineCaptcha = new LineCaptcha(200,80,5,3);
      //验证码生成
      lineCaptcha.createCode();
    
      //获取验证码信息
      //后期我们应该将这个数据存入Session或其他某些其他容器中等待与用户输入的验证码校验
      String code = lineCaptcha.getCode();
    
      //使用输出流输出验证码图片到浏览器
      response.setContentType("text/html;UTF-8");
      ServletOutputStream sos = response.getOutputStream();
      lineCaptcha.write(sos);
      sos.close();
    

    }

  • 前端

    <body> <form method="post" action="servlet"> 用户名:
    密  码 :
    验证码: <%--利用JSP脚本表达式,在请求资源路径之前通过动态获取应用上下文对象,避免通过应用上下文对象访问路径问题导致资源无法访问--%>
    看不清,换一张
    </form> </body> <script type="text/javascript"> window.onload = function () { document.getElementById("reset").addEventListener("click",function () { //添加单击事件修改img路径,但是链接必须发生变化,因此使用时间戳 document.getElementById("myImg").src = "<%= request.getContextPath() %>/servlet?timeStemp=" + new Date().getTime() }) } /* var reset = function() {
          }*/
    
    </script>
  • 细节:

    • get请求重新执行要求链接不同,可通过添加时间戳实现

ServletConfig 初始化参数对象

  • 常用方法
    • getInitParameter(String key)
      • 获取xml文件或注解中的初始化参数,返回String
  • 在非init方法中取得ServletConfig对象
    • this.getServletConfig()

ServletContext

  • 常用方法
    • getRealPath(String uri)
      • 获取uri指向资源的绝对路径
        • servletContext().getRealPath("/")
          • 获取根目录真实路径
        • servletContext().getRealPath("/images/img.png")
          • 获取根目录下/images/img.png文件的真实目录

生命周期

  • 注意:
    • 单例模式,整个Tomcat生命周期中,每个Servlet只会被创建一次

a. init()初始化

    • Servlet对象创建完成后被调用,因为Servlet是单例的,所以整个Tomcat生命周期中只会被调用一次

    • 可与初始化参数配合使用,为Servlet类添加成员变量

    • 必须调用super.init(),否则无法为当前类中的init()属性进行赋值,无法调用init方法以外的其他方法获取config对象

      @Override
      public void init(ServletConfig config) throws ServletException {
          //调用super.init(config)当前类中的config属性赋值
          super.init(config);
          name = config.getInitParameter("name");
          age = config.getInitParameter("age");
      }
      

b. service()请求进入时

    • 每次请求进入Servlet都会执行一次这个方法,用于分析请求是get还是post,根据请求方式帮助我们调用doGet或doPost方法
    • 注意:必须利用super调用父类中的service方法,否则不会进入doGet或doPost()

c. destroy()销毁

    • Servlet销毁时执行,,因为Servlet是单例的,所以整个Tomcat生命周期中只会被调用一次
    • Servlet销毁的时机是Tomcat容器关闭时,用于释放一些资源

d. 初始化参数

ⅰ. 基于XML方式
<?xml version="1.0" encoding="UTF-8"?>
<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>servelet</servlet-name>
        <servlet-class>com.wry.servlet.Servlet</servlet-class>
        <init-param>
            <param-name>i</param-name>
            <param-value>1</param-value>
        </init-param>
        <init-param>
            <param-name>j</param-name>
            <param-value>100</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>servelet</servlet-name>
        <url-pattern>/servlet</url-pattern>
    </servlet-mapping>
</web-app>
ⅱ. 取得初始化参数的值
  • 通过成员变量共享属性值
    • Servlet的init方法只会执行一次,Servlet是单例的。非线程安全的,当出现并发访问,共享数据无法保证一致性.在使用Servlet不要定义共享成员变量.

      public class Servlet extends HttpServlet {
      private String name;
      private String age;

      @Override
      public void init(ServletConfig config) throws ServletException {
          name = config.getInitParameter("name");
          age = config.getInitParameter("age");
      }
      

      }

  • 通过在方法中获取ServletConfig对象获取初始化参数的值

    • 必须在init()方法中调用super.init(config),否则GennericServlet类中的config属性为null,无法获取到ServletConig对象

    • 利用这种方法,既可以获取初始化参数,又可以避免线程安全问题

      public class Servlet extends HttpServlet {

      @Override
      public void init(ServletConfig config) throws ServletException {
          super.init(config);
      }
      
      /**
       * 用于处理get请求
       * @param request
       * @param response
       * @throws ServletException
       * @throws IOException
       */
      @Override
      protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
          response.setCharacterEncoding("UTF-8");
          //利用用户响应对象获取输出流
          PrintWriter out = response.getWriter();
          out.print(("<h1>收到一个get请求</h1>"));
      
          //获取ServletConfig对象
          ServletConfig config = this.getServletConfig();
          //获取name属性值
          String name1 = config.getInitParameter("name");
          out.println(name1);
      }
      

      }

ⅲ. 设置Servlet值的初始化时机
  • 通过<Servlet>中的<load-on-startup>标签指定创建实值
    • 只要该标签值大于等于1即可在Tomcat启动时创建Servlet对象
    • 如果有多个Servlet需要在启动时创建,可以利用这个数值决定创建顺序,如果数值相同则按照名称排序决定加载顺序
  • 如果是基于注解配置Servlet则需要在@WebServlet注解中指定loadOnStartup来指定Servlet创建时机值,取值为整数类型

    <servlet> <servlet-name>servelet</servlet-name> <servlet-class>com.wry.servlet.Servlet</servlet-class> <init-param> <param-name>name</param-name> <param-value>Zhangsan</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet>
  • JSP和Servlet的对比

Servlet中虽然可以写标签、css样式等,但使用起来没有在jsp或者html中书写方便。JSP可以做的事情,Servlet同样可以完成,只不过两者侧重点不同:JSP多用于数据展示,Servlet多用于逻辑控制。

相关推荐
m0_571957581 小时前
Java | Leetcode Java题解之第543题二叉树的直径
java·leetcode·题解
一点媛艺2 小时前
Kotlin函数由易到难
开发语言·python·kotlin
姑苏风2 小时前
《Kotlin实战》-附录
android·开发语言·kotlin
奋斗的小花生3 小时前
c++ 多态性
开发语言·c++
魔道不误砍柴功3 小时前
Java 中如何巧妙应用 Function 让方法复用性更强
java·开发语言·python
NiNg_1_2343 小时前
SpringBoot整合SpringSecurity实现密码加密解密、登录认证退出功能
java·spring boot·后端
闲晨3 小时前
C++ 继承:代码传承的魔法棒,开启奇幻编程之旅
java·c语言·开发语言·c++·经验分享
老猿讲编程3 小时前
一个例子来说明Ada语言的实时性支持
开发语言·ada
Chrikk4 小时前
Go-性能调优实战案例
开发语言·后端·golang
幼儿园老大*4 小时前
Go的环境搭建以及GoLand安装教程
开发语言·经验分享·后端·golang·go