Servlet、HttpServletRequest、HttpServletResponse、静态与动态网页、jsp、重定向与转发

DAY15.2 Java核心基础

JavaWeb

要想通过浏览器或者客户端来访问java程序,必须通过Servlet来处理

没有Servlet,java是无法处理web请求的

Web交互:

  • 接收请求HttpServletRequest:可以获取到请求的信息,比如uri,url,访问的方法...
  • 返回请求HttpServletResponse:可以获取Writer,来封装信息返回给浏览器

代码示例:

java 复制代码
@WebServlet("/test")
public class MyHttpServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("重写的doGet方法,下面是业务逻辑");
        resp.getWriter().write("hello");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("重写的doPost方法,下面是业务逻辑");
    }
}

但是返回的类型是字符串

但是前端都是网页的形式,如何返回网页的形式呢?

可以返回html格式的代码

网页就可以渲染上去了

如果要返回一个写好的网页呢?

之前在Tomcat章节说过我们可以直接通过链接访问到对应的网页,那为什么还需要先访问Servlet再返回HTML呢?

因为我们需要拿到数据渲染到静态网页

静态网页:写死了的网页,无法更新数据

动态网页:我们可以渲染数据到网页上面

真正的网页:静态页面(HTML)+业务数据(后端处理)

但是处理不能在write的时候处理撒

java 复制代码
resp.getWriter().write("<h1>Hello World</h1>");

比如要改这个h1标签里面的内容,我们不能直接在这里改,如果这个页面很大很长那咋办?是吧

如果要加一、十行...代码怎么办?

就像

java 复制代码
writer.write("<h1>Hello World</h1>");
writer.write("<h1>Hello World2</h1>");
writer.write("<h1>Hello World3</h1>");
writer.write("<h1>Hello World4</h1>");

要是这个页面有上百行,不可能在这写一百行write吧

Java 这时候出现了 JSP 通过 JSP 的机制来解决这个问题

JSP :Java Server Page -- Java服务页面

一套前端HTML的动态模板,就好像HTML和Java的混合体,可以动态拼接HTML代码,并且可以嵌入Java代码

手动拼接HTML代码太麻烦

可以直接在JSP中编写java代码,JSP会自动转化为一个Servlet,自动将所有的代码生成对应的write输出

java 复制代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <%
        String name ="张三";
    %>
    <h1>Hello</h1>
    <h1>I</h1>
    <h1>am</h1>
    <h1><%=name%></h1>
</body>
</html>

嵌入java代码可以渲染数据

前端看到的是经过JSP加工后的代码

JSP 内置对象

内置对象是jsp引擎自动创建的,开发者无需创建即可使用

  • request:HttpServletRequest 的一个对象,接收用户请求

  • response:HttpServletResponse 的一个对象,客户端做出响应

  • pageContext:PagaContext 的一个对象,页面上下文,获取页面信息

  • session:HttpSession 的一个对象,代表浏览器和服务器的一次会话,保存一个用户信息

  • application:ServletContext 的一个对象,表示当前 WEB 应用,全局对象,保存所有用户的共享数据

  • config:当前 JSP 对应的 Servlet 的 ServletConfig 对象,可以获取当前 Servlet 的信息

  • out:JspWriter 对象,向客户端输出打印信息

  • page:指当前 JSP 对应的 Servlet 对象

  • exception:表示 JSP 页面发送的异常信息

常用的就request、response、session三个内置对象

request常用方法

  • String getParameter(String name) :获取前端传来的参数

  • void setAttribute(String name,Object value) :通过键值对的形式来保存数据

  • Object getAttribute(String name) :通过 key 值获取数据

  • RequestDispatch getRequestDispatch(String path) :返回一个 RequestDispatch 对象,forward() 用于转发请求

doGet的重写业务代码逻辑

java 复制代码
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    System.out.println("重写的doGet方法,下面是业务逻辑");
    // 获取到url中的query参数
    String id = req.getParameter("id");
    // 设置request的参数,以便jsp可以找到
    req.setAttribute("id",id);
    // 设置请求转发路径,转发到page.jsp
    RequestDispatcher requestDispatcher = req.getRequestDispatcher("/page.jsp");
    // 请求转发
    requestDispatcher.forward(req,resp);
}

jsp代码:

通过request.getAttribute("id")获取到id的值,然后渲染到网页上面

jsp 复制代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <%
        String name ="张三";
        String id = (String) request.getAttribute("id");
    %>
    <h1>Hello</h1>
    <h1>I</h1>
    <h1>am</h1>
    <h1><%=name%></h1>
    <h1><%=id%></h1>
</body>
</html>

访问网页:

传递的id值为1,渲染到了这个网页上面

response 的常用方法

  • sendRedirect(String path) //重定向
java 复制代码
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("重写的doGet方法,下面是业务逻辑");
        String id = req.getParameter("id");
        // 获取到url中的query参数
        req.setAttribute("id",id);
        // 设置请求转发路径,跳转到page.jsp
//        RequestDispatcher requestDispatcher = req.getRequestDispatcher("/page.jsp");
        // 请求转发
//        requestDispatcher.forward(req,resp);
        resp.sendRedirect("/page.jsp");
    }

如果用sendRedirect(String path) //重定向,则无法取出request的数据

同样都是重定向,为什么sendRedirect(String path) 不能获取request保存的数据呢?(面试考题)

其实是因为sendRedirect(String path) 是重新发送了一个请求,会创建一个新的request对象,则该对象是没有携带id属性参数的

转发和重定向都是进行页面跳转的,区别在哪?

重定向:两次请求

转发:一次请求

比如刚刚那个请求,先进入的是Servlet

如果是转发的话,则进入Servlet和jsp的请求是同一个请求,那么jsp可能可以获取到servlet里面处理过有id参数的request对象,那么肯定可以获取到这个对象的属性参数了

如果是重定向的话,进入Servlet和jsp的请求不是同一个请求,第一个请求是进入Servlet,重定向就相当于让浏览器重新发送一个请求来访问 JSP,第一个请求在 Servlet 中已经结束了它的生命周期,第二次方法 JSP 的请求相当于从浏览器发送的一个全新的请求

但是我们非要用重定向来传递数据呢,那么怎么实现呢?

那么我们需要使用生命周期更长的对象来存储数据

比如session存储,就算是两次不同的请求也可以获取到session存储的数据

session的作用域大于request,都是用来存储数据的

只要不关闭浏览器,我们都可以获取到session里面的数据

java 复制代码
HttpSession session = req.getSession();
session.setAttribute("id",id);

在代码中用session存储数据

jsp 复制代码
<%
    String name ="张三";
    String id = (String) request.getSession().getAttribute("id");
%>

在jsp读取session数据

可以看见虽然重定向了,但是还是获取到了id的数据

jsp 复制代码
<%
    String name ="张三";
    String id = (String) request.getSession().getAttribute("id");
%>
<h1>Hello</h1>
<h1>I</h1>
<h1>am</h1>
<h1><%=name%></h1>
<h1><%=id%></h1>
虽然可以实现数据的传输,但是步骤较为繁琐,效率较低,如何来解决呢?

使用 EL 表达式

EL 表达式有什么作用?

替换 JSP 页面中访问数据时的复杂编码

简化 JSP 页面的取值操作

语法:${key}

JSP 取值的特点是先要存值,才能取值

java 复制代码
<body>
    <h1>Hello</h1>
    <h1>I</h1>
    <h1>am</h1>
    <h1>${id}</h1>
</body>

比之前的取值方便多了

EL 表达式 ${id} 会依次从以下作用域查找变量:
  • Page Scope(页面作用域)
  • Request Scope(请求作用域)
  • Session Scope(会话作用域)
  • Application Scope(应用作用域)

如果设置没问题,还是出现了${id}的话,有可能EL表达式被忽略了,我们可以手动在 jsp文件 顶部启用

java 复制代码
<%@ page isELIgnored="false" %>
相关推荐
你怎么知道我是队长3 小时前
C语言---缓冲区
c语言·开发语言
一勺菠萝丶4 小时前
PDF24 转图片出现“中间横线”的根本原因与终极解决方案(DPI 原理详解)
java
姓蔡小朋友4 小时前
Unsafe类
java
一只专注api接口开发的技术猿4 小时前
如何处理淘宝 API 的请求限流与数据缓存策略
java·大数据·开发语言·数据库·spring
superman超哥4 小时前
Rust 异步递归的解决方案
开发语言·后端·rust·编程语言·rust异步递归
荒诞硬汉4 小时前
对象数组.
java·数据结构
期待のcode4 小时前
Java虚拟机的非堆内存
java·开发语言·jvm
黎雁·泠崖4 小时前
Java入门篇之吃透基础语法(二):变量全解析(进制+数据类型+键盘录入)
java·开发语言·intellij-idea·intellij idea
仙俊红4 小时前
LeetCode484周赛T4
java