08.JSP技术

一、什么是JSP

JSP(Java Server Pages)是JavaWeb服务器端的动态资源。它与html页面的作用是相同的,显示数据获取数据。JSP文件的扩展名是.jsp。

JSP = html + Java代码片段 + JSP动态标签

HTML代码用来显示网页中静态内容,Java代码用来显示网页中的动态内容。

二、JSP的作用

  • Servlet:
  • 缺点:不适合设置HTML响应体,需要大量的response.getWriter().print("<html>")
  • 优点:动态资源,可以编程。
  • HTML:
  • 缺点:HTML是静态页面,不能包含动态信息
  • 优点:不用为输出HTML而发愁
  • JSP(Java Server Pages):
  • 优点:在原有HTML的基础上添加JAVA脚本,构成jsp页面。

三、JSP和Servlet的分工

  • JSP:
  • 作为请求发起页面,例如显示表单、超链接。
  • 作为请求结束页面,例如显示数据。
  • Servlet:
  • 作为请求中处理数据的环节。

【案例】两个整数加法计算

在form页面输入两个整数,提交后由AServlet进行计算,然后将结果显示到result页面。

创建一个名为HelloJSP的Dynamic Web Project,

在WebContent目录下创建一个名为plus的文件夹,在该文件夹中创建两个JSP文件:form.jsp和result.jsp,

在src目录下创建一个名为com.sdbi.servlet的包,在该包下创建一个类AServlet.java。

(1)form.jsp文件,具体代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>表单</title>
</head>
<body>
    <form action="../AServlet" method="POST">
        整数1:<input type="text" name="num1" /><br /> 
        整数2:<input type="text" name="num2" /><br />
        <input type="submit" value="提交" />
    </form>
</body>
</html>

(2)result.jsp文件,具体代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>结果</title>
</head>
<body>
    结果是:<%=request.getAttribute("result") %>
</body>
</html>

(3)AServlet.java文件,具体代码如下:

@WebServlet("/AServlet")
public class AServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 获取参数
        String s1 = request.getParameter("num1");
        String s2 = request.getParameter("num2");
        // 转换成int类型
        int num1 = Integer.parseInt(s1);
        int num2 = Integer.parseInt(s2);
        // 运算
        int sum = num1 + num2;
        // 把结果保存到request域中
        request.setAttribute("result", sum);
        // 转发到result.jsp
        request.getRequestDispatcher("/plus/result.jsp").forward(request, response);
    }
}

四、JSP的原理

1、JSP是特殊的Servlet

JSP是一种特殊的Servlet,某个JSP页面就是一个Servlet类的对象。

当JSP页面首次被访问时,发生如下事情:

(1)JSP容器(Tomcat)会先把JSP文件编译成Java文件(实现Servlet接口的类);

(2)把.java编译成.class;

(3)创建该类对象;

(4)调用它的service()方法。

如果第二次请求同一JSP时,直接调用service()方法。

虽然在web.xml文件中没有与JSP相关的配置,但Web服务器仍然可以根据URL找到对应的JSP文件。

这是因为在Tomcat服务器的web.xml(Tomcat安装目录下\conf\web.xml)文件中实现了JSP的相关配置,具体如下:

从配置信息可以看出,以.jsp为扩展名的URL访问请求都是由org.apache.jasper.servlet.JspServlet处理,所以,Tomcat中的JSP引擎就是这个Servlet程序,该Servlet程序实现了对所有JSP页面的解析。

JSP文件也可以像Servlet程序一样,在web.xml文件中进行注册和映射虚拟路径。

注册JSP页面的方式与Servlet类似,只需将<servlet-class>元素修改为<jsp-file>元素即可。

例如,要映射/plus/form.jsp的虚拟访问路径,需要在web.xml配置中配置如下信息:

<servlet>
    <servlet-name>FormJspServlet</servlet-name>
    <jsp-file>/plus/form.jsp</jsp-file>
</servlet>
<servlet-mapping>
    <servlet-name>FormJspServlet</servlet-name>
    <url-pattern>/form</url-pattern>
</servlet-mapping>

其中,<jsp-file>元素表示JSP文件,它表示的路径必须以“/”开头,这个“/”表示JSP文件所在的Web应用程序的根目录。

2、JSP生成Servlet存放目录

JSP生成的Servlet存放在Tomcat安装目录的work目录下,我们打开看看其中的内容,在JSP中的静态信息(例如<html>等)在Servlet中都是使用out.write()完成打印。这些静态信息都是作为字符串输出给了客户端。

 

五、JSP语法

1、JSP脚本

JSP脚本就是Java代码片段,它分为三种:

<%...%>:JSP脚本:Java代码片段,用于定义0~N条Java语句,方法内能写什么,它就可以放什么

<%=…%>:JSP表达式:用于输出(常用),用于输出一个表达式(或变量)的值。response.getWriter().print( ... ); 这里参数能放什么,它就可以放什么

<%!...%>:JSP声明:Java中类成员的声明,用来创建类的成员变量和成员方法(基本不用,但容易被考到),例如,成员变量和方法。类体中可以放什么,它就可以放什么

【案例】演示JSP中的Java代码片段

在WebContent目录下创建一个JSP文件:index.jsp。

<body>
    <%
        int a = 10; //定义变量
    %>
    <%
        out.print(a++); //输出变量
    %>
    <br />
    <%=a%>
    <br />
    <%!int a = 100;%>
    <%
        out.print(a++);
    %>
    <br />
    <%
        out.print(this.a++);
    %>
    <br />
    <%!private String hello = "world";
    public String sayHello() {
        return hello;
    }%>
    <%=sayHello()%>
</body>

在这基础上再来创建一个表格:

<table border="1" align="center" width="60%">
    <tr align="center">
        <td>姓名</td>
        <td>年龄</td>
    </tr>
    <%
        for (int i = 0; i < 10; i++) {
    %>
    <tr align="center">
        <td>张三</td>
        <td>36</td>
    </tr>
    <%
        }
    %>
</table>

我们到Tomcat安装目录下的\work\Catalina\localhost\HelloJSP\org\apache\jsp中找一下index.jsp翻译生成的Servlet,对比看一下。

会发现:

在JSP中的<%...%>Java代码片段会原封不动的翻译到生成的Java类中;

JSP中的标签会以字符串形式通过out.write()方法输出;

JSP中的<%=…%>Java表达式会以变量形式通过out.print()方法输出;

JSP中的<%!...%>成员定义会在Java中变为Servlet类的成员变量和成员方法。

2、JSP注释

1JSP注释<%-- … --%>我们现在已经知道JSP是需要先编译成.java,再编译成.class的。其中<%-- … --%>中的内容在JSP翻译成.java时会被忽略的,即JSP注释,里面的内容不会被发送到客户端。

2HTML注释<!-- … -->:也可以在JSP页面中使用HTML注释,但这个注释在JSP编译成的.java中是存在的,它不会被忽略,而且会被发送到客户端浏览器。但是在浏览器显示服务器发送过来的HTML时,因为<!-- … -->是HTML的注释,所以浏览器是不会显示它的。但是我们可以在浏览器中通过右键查看源代码,可以看到HTML注释中的内容。

 

六、JSP指令

1、JSP指令概述

JSP指令的格式:<%@指令名 attr1="" attr2="" %>,一般都会把JSP指令放到JSP文件的最上方,但这不是必须的。

JSP中有三大指令:pageincludetaglib

最为常用,属性最多,也最为复杂的就是page指令了。

2、page指令

page指令是最为常用的指令,也是属性最多的指令。

page指令没有必须属性,都是可选属性。例如<%@page %>,没有给出任何属性也是可以的!

在JSP页面中,任何指令都可以重复出现。

<%@ page language=”java”%>

<%@ page import=”java.util.*”%>

<%@ page pageEncoding=”utf-8”%>

这也是可以的。

(1)page指令的pageEncoding和contentType(重点)

我们来看一下JSP文件的第一行:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

pageEncoding指定当前JSP页面的编码。

这个编码是给服务器看的,服务器需要知道当前JSP使用的编码,不然服务器无法正确把JSP编译成java文件。

所以这个编码只需要与真实的页面编码一致即可。

在Eclipse中,在JSP文件上点击右键,选择属性就可以看到当前JSP页面的编码了。

如果我们希望Eclipse在自动创建JSP页面时,使用UTF-8作为编码,我们可以在Window > Preferences > Web > JSP Files中将Encoding设置为“ISO 10464/Unicode(UTF-8)”即可。

 

contentType属性与response.setContentType()方法的作用相同。

它会完成两项工作,一是设置响应字符流的编码,二是设置content-type响应头。

例如:<%@ page contentType="text/html;charset=utf-8"%>,它会在翻译的Servlet类中出现response.setContentType("text/html;charset=utf-8")。

pageEncoding和contentType这两个属性的关系:

  • 如果两个属性只提供一个,那么另一个的默认值为设置那一个。
  • 如果两个属性都没有设置,那么默认为ISO-8859-1。

无论是page指令的pageEncoding还是contentType,它们的默认值都是ISO-8859-1,我们知道ISO-8859-1是无法显示中文的,所以JSP页面中存在中文的话,一定要设置这两个属性。

(2)page指令的import属性

importpage指令中一个很特别的属性。

import属性值对应Servlet中的import语句。

import属性值可以使逗号:

<%@ page import="java.net.*,java.util.*,java.sql.*"%>

import属性是唯一可以重复出现的属性:

<%@ page import="java.util.*" import="java.net.*" import="java.sql.*"%>

但是,我们一般会使用多个page指令来导入多个包:

<%@ page import="java.util.*"%>
<%@ page import="java.net.*"%>
<%@ page import="java.text.*"%>

(3)page指令的errorPage和isErrorPage

  • errorPage:当前页面如果抛出异常,那么要转发到哪一个页面,由errorPage来指定。

我们知道,在一个JSP页面出错后,Tomcat会响应给用户错误信息(500页面)。如果你不希望Tomcat给用户输出错误信息,那么可以使用page指令的errorPage来指定错误页。也就是自定义错误页面,例如:<%@ page errorPage="xxx.jsp"%>。这时,在当前JSP页面出现错误时,会请求转发到xxx.jsp页面。我们来测试一下。

创建a.jsp文件,代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"% errorPage="errorPage.jsp"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
    <%
        int i = 10 / 0;
    %>
</body>
</html>

创建errorPage.jsp文件,代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
    <h1>出错啦!</h1>
</body>
</html>

发布到Tomcat,浏览器访问http://localhost:8080/HelloJSP/a.jsp,出现如下画面:

在上面代码中,a.jsp抛出异常后,会请求转发到errorPage.jsp。在浏览器的地址栏中还是a.jsp,因为是请求转发

而且客户端浏览器收到的响应码为200,表示请求成功。

  • isErrorPage:指定当前页面是否为处理错误的页面。当该属性为true时,这个页面会设置状态码为500,而且这个页面可以使用9大内置对象中的exception隐式对象。

上例中,如果希望客户端得到500,那么就需要指定errorPage.jsp为错误页面,并且我们可以输出异常的内容。如果没有将isErrorPage属性设置为true的话,exception隐式对象是不可以调用的。修改errorPage.jsp文件,代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"% isErrorPage="true"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
    <%
        exception.printStackTrace(response.getWriter());
    %>
    <h1>出错啦!</h1>
</body>
</html>

 

【注意】IE会在状态码为500时,并且响应正文的长度小于等于512B时不给予显示。而是显示“网站无法显示该页面”字样。这时,我们可以到IE选项 à 高级 à 取消“显示友好HTTP错误消息”的勾选。或者是需要添加一些响应内容即可,例如上例中的errorPage.jsp中想响应中输出异常的内容,这样IE也可以正常显示了。

 

(4)web.xml中配置错误页面

不只可以通过JSP的page指令的errorPage属性来配置错误页面,还可以在web.xml文件中指定错误页面。这种方式其实与page指令无关,在这里跟着一起讲一下。

我们在web.xml增加如下代码:

<error-page>
    <error-code>404</error-code>
    <location>/error404.jsp</location>
</error-page>
<error-page>
    <error-code>500</error-code>
    <location>/error500.jsp</location>
</error-page>

然后,我们在a.jsp文件的page指令中去掉errorPage属性。然后自定义两个错误页面error404.jsp和error500.jsp。

这时,我们访问http://localhost:8080/HelloJSP/a.jsp会转发至error500.jsp页面,我们如果访问一个不存在的资源,会转发至error404.jsp页面。

 

 

如果我们在web.xml文件中在添加如下代码:

<error-page>
    <exception-type>java.lang.RuntimeException</exception-type>
    <location>/errorPage.jsp</location>
</error-page>

这是就会根据<exception-type>更精确的捕获异常类型来实现错误页面的转发。

<error-page>有两种使用方式:

  • <error-code>和<location>子元素;
  • <exception-type>和<location>子元素;

其中<error-code>是指定响应码;<location>指定转发的页面;<exception-type>是指定抛出的异常类型。

在上例中:

  • 当出现404时,会跳转到error404.jsp页面;
  • 当出现RuntimeException异常时,会跳转到errorPage.jsp页面;
  • 当出现非RuntimeException的异常时,会跳转到error500.jsp页面。

这种方式会在控制台看到异常信息,而使用page指令时不会在控制台打印异常信息。

(5)page指令的autoFlush和buffer

buffer表示当前JSP的输出流(out隐藏对象)的缓冲区大小,默认为8kb。

autoFlush表示在out对象的缓冲区满时如何处理:

  • 当autoFlush为true时,表示缓冲区满时把缓冲区数据输出到客户端,authFlush的默认值为true;
  • 当authFlush为false时,表示缓冲区满时,抛出异常。

这两个属性一般我们也不会去特意设置,都是保留默认值。

(6)page指令的isELIgnored

以后我们会讲解EL表达式语言,page指令的isElIgnored属性表示当前JSP页面是否忽略EL表达式,默认值为false,表示不忽略(即支持EL表达式)。

(7)page指令的其他属性(基本不会用)

  • language:指定当前JSP编译后的语言类型,默认值为Java。
  • info:JSP说明性信息。
  • isThreadSafe:当前的JSP是否支持并发访问,默认值为false。为true时,JSP生成的Servlet会去实现一个过时的接口SingleThreadModel,这时JSP就只能处理单线程的访问。
  • session:当前JSP页面是否支持session内置对象,默认值为true,表示当前JSP页面可以使用session对象,如果为false表示当前JSP页面不能使用session对象。
  • extends:指定当前JSP页面生成的Servlet的父类。

3、include指令 -- 静态包含

与RequestDispatcher的include()方法(请求包含)的功能相似。但是,区别是:

  • <%@include%> 它是在JSP翻译成Java文件时完成的。它们共同生成一个Java(就是一个Servlet)文件,然后再编译一个class。
  • RequestDispatcher的include()是一个方法,包含和被包含的是两个Servlet,即两个.class。它只是把响应的内容在运行时合并了。

作用:把页面分解了,使用包含的方式组合在一起,这样一个页面中不变的部分,就是一个独立JSP,而我们只需要处理其他变化的页面。

我们来测试一下,创建两个JSP页面:hello.jsp和world.jsp

在hello.jsp中定义一个变量name,另外通过include指令包含world.jsp页面,具体代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>hello.jsp</title>
</head>
<body>
    <h1>hello.jsp</h1>
    <%
        String name = "zhangsan";
    %>
    <%@include file="world.jsp"%>
</body>
</html>

在world.jsp中通过out输出变量name的值,具体代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>world.jsp</title>
</head>
<body>
    <h1>world.jsp</h1>
    <%
        out.print("Hello, " + name);
    %>
</body>
</html>

发布运行hello.jsp,可以看到如下画面。查看生成的.java和.class文件,只有hello.jsp被翻译。

 

在Eclipse中,world.jsp页面会报语法错误,可不去理会,因为Eclipse想把world.jsp单独翻译成一个Servlet,但是变量name又没有定义,所以会报语法错误。

但是我们不单独执行world.jsp页面,不会翻译这个页面,因此这个错误可以不去理会。

 

4、taglib指令 -- 导入标签库

用来在当前JSP页面中导入第三方的标签库,它有两个属性:

  • prefix:指定标签库在本页面中的前缀!由我们自己来起名称。
  • uri: 指定标签库的位置。需要先把第三方标签库所需jar包放到类路径中。

例如:

<%@taglib prefix="s" uri="/struts-tags"%>

前缀的用法  <s:text> 

七、JSP九大内置对象

1、什么是JSP九大内置对象

在JSP中无需创建就可以使用的9个对象,它们是:

  • out(JspWriter):等同与response.getWriter(),用来向客户端发送文本数据;
  • config(ServletConfig):对应Servlet中的ServletConfig;
  • page(Object):指当前JSP页面对象,但是,我们一般使用this对象而不用page对象,因为page是this对象向上转型得到的,page对象是Object类型的,它的方法很少;
  • pageContext(PageContext):页面上下文对象;
  • exception(Throwable):只有在错误页面中可以使用这个对象;
  • request(HttpServletRequest):即HttpServletRequest类的对象;
  • response(HttpServletResponse):即HttpServletResponse类的对象;
  • application(ServletContext):即ServletContext类的对象;
  • session(HttpSession):即HttpSession类的对象,不是每个JSP页面中都可以使用,如果在某个JSP页面中设置<%@page session="false"%>,说明这个页面不能使用session。

在这9个对象中有很多是极少会被使用的,例如:config、page、exception基本不会使用。

在这9个对象中有两个对象不是每个JSP页面都可以使用的:exception、session。

2、pageContext

(1)域对象

pageContext指一个JSP页面。这个域是在当前JSP页面和当前JSP页面中使用的标签之间共享数据。

四大域范围:

pageContext < HttpServletRequest(request) < HttpSession(session) < ServletContext(application)

域对象的方法:

  • void setAttribute(String name, Object value)
  • Object getAttrbiute(String name)
  • void removeAttribute(String name)
  • Enumeration<String> getAttributeNames()

(2)代理其他域对象

还可以使用pageContext来代理其它3个域对象的功能,也就是说可以使用pageContext向request、session、application对象中存取数据,具体方法:

  • void setAttribute(String name, Object value, int scope)
  • Object getAttribute(String name, int scope)
  • void removeAttribute(String name, int scope)

这三个方法都多了一个参数int scope,通过这个参数,指定要代理其他的域,这里可以传入pageContext 中代表域的常量:

  • PageContext.APPLICATION_SCOPE :4
  • PageContext.SESSION_SCOPE :3
  • PageContext.REQUEST_SCOPE :2
  • PageContext.PAGE_SCOPE(默认值):1

例如:

pageContext.setAttribute("xxx", "XXX", PageContext.SESSION_SCOPE); // 在Session域中保存数据

(3)全域查找

我们还可以使用findAttribute()方法进行全域查找,从小域到大域开始搜索,如果搜索到就直接获取该值,如果所有域中都找不到,返回一个null。

例如:

pageContext.findAttribute("xxx"); //从小到大,依次查找

(4)获取其他8个内置对象:

可以通过一个pageContext对象获取其他所有内置对象,即一个当九个

pageContext获取其他八个对象的方法有:

  • JspWriter getOut():获取out内置对象;
  • ServletConfig getServletConfig():获取config内置对象;
  • Object getPage():获取page内置对象;
  • ServletRequest getRequest():获取request内置对象;
  • ServletResponse getResponse():获取response内置对象;
  • HttpSession getSession():获取session内置对象;
  • ServletContext getServletContext():获取application内置对象;
  • Exception getException():获取exception内置对象;

八、JSP动作标签

动作标签的作用是用来简化Java脚本的。用来替代一部分Java脚本,使非Java开发人员也可以向JSP中添加动态信息。

JSP的动作标签,与HTML提供的标签有本质的区别。

  • 动作标签是由Tomcat(服务器)来解释执行,它与Java代码一样,都在服务器端执行的;
  • HTML标签由浏览器来执行。

1、<jsp:include>

动态包含,它与RequestDispatcher的include方法是一样的,一个是在Servlet中使用,一个是在JSP中使用。

<%@include>和<jsp:include>有什么不同?

我们来写程序看一下<jsp:include>的效果。

在WebContent下创建一个文件夹jspinclude,在里面创建两个JSP文件:b.jsp和c.jsp,在b.jsp中动态包含c.jsp。

b.jsp部分代码如下:

<body>
    <h1>b.jsp</h1>
    <jsp:include page="c.jsp"></jsp:include>
</body>

c.jsp部分代码如下:

<body>
    <h1>c.jsp</h1>
</body>

发布运行b.jsp,查看生成的.java和.class文件。

 

你会发现b.jsp和c.jsp两个JSP文件都被翻译成了.java文件,并且被编译。动态包含的原理:

 

这时候我们再来思考一下,如果在b.jsp中定义了一个变量name,在c.jsp中使用这个变量,这时程序能不能运行?

答案是:不能!因为c.jsp也会被编译为.class,这时就会报服务器错误。

2、<jsp:forward>

动态转发,它与RequestDispatcher的forward方法是一样的,一个是在Servlet中使用,一个是在JSP中使用。

在WebContent下创建一个文件夹jspforward,在里面也创建两个JSP文件:b.jsp和c.jsp,在b.jsp中动态包含c.jsp。

b.jsp部分代码如下:

<body>
    <h1>b.jsp</h1>
    <jsp:forward page="c.jsp"></jsp:forward>
</body>

c.jsp部分代码如下:

<body>
    <h1>c.jsp</h1>
</body>

发布运行b.jsp,查看生成的.java和.class文件。

 

你会发现,只显示c.jsp中的内容,b.jsp中的内容没有显示,因为转发是“留头不留体”。

3、<jsp:param>

用作为<jsp:include>和<jsp:forward>的子标签,用来给转发或包含的页面传递参数。

修改上面的b.jsp代码:

<body>
    <h1>b.jsp</h1>
    <jsp:forward page="c.jsp">
        <jsp:param value="admin" name="username" />
        <jsp:param value="123" name="password" />
    </jsp:forward>
</body>

修改c.jsp代码:

<body>
    <h1>c.jsp</h1>
    <%
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        out.print(username + ", " + password);
    %>
</body>

发布运行b.jsp。

 

 

posted @ 2022-10-25 09:00  熊猫Panda先生  阅读(273)  评论(0编辑  收藏  举报