Servlet

1.Servlet简介

  • Servlet是sun公司开发动态web的一门技术

  • sun在这些API中提供了一个接口叫Servlet,开发Servlet程序的步骤:

    • 编写一个类,实现Servlet接口
    • 把开发好的Java类部署到web服务器中

    把实现了Servlet接口的Java程序叫做Servlet

2.HelloServlet创建流程

  1. 构建一个普通的Maven项目,删掉里面的src目录,然后建立新的model,可写多个项目,这个空的工程就是Maven主工程

  2. 关于Maven父子工程的理解

    父项目中会有

    <modules>
        <module>servlet01</module>
    </modules>
    

    子项目中会有

    <parent>
        <artifactId>javaweb01_servlet</artifactId>
        <groupId>com.java</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    

    父项目中的java子项目可以直接使用

  3. Maven环境优化:

    1. 修改web.xml与Tomcat版本对应
    2. 将maven的结构搭建完整(建java和resources文件夹)
  4. 编写一个servlet

    1. 编写一个普通类
    2. 实现Servlet接口,直接继承HttpServlet
    public class HelloServlet extends HttpServlet {
        //由于get和post只是请求实现的方式不同,可以互相调用,业务逻辑一样
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //ServletOutputStream outputStream = resp.getOutputStream();
            PrintWriter writer = resp.getWriter(); //响应流
            writer.print("Hello,Servlet");
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
    
  5. 编写Servlet的映射:Java程序通过浏览器访问时,需要连接web服务器,所以需要在web服务中注册所写的Servlet,并且需要配置一个地址

    <!--注册Servlet-->
    <servlet>
        <servlet-name>hello</servlet-name>
        <servlet-class>com.java.servlet.HelloServlet</servlet-class>
    </servlet>
    <!--Servlet的请求路径-->
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
    
  6. 配置Tomcat

  7. 启动测试

3.Servlet原理

Servlet是由web服务器调用,web服务器在收到浏览器的请求之后,就会进行以下操作: Servlet原理

4.Mapping

  1. 一个Servlet可以指定一个映射路径

    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
    
  2. 一个Servlet可以指定多个映射路径

    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello1</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello2</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello3</url-pattern>
    </servlet-mapping>
    
  3. 一个Servlet可以指定通用映射路径

    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello/*</url-pattern>
    </servlet-mapping>
    
  4. 默认请求路径(一般用来写404,500等错误页面)

    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
    
  5. 指定一些后缀.abc

    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>*.abc</url-pattern>
    </servlet-mapping>
    
  6. 优先级问题:指定了固有的映射路径优先级最高,如果找不到就会走默认的请求路径

    <!--404-->
    <servlet>
        <servlet-name>error</servlet-name>
        <servlet-class>com.java.servlet.ErrorServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>error</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
    

5.ServletContext对象

web容器在启动的时候,会为每个web程序创建一个对应的ServletContext对象,塔代表了当前web应用,ServletContext的作用:

  • 共享数据:在一个Servlet中保存的数据,可以在另一个Servlet中拿到

    //放数据
    public class SetServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            ServletContext context = this.getServletContext();
            String username = "小明";
            context.setAttribute("name",username); //将数据保存到ServletContext中,名字为name,值为username
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
    
    //取数据
    public class GetServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
            ServletContext context = this.getServletContext();
            String name = (String) context.getAttribute("name");
            System.out.println(name);
            
            resp.setContentType("text/html");
            resp.setCharacterEncoding("utf-8");
            resp.getWriter().print("名字:" + name);
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
    
    <servlet>
        <servlet-name>setName</servlet-name>
        <servlet-class>com.java.servlet.SetServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>setName</servlet-name>
        <url-pattern>/setName</url-pattern>
    </servlet-mapping>
    <servlet>
        <servlet-name>getName</servlet-name>
        <servlet-class>com.java.servlet.GetServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>getName</servlet-name>
        <url-pattern>/getName</url-pattern>
    </servlet-mapping>
    
  • 获取初始化参数

    public class ServletDemo extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
            ServletContext context = this.getServletContext();
            String url = context.getInitParameter("url");
            resp.getWriter().print(url);
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
    
    <!--配置一些web应用初始化参数-->
    <context-param>
        <param-name>url</param-name>
        <param-value>jdbc:mysql://localhost:3306/mybatis</param-value>
    </context-param>
    <servlet>
        <servlet-name>getURL</servlet-name>
        <servlet-class>com.java.servlet.ServletDemo</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>getURL</servlet-name>
        <url-pattern>/getURL</url-pattern>
    </servlet-mapping>
    
  • 请求转发

    public class ServletDemo extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
            ServletContext context = this.getServletContext();
            RequestDispatcher requestDispatcher = context.getRequestDispatcher("/getURL"); //转发的请求路径
            requestDispatcher.forward(req,resp); //调用forward实现请求转发
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
    
  • 读取资源文件

    • 在java中新建一个properties

      InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/com/java/servlet/aaa.properties");
      
    • 在resources中新建一个properties

      username=root
      password=123456
      
      public class ServletDemo02 extends HttpServlet {
          @Override
          protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");
              Properties properties = new Properties();
              properties.load(is);
              String username = properties.getProperty("username");
              String password = properties.getProperty("password");
              System.out.println(username + password);
          }
      
          @Override
          protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              doGet(req, resp);
          }
      }
      

6.HttpServletResponse

web服务器接收到客户端的http请求,针对这个请求分别创建一个代表请求的HttpServletRequest对象,代表响应的一个HttpServletResponse;

  • 如果要获取客户端请求过来的参数:HttpServletRequest

  • 如果要给客服端响应一些信息:HttpServletResponse

  • 简单分类:

    1. 负责向浏览器发送数据的方法

      ServletOutputStream getOutputStream() throws IOException;
      PrintWriter getWriter() throws IOException;
      
    2. 负责向浏览器发送响应头的方法

      void setCharacterEncoding(String var1);
      void setContentLength(int var1);
      void setContentLengthLong(long var1);
      void setContentType(String var1);
      void setDateHeader(String var1, long var2);
      void addDateHeader(String var1, long var2);
      void setHeader(String var1, String var2);
      void addHeader(String var1, String var2);
      void setIntHeader(String var1, int var2);
      void addIntHeader(String var1, int var2);
      
    3. 响应的状态码

      int SC_CONTINUE = 100;
      int SC_SWITCHING_PROTOCOLS = 101;
      int SC_OK = 200;
      int SC_CREATED = 201;
      int SC_ACCEPTED = 202;
      int SC_NON_AUTHORITATIVE_INFORMATION = 203;
      int SC_NO_CONTENT = 204;
      int SC_RESET_CONTENT = 205;
      int SC_PARTIAL_CONTENT = 206;
      int SC_MULTIPLE_CHOICES = 300;
      int SC_MOVED_PERMANENTLY = 301;
      int SC_MOVED_TEMPORARILY = 302;
      int SC_FOUND = 302;
      int SC_SEE_OTHER = 303;
      int SC_NOT_MODIFIED = 304;
      int SC_USE_PROXY = 305;
      int SC_TEMPORARY_REDIRECT = 307;
      int SC_BAD_REQUEST = 400;
      int SC_UNAUTHORIZED = 401;
      int SC_PAYMENT_REQUIRED = 402;
      int SC_FORBIDDEN = 403;
      int SC_NOT_FOUND = 404;
      int SC_METHOD_NOT_ALLOWED = 405;
      int SC_NOT_ACCEPTABLE = 406;
      int SC_PROXY_AUTHENTICATION_REQUIRED = 407;
      int SC_REQUEST_TIMEOUT = 408;
      int SC_CONFLICT = 409;
      int SC_GONE = 410;
      int SC_LENGTH_REQUIRED = 411;
      int SC_PRECONDITION_FAILED = 412;
      int SC_REQUEST_ENTITY_TOO_LARGE = 413;
      int SC_REQUEST_URI_TOO_LONG = 414;
      int SC_UNSUPPORTED_MEDIA_TYPE = 415;
      int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
      int SC_EXPECTATION_FAILED = 417;
      int SC_INTERNAL_SERVER_ERROR = 500;
      int SC_NOT_IMPLEMENTED = 501;
      int SC_BAD_GATEWAY = 502;
      int SC_SERVICE_UNAVAILABLE = 503;
      int SC_GATEWAY_TIMEOUT = 504;
      int SC_HTTP_VERSION_NOT_SUPPORTED = 505;
      
  • 常见应用:

    1. 向浏览器输出消息(getWriter)

    2. 下载文件

      public class FileServlet extends HttpServlet {
          @Override
          protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              //1. 获取下载文件的路径
              String realPath = this.getServletContext().getRealPath("\\WEB-INF\\classes\\都市.png");
              System.out.println("下载文件的路径:" + realPath);
              //2. 获取文件下载名
              String fileName = realPath.substring(realPath.lastIndexOf("\\")+1);
              //3. 设置浏览器支持下载,URLEncoder.encode()解决中文乱码
              resp.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(fileName,"utf-8"));
              //4. 获取下载的输入流
              FileInputStream in = new FileInputStream(realPath);
              //5. 创建缓冲区
              int len = 0;
              byte[] buffer = new byte[1024];
              //6. 获取OutputStream对象
              ServletOutputStream out = resp.getOutputStream();
              //7. 将FileOutputStream流写入到buffer缓冲区,使用OutPutStream将缓冲区中的数据输出到客户端
              while((len = in.read(buffer)) > 0){
                  out.write(buffer,0,len);
              }
              in.close();
              out.close();
          }
      
          @Override
          protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              doGet(req, resp);
          }
      }
      
    3. 验证码功能

      public class ImageServlet extends HttpServlet {
          @Override
          protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              //浏览器三秒刷新一次
              resp.setHeader("refresh","3");
              //在内存中创建一个图片
              BufferedImage image = new BufferedImage(80,20,BufferedImage.TYPE_INT_RGB);
              //得到图片
              Graphics2D g = (Graphics2D) image.getGraphics(); //笔
              //设置图片的背景颜色
              g.setColor(Color.white);
              g.fillRect(0,0,80,20);
              //给图片写数据
              g.setColor(Color.blue);
              g.setFont(new Font(null,Font.BOLD,20));
              g.drawString(makeNum(),0,20);
      
              //告诉浏览器用图片方式打开
              resp.setContentType("image/jpeg");
              //不让浏览器缓存
              resp.setDateHeader("expires",-1);
              resp.setHeader("Cache-Control","no-cache");
              resp.setHeader("Pragma","no-cache");
      
              //把图片写到浏览器
              ImageIO.write(image,"jpg", resp.getOutputStream());
          }
      
          //生成随机数
          private String makeNum(){
              Random random = new Random();
              //生成一个0-9999999之间的随机数
              String num = random.nextInt(9999999)+"";
              StringBuffer sb = new StringBuffer();
              for (int i = 0; i < 7-num.length(); i++) {
                  sb.append("0");
              }
              num = sb.toString() + num;
              return num;
          }
      
          @Override
          protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              doGet(req, resp);
          }
      }
      
    4. 实现重定向

      B这个web资源收到客户端A的请求后,通知A去访问另外一个web资源C的过程叫重定向

      /*
      	resp.setHeader("Location","/response/image");
      	resp.setStatus(302);
      */
      resp.sendRedirect("/response/image"); //发布项目名+重定向路径
      

      面试题:重定向和请求转发的区别:

      • 相同点:页面都会发生跳转
      • 不同点:请求转发的时候url不会产生变化,状态码307,重定向则会,状态码302

7.HttpServletRequest

HttpServletRequest代表客户端的请求,用户通过Http协议访问服务器,http请求中的所有信息会被封装到HttpServletRequest,通过HttpServletRequest的方法,获得客户端的所有信息

  • 获取前端传递的参数,并且请求转发

    public class LoginServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            req.setCharacterEncoding("utf-8");
            String username = req.getParameter("username");
            String password = req.getParameter("password");
            String[] hobbies = req.getParameterValues("hobby");
            System.out.println(username);
            System.out.println(password);
            System.out.println(Arrays.toString(hobbies));
            //resp.sendRedirect(req.getContextPath() + "/success.jsp");
            req.getRequestDispatcher("/success.jsp").forward(req,resp);
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
    
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
    	<title>登录</title>
    </head>
    <body>
    <h2 style="text-align: center">登录</h2>
    <div style="text-align: center">
    	<form action="${pageContext.request.contextPath}/login" method="post">
      	用户名:<input type="text" name="username"><br>
      	密码:<input type="password" name="password"><br>
      	爱好:<input type="checkbox" name="hobby" value="爬山">爬山
            	<input type="checkbox" name="hobby" value="游泳">游泳
            	<input type="checkbox" name="hobby" value="睡觉">睡觉
            	<input type="checkbox" name="hobby" value="读书">读书
        	<br>
        	<input type="submit">
    	</form>
    
    </div>
    </body>
    </html>
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Remote_Li

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值