Servlet、request、response等

5.12、Servlet的依赖

<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>javax.servlet-api</artifactId>
   <version>4.0.1</version>
   <scope>provided</scope>
</dependency>

jsp的依赖

        <dependency>
           <groupId>javax.servlet.jsp</groupId>
           <artifactId>javax.servlet.jsp-api</artifactId>
           <version>2.3.3</version>
           <scope>provided</scope>
       </dependency>

 

6、Servlet

6.1、Servlet简介
  • Servlet就是sun公司开发动态web的一门技术

  • Sun在这些API中提供一个接口叫做:Servlet,如果你想开发一个Servlet程序,只需要完成两个小步骤:

    • 编写一个类,实现Servlet接口

    • 把开发好的Java类部署到web服务器中。

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

6.2、HelloServlet

Servlet接口在Sun公司有两个默认的实现类:HttpServlet,GenericServlet

 

 

  1. 构建一个普通的Maven项目,删掉里面的src目录,以后我们的学习就在这个项目里面建立Model;这个空的工程就是Maven主工程;

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

父项目中会有

    <modules>
       <module>servlet-01</module>
   </modules>

子项目会有

    <parent>
       <artifactId>javaweb-02-servlet</artifactId>
       <groupId>com.kuang</groupId>
       <version>1.0-SNAPSHOT</version>
   </parent>

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

son extends father
  1. Maven环境优化

    1. 修改web.xml为最新的(Tomcat中拿来)

    2. 将maven的结构搭建完整

  2. 编写一个Servlet程序

    1. 编写一个普通类

    2. 实现Servlet接口,这里我们直接继承HttpServlet

    public class HelloServlet  extends HttpServlet {

       //由于get或者post只是请求实现的不同的方式,可以相互调用,业务逻辑都一样;
       @Override
       protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
           PrintWriter writer = resp.getWriter();    //响应流
           writer.println("Hello,Servlet!");
      }
       @Override
       protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
           super.doPost(req, resp);
      }
    1. 编写Servlet的映射

    为什么需要映射:我们写的是java程序,但是要通过浏览器访问,而浏览器需要连接web服务器,所以我们需要在web服务中注册我们写的Servlet,还需要给他一个浏览器能够访问的路径;

    <!--    注册Servlet-->
       <servlet>
           <servlet-name>hello</servlet-name>
    <!--       一个Servlet对应一个class-->
           <servlet-class>com.kuang.servlet.HelloServlet</servlet-class>
       </servlet>
       <servlet-mapping>
           <servlet-name>hello</servlet-name>
           <url-pattern>/hello</url-pattern>
       </servlet-mapping>
    </web-app>
    1. 配置Tomcat

    注意:配置项目发布的路径就可以了

    1. 启动测试,OK!

    6.3、Servlet原理

    Servlet是由Web服务器调用,web

 

6.4、Mapping问题
  1. 一个Servlet可以指定一个映射路径

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

    <servlet-mapping>
       <servlet-name>hello</servlet-name>
       <url-pattern>/hello</url-pattern>
   </servlet-mapping>
   <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>
  1. 一个Servlet可以指定通用映射路径

    <servlet-mapping>
       <servlet-name>hello</servlet-name>
       <url-pattern>/hello/*</url-pattern>
   </servlet-mapping>
  1. 默认请求路径

// 默认请求路径,会走Servlet,不会走index.jsp  
   <servlet-mapping>
       <servlet-name>hello</servlet-name>
       <url-pattern>/*</url-pattern>
   </servlet-mapping>
  1. 指定一些后缀或者前缀等等...

<!--    可以自定义后缀实现请求映射
 注意点:*前面不能加项目映射的路径
       /sakldjaks.qinjiang
-->
   <servlet-mapping>
       <servlet-name>hello</servlet-name>
       <url-pattern>*.qinjiang</url-pattern>
   </servlet-mapping>
  1. 优先级问题

指定了固有的映射路径优先级更高,如果找不到就会走默认的处理请求;

<!--  404  -->
   <servlet>
       <servlet-name>error</servlet-name>
       <servlet-class>com.kuang.servlet.ErrorServlet</servlet-class>
   </servlet>
   <servlet-mapping>
       <servlet-name>error</servlet-name>
       <url-pattern>/*</url-pattern>
   </servlet-mapping>
6.5、ServletContext

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

1、共享数据

我在这个Servlet中保存的数据,可以在另外一个servlet中拿到;

public class HelloServlet extends HttpServlet {
   @Override
   protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       //this.getServletContext()   Servlet上下文
       ServletContext context = this.getServletContext();

       String username = "qinjiang";  //数据
       context.setAttribute("username",username);  //将一个数据保存在了ServletContext中,名字为:username,值 username
  }
}
public class GetServlet extends HttpServlet {
   @Override
   protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       resp.setContentType("text/html");
       resp.setCharacterEncoding("utf-8");
       ServletContext context = this.getServletContext();
       String username = (String)context.getAttribute("username");
       PrintWriter writer = resp.getWriter();
       writer.println(username);
       //上面两步等于resp.getWriter().println(username);
  }
   @Override
   protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       super.doPost(req, resp);
  }
}
    <servlet>
       <servlet-name>hello</servlet-name>
       <servlet-class>com.kuang.servlet.HelloServlet</servlet-class>
   </servlet>
   <servlet-mapping>
       <servlet-name>hello</servlet-name>
       <url-pattern>/hello</url-pattern>   //用来浏览器访问的
   </servlet-mapping>

   <servlet>
       <servlet-name>hello1</servlet-name>
       <servlet-class>com.kuang.servlet.GetServlet</servlet-class>
   </servlet>
   <servlet-mapping>
       <servlet-name>hello1</servlet-name>
       <url-pattern>/hello1</url-pattern>
   </servlet-mapping>

测试访问结果;(hello1要获取hello的数据,浏览器需要先进入hello的页面,然后在进入hello1的页面才能能获取到,否则会出现null)

2、获取初始化参数
    <context-param>  //XML里配置
       <param-name>url</param-name>
       <param-value>jdbc:mysql://localhost:3306</param-value>
   </context-param>
    @Override 
   protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       ServletContext context = this.getServletContext();

       String url = context.getInitParameter("url");
       resp.getWriter().print(url);
  }
3、请求转发
    @Override
   protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       ServletContext context = this.getServletContext();
       System.out.println("进入了Demo04");
      // RequestDispatcher requestDispatcher = context.getRequestDispatcher("/gp"); //转发的请求路径
      // requestDispatcher.forward(req,resp);//调用forward实现请求转发;
       context.getRequestDispatcher("/gp").forward(req,resp);
  }
上面的是请求转发的方式(通过B在找C),下面的是重定位(B返回后直接去找C)。

 

 

4、 读取资源文件

Properties

  • 在java目录下新建properties

  • 在resources目录下新建properties

发现:都被打包到了同一个路径下:classes,我们俗称这个路径为classpath:

思路:需要一个文件流;

username=root
password=123456
public class ServletDemo05 extends HttpServlet {
   @Override
   protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       InputStream is = this.getServletContext().getResourceAsStream("/WEB-INF/classes/db.properties");//   /代表当前web应用

       Properties prop = new Properties();
       prop.load(is);
       String user = prop.getProperty("username");
       String pwd = prop.getProperty("password");
       resp.getWriter().print(user+":"+pwd);
  }
   @Override
   protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       doGet(req, resp);
  }
}
6.6、HttpServletResponse

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

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

  • 如果要给客户端响应一些信息:找HttpServletRequest

1、简单分类

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

    ServletOutputStream getOutputStream() throws IOException;
   PrintWriter getWriter() throws IOException;

负责像浏览器发送响应头的方法

    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);

响应的状态码:

 

 

2、常见应用
  1. 向浏览器输出消息

  2. 下载文件

    1. 要获取下载文件的路径

    2. 下载的文件名是啥?

    3. 设置想办法让浏览器能够支持下载我们需要的东西

    4. 获取下载文件的输入流

    5. 创建缓冲区

    6. 获取OutputStream对象

    7. 将FileOutputStream流写入到buffer缓冲区

    8. 使用OutputStream将缓冲区中的数据输出到客户端!

    public class FileServlet extends HttpServlet {
       @Override
       protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //       1. 要获取下载文件的路径   这里需要classes下面的路径
           String realPath = "D:\\ideaPractice\\javaWeb\\javaweb-nnew02-servlet\\response\\target\\classes\\1.png";
           System.out.println("下载文件的路径:"+realPath);

    //       2. 下载的文件名是啥?
           String filename = realPath.substring(realPath.lastIndexOf("\\") + 1);
    //       3. 设置想办法让浏览器能够支持下载我们需要的东西
           resp.setHeader("Content-Disposition","attachment; filename="+filename);
    //       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();
    3、随机数
    public class ImageServlet extends HttpServlet {
       @Override
       protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

           //如何让浏览器5秒自动刷新一次;
           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,150,20);
           //给图片写数据
           g.setColor(Color.blue);
           g.setFont(new Font(null,Font.BOLD,20));
           g.drawString(makeNum(),0,20);
           //告诉浏览器,这个请求用图片的方式打开
           resp.setContentType("image/jpg");
           //网站存在缓存,不让浏览器缓存
           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();
           String num = random.nextInt(99999999) + "";
           StringBuffer sb = new StringBuffer();
           for (int i = 0; i < 7 - num.length(); i++) {
               sb.append("0");
          }
           num = sb.toString() + num;
           return num;
      }
    4、实现重定向

 

void secdRedirect(String var1) throws IOException;

测试:

    @Override
   protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       /*
       resp.setHeader("location","/r/img");
       resp.setStatus(302);
        */
       resp.sendRedirect("/r/img");      //重定向
  }

面试题:聊聊重定向和转发的区别?

相同点

  • 页面都会实现跳转

不同点

  • 请求转发的时候,url不会变化 307

  • 重定向时候,url地址栏会发生变化 302

 resp.sendRedirect("/r/success.jsp");    //重定向路径要注意
       req.getRequestDispatcher("/success.jsp").forward(req,resp); //跟上面结果一样

 

6.7、HttpServletRequest

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

1、获取前端传递的参数

 

 

2、请求转发
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

       req.setCharacterEncoding("utf-8");
       resp.setCharacterEncoding("utf-8");
       String username = req.getParameter("username");
       String password = req.getParameter("password");
       String[] hobbys = req.getParameterValues("hobbys");
       System.out.println("=======================");
       //后台接受中文乱码问题
       System.out.println(username+":"+password);
       System.out.println(Arrays.toString(hobbys));
       System.out.println("=======================");

       // 通过请求转发
       System.out.println(req.getContextPath());
       req.getRequestDispatcher("/success.jsp").forward(req,resp);
  }
}
<div>
<%--    这里表单表示的意思:以post方式提交表单,提交到login请求--%>
   <form action="${pageContext.request.contextPath}/login" method="post">
      用户名:<input type="text" name="username"><br>
      密码:<input type="password" name="password"><br>
      爱好:
       <input type="checkbox" name="hobbys" value="女孩">女孩
       <input type="checkbox" name="hobbys" value="代码">代码
       <input type="checkbox" name="hobbys" value="唱歌">唱歌
       <input type="checkbox" name="hobbys" value="电影">电影
       <br>
       <input type="submit">
   </form>
</div>

 

 

 

 

posted @ 2021-10-16 16:44  敲代码的体育生  阅读(81)  评论(0)    收藏  举报