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

发布于:2025-03-23 ⋅ 阅读:(21) ⋅ 点赞:(0)

DAY15.2 Java核心基础

JavaWeb

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

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

Web交互:

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

代码示例:

@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方法,下面是业务逻辑");
    }
}

但是返回的类型是字符串

image-20250321214229253

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

可以返回html格式的代码

image-20250321214341367

网页就可以渲染上去了

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

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

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

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

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

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

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

resp.getWriter().write("<h1>Hello World</h1>");

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

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

就像

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输出

<%@ 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>

image-20250321220032857

嵌入java代码可以渲染数据

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

image-20250321220223346

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的重写业务代码逻辑

@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的值,然后渲染到网页上面

<%@ 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,渲染到了这个网页上面

image-20250322225115116

response 的常用方法

  • sendRedirect(String path) //重定向
    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里面的数据

HttpSession session = req.getSession();
session.setAttribute("id",id);

在代码中用session存储数据

<%
    String name ="张三";
    String id = (String) request.getSession().getAttribute("id");
%>

在jsp读取session数据

image-20250322230924119

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

<%
    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 取值的特点是先要存值,才能取值

<body>
    <h1>Hello</h1>
    <h1>I</h1>
    <h1>am</h1>
    <h1>${id}</h1>
</body>

比之前的取值方便多了

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

image-20250322232340656

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

<%@ page isELIgnored="false" %>