JSP、HTML和Tomcat

9x9上三角乘法表

乘法表的实现

html 复制代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html>
<head>
  <title>9×9 上三角乘法表</title>
  <style>
    body {
      font-family: monospace;
      padding: 20px;
    }
    .row {
      white-space: nowrap;
    }
    .cell {
      display: inline-block;
      width: 80px;
    }
  </style>
</head>
<body>
<h2>9×9 上三角乘法表</h2>
<%
  for (int i = 1; i <= 9; i++) {
%>
<div class="row">
  <% for (int j = 1; j < i; j++) { %>
  <span class="cell">&nbsp;</span>
  <% }
    for (int j = i; j <= 9; j++) { %>
  <span class="cell"><%= i %>×<%= j %>=<%= i * j %></span>
  <% } %>
</div>
<%
  }
%>
</body>
</html>

分清楚哪些是可以自定义名字的,哪些是规定的语法

html 复制代码
<div class="lalala-row">
    <% for (int j = 1; j < i; j++) { %>
        <span class="lalala-cell">&nbsp;</span>
    <% }
       for (int j = i; j <= 9; j++) { %>
        <span class="lalala-cell"><%= i %>×<%= j %>=<%= i * j %></span>
    <% } %>
</div>

这里进行循环lalala是自己定义的名字

但head里的style里的设置也因此要修改符合了

html 复制代码
<style>
    body {
        font-family: monospace;
        padding: 20px;
    }
    .lalala-row {
        white-space: nowrap;
    }
    .lalala-cell {
        display: inline-block;
        width: 80px;
    }
</style>

body { font-family: monospace; padding: 20px; }

属性 含义
font-family: monospace; 设置字体为等宽字体,确保每个字符宽度一样(比如数字、乘号、等号对齐)
padding: 20px; 给页面四周加内边距,让内容不贴边,视觉更舒服

.row { white-space: nowrap; }

这个是用在:

<div class="row"> ... </div>

属性 含义
white-space: nowrap; 告诉浏览器:不要自动换行,所有乘法项都显示在一行内

🚫 否则每个 <span> 到边界时会自动换行,排版会乱

.cell { display: inline-block; width: 80px; }

这是每个乘法项的样式:

属性 含义
display: inline-block; <span> 像文字一样横向排列,但也能设置宽度(不像普通的 inline 元素那样不能设置宽度)
width: 80px; 给每个乘法项 固定宽度 ,这样不论 1×1=1 还是 9×9=81,都在统一宽度块内显示,整齐对齐

&nbsp; 是 HTML 中的不换行空格字符

  • 全称是:non-breaking space
  • 表示一个真正可见的空格不会被浏览器忽略
html 复制代码
<body>
<h2>9×9 上三角乘法表</h2>
<%
  for (int i = 1; i <= 9; i++) {
%>
<div class="row">
  <% for (int j = 1; j < i; j++) { %>
  <spanforthecellWith class="cell">&nbsp;</spanforthecellWith>
  <% }
    for (int j = i; j <= 9; j++) { %>
  <spanWwwhateverIcanName class="cell"><%= i %>×<%= j %>=<%= i * j %></spanWwwhateverIcanName>
  <% } %>
</div>
<%
  }
%>
</body>

class前可以任意命名(但一般不要这样做,还是不太允许的)

  • 浏览器看到 spanWwwhateverIcanName,虽然它不是标准 HTML 标签 ,但因为它是内联标签(inline element),不会影响整体布局
  • 它仍然像 <span> 一样显示,所以不会影响页面的结构

浏览器不认识 div__lalala 这个标签,所以它会:

  • 直接忽略 div__lalala,导致其内部的元素可能失去结构化
  • 或者以未知的块级元素解析 ,导致 CSS(如 white-space: nowrap失效
  • 浏览器对内联元素的解析更宽松(即使是未知标签,也不会影响排版)。
  • 浏览器对块级元素的解析更严格 ,未知块级标签会影响 CSS 结构,导致排版错误。

标签包含

html 复制代码
<%@page contentType="text/html;charset=gb2312"%>
<html>
<head>
  <title>include demo</title>
</head>
<body>
  <%@include file="incl.jsp"%>
  <%@include file="incl.txt"%> 
  <%@include file="incl.inc"%>   
</body>
</html>

<%@page contentType="text/html;charset=gb2312"%>

  • 设置页面的内容类型为 HTML

  • 设置字符编码为 GB2312(早期用于中文页面的编码)

  • 这会影响 HTTP 响应头和 HTML <meta charset> 默认值

<%@include file="incl.jsp"%>

<%@include file="incl.txt"%>

<%@include file="incl.inc"%>

用的是 JSP 的"静态包含指令"(directive include)

含义:在 JSP 被编译成 Java 代码之前,直接把指定文件的内容"粘贴"到这行位置上。

JSP 是一个"预处理器"

  • incl.jsp → 一个包含 <h1>欢迎访问</h1> 的 HTML

  • incl.txt → 一个纯文本,比如 这是文本部分

  • incl.inc → 一个 HTML 片段,比如 <footer>版权所有</footer>

只要你把这三个文件放在和 includeDemo01.jsp 同一目录下,就可以了

只要它们是合法的文本片段(HTML 或 JSP 语法中可插入的内容),就能被静态包含进去。

  • 不一定非是 JSP 文件

  • 只要在语法上能"插得进去",都没问题

html 复制代码
<%-- 使用此语句处理显示中的乱码 --%>
<%@page contentType="text/html;charset=gb2312"%>
<html>
<head>
	<title>include demo</title>
</head>
<body>
<%--
 <jsp:include page="incl.jsp">
	<jsp:param name="ref1" value="ZTE"/>
	<jsp:param name="ref2" value="tom"/>
 </jsp:include>  
--%>


<jsp:include page="incl.txt">
	<jsp:param name="ref1" value="ZTE"/>
	<jsp:param name="ref2" value="ls"/>
</jsp:include>


 <%--<jsp:include page="incl.inc"/> --%>
</body>
</html>
  • 告诉 JSP 引擎输出 HTML 页面时使用 GB2312 编码(中文)

  • 防止中文乱码问题

  • 这对输出的参数(如"ZTE"、"tom")中含中文时尤其关键

<html>

<head>

<title>include demo</title>

</head>

<body>

标准 HTML 页面结构,主体都在 <body>

html 复制代码
<%--
 <jsp:include page="incl.jsp">
	<jsp:param name="ref1" value="ZTE"/>
	<jsp:param name="ref2" value="tom"/>
 </jsp:include>  
--%>

它是标签式动态包含,特点如下:

特性 含义
<jsp:include ... /> 运行时包含 (和 @include 不同)
<jsp:param /> 向被包含的 JSP 页面传递参数(类似 URL 参数)
被包含页面 incl.jsp:可以使用 request.getParameter("ref1") 获取值

如果取消注释,运行时会:

  • 加载 incl.jsp

  • 向其中传递两个参数:ref1=ZTEref2=tom

html 复制代码
<jsp:include page="incl.txt">
	<jsp:param name="ref1" value="ZTE"/>
	<jsp:param name="ref2" value="ls"/>
</jsp:include>

包含的是 .txt 文件,Tomcat 默认不会把 .txt 当作 JSP 来解析,而是:

把它当成纯文本文件 → 直接输出内容,不处理其中的 JSP 语法(<%= ... %>)

这就是你看到它原样打印出来的原因。

正常获取参数的两种前提方式:

✅ 方式 1:通过 HTML 表单提交(推荐)

你需要一个表单页面(比如 demo01.html),向 demo02.jsp 发起 POST 请求并带上 uname 参数:

html 复制代码
<!-- demo01.html -->
<form action="demo02.jsp" method="post">
  <label>请输入姓名:</label>
  <input type="text" name="uname">
  <input type="submit" value="提交">
</form>

需要新建一个 HTML 文件,比如命名为 demo01.html,内容如下:

放在和 demo02.jsp 同一个 Web 应用项目目录下 (比如你的 webapp/WebContent/src/main/webapp/ 中)

方式 2:通过 GET 参数访问

你也可以直接在地址栏里输入 URL,带上 uname 参数:

http://localhost:8080/你的项目/demo02.jsp?uname=张三

所谓"静态编码 vs 动态编码"指的就是:

编码处理方式指的是 后端 JSP 页面中对中文参数的"读取方式" ,与 HTML 是否是静态页面无直接关系

类别 实现方式 特点
静态编码(手动转码) 获取参数后再用 getBytes() + new String(...) 手动转换 繁琐但对控制力高,适用于不支持动态设置编码的环境
动态编码(统一设置) request.setCharacterEncoding("编码") 预先设定 推荐方式,简洁稳定

理解并对比:

客户端跳转sendRedirect
服务端跳转forward<jsp:forward>

各自的执行顺序、显示效果、地址栏变化、数据是否能传递

复制代码
<%@page contentType="text/html;charset=gb2312"%>
<h1>欢迎光临:responseDemo03.jsp</h1>
<!-- http://127.0.0.1:8080/test/base/05/responseDemo03.jsp?upass=123 -->
<%
	 System.out.println("** 跳转之前...") ;
%>
<%
	// 进行跳转
   response.sendRedirect("responseDemo04.jsp?uname=ZTE");

  //response.setHeader("refresh","0;URL=responseDemo04.jsp?uname=ZTE") ;
%>
	    
 <%--<jsp:forward page="responseDemo04.jsp"/>--%>
	   
	 
<%          //request.getRequestDispatcher("responseDemo04.jsp").forward(request, response);
 
 System.out.println("** 跳转之后...");
 
%>

<%@page contentType="text/html;charset=gb2312"%>

  • 设置当前页面的内容类型为 HTML,字符编码是 gb2312(简体中文)

  • 作用:防止中文乱码

<h1>欢迎光临:responseDemo03.jsp</h1>

  • 页面显示的静态内容,表示这是 03.jsp 页面

  • 只有在没有跳转成功时才可能看到这个内容(实际上会被跳走)

<% ... %>JSP 的脚本标记(scriptlet),它的作用是:

✳️ 把其中的 Java 代码嵌入到 HTML 页面中,并由服务器(Tomcat)在运行时翻译成 Java Servlet 来执行

JSP(Java Server Pages)是 服务器端动态网页技术,它的本质是:

✳️ 一种"模板语言",页面中可以写 HTML + Java 代码

它不是浏览器能直接识别的,而是被 Tomcat 服务器在第一次访问时

JSP → 翻译成 Java Servlet → 编译为 class → 运行 → 返回 HTML

假设你访问一个 JSP 页面:

http://localhost:8080/demo/responseDemo03.jsp

Tomcat 后台执行的完整流程如下

  1. 解析 JSP 文件

    • Tomcat 找到 .jsp 文件

    • 把页面中的 HTML 保留,把 <% %> 中的 Java 代码提取出来

  2. 翻译成 Java Servlet 文件

    • 每个 JSP 都会被转成一个 Servlet 类(比如叫 responseDemo03_jsp.java
  3. 编译成 .class 字节码

    • Servlet 类被编译成 .class 文件,交给 JVM 执行
  4. 运行 Servlet,输出 HTML

    • Servlet 执行时,把 HTML 输出给浏览器

    • <% System.out.println(...) %> 会打印到服务器控制台(Tomcat 终端)

    • <%= ... %> 的内容会输出到浏览器页面

你访问的 responseDemo03.jsp 页面能正常运行

里面的跳转目标 responseDemo04.jsp 根本不存在或路径不对

跳转后地址栏变成了 responseDemo04.jsp?uname=ZTE,并成功显示了页面内容

客户端跳转(Client-side Redirect)成功

测试服务端跳转(Server-side Forward)

客户端跳转的时机非常早,JSP 在遇到这句代码时:

response.sendRedirect("responseDemo04.jsp?uname=ZTE");

会立刻:

终止后续 JSP 执行(包括页面还没输出的 HTML)

把响应状态设置成 302(重定向)

让浏览器主动发起新请求访问目标地址

如果你想要先显示一部分页面再跳转,那就不是 sendRedirect 的用途,而需要用 JavaScript 来实现:

<h1>欢迎光临</h1>

<script>

setTimeout(() => {

window.location.href = "responseDemo04.jsp?uname=ZTE";

}, 2000); // 2秒后跳转

</script>

response.setHeader("refresh",...) 也是客户端跳转 ,类似 sendRedirect,通过 HTTP 响应头控制刷新跳转

<%--<jsp:forward page="responseDemo04.jsp"/>--%>

它是另一种服务端跳转写法,和 request.getRequestDispatcher(...).forward(...) 是等价的,写法更简洁

http://localhost:8080/Web_exploded/responseDemo03.jsp

复制代码
<!--http://127.0.0.1:8080/test/base/05/cookieDemo01.jsp?name=tom&password=123-->
<%
	String uname=request.getParameter("name");
	String upass=request.getParameter("password");
	Cookie c1 =null;
	Cookie c2 =null;
	if("tom".equals(uname)&&"123".equals(upass))
	{
		c1 = new Cookie("name",uname) ;
		c2 = new Cookie("password",upass) ;

		// 保存时间为60秒
		//c1.setMaxAge(60) ;
		//c2.setMaxAge(60) ;
	}

	// 通过response对象将Cookie设置到客户端
	response.addCookie(c1) ;
	response.addCookie(c2) ;
%>

<!-- 访问示例:http://127.0.0.1:8080/test/base/05/cookieDemo01.jsp?name=tom\&password=123 -->

你需要用浏览器访问这个地址,带上参数 name=tom&password=123

默认浏览器关闭时 Cookie 消失;设置了 setMaxAge() 后可以保留固定时间

系统 Cookie:浏览器自动携带,例如 JSESSIONID(Session ID)

用户 Cookie:程序员手动通过 new Cookie(...) 创建的,比如你这里的 name 和 password

使用 Session 实现用户身份验证

复制代码
<%@page contentType="text/html;charset=gb2312"%>
<form action="login.jsp" method="post">
	用户名:<input type="text" name="uname"><br>
	密码:<input type="text" name="upass"><br>
	<input type="submit" value="登陆">
</form>

<%
	// 判断是否有请求内容
	// 在自提交的页面中,必须对程序第一次运行做出处理
        if(request.getParameter("uname")!=null&&request.getParameter("upass")!=null)
	      {
		// 第一次的时候,并不能取得请求的参数
		 String name = request.getParameter("uname") ;
		String password = request.getParameter("upass") ;
		  System.out.println("name:"+name) ;
		  System.out.println("password:"+password) ;
		 if(name.equals("admin")&&password.equals("admin"))
		 {
			// 表示登陆成功
			// 通过flag属性判断用户是否已经登陆
			session.setAttribute("flag","ok") ;
			// 跳转到sucess.jsp
			//response.sendRedirect("sucess.jsp") ;
			%>
		<jsp:forward page="sucess.jsp"/>
		<%
		}
		else
		{
			 
	      response.sendRedirect("error.jsp");
	 
		  }
	   } 
%>

<form action="login.jsp" method="post">

这句话的意思是:

当你在输入框里填完用户名和密码

然后点击"登录"按钮

浏览器会自动把你填写的内容通过 HTTP 的 POST 方法发回给 login.jsp 页面本身

这个提交过程是 浏览器自己完成的,你无需手动在地址栏输入任何参数

response.setHeader("refresh", "2;URL=login.jsp");

其中的数字 2 表示:

✅ 在页面显示当前内容 2 秒后,自动跳转到 login.jsp 页面。

Refresh: 秒数;URL=跳转地址

所以这句的意思就是:

当前页面停留 2 秒

然后自动跳转回 login.jsp

你在浏览器看到的是:"登录失败"显示 2 秒 → 页面自动返回登录界面

在 JSP 或 Web 开发中,URL=login.jsp 这样的写法是相对路径

它并不一定非要写完整的 http://localhost:8080/xxx/login.jsp

session.setAttribute("flag", "ok");

它的作用是:

在服务器端为当前访问用户的 Session 中,保存一条数据:键是 "flag",值是 "ok"。

这就像是贴了一个标签,告诉服务器:"这个用户已经登录了"。

<jsp:forward page="sucess.jsp"/>

确实,这句是页面跳转语句,但跳转本身并不判断用户是否登录,它只是跳页面。

而:

session.setAttribute() 是用来标记身份的,跳转之后别的页面可以判断是否有这个标记。

相关推荐
哆啦刘小洋3 小时前
HTML Day04
前端·html
数据潜水员4 小时前
C#基础语法
java·jvm·算法
你这个代码我看不懂5 小时前
Java项目OOM排查
java·开发语言
Zong_09155 小时前
AutoCompose - 携程自动编排【开源】
java·spring boot·开源·自动编排
敲代码的小吉米5 小时前
前端HTML contenteditable 属性使用指南
前端·html
.生产的驴5 小时前
SpringCloud 分布式锁Redisson锁的重入性与看门狗机制 高并发 可重入
java·分布式·后端·spring·spring cloud·信息可视化·tomcat
虾球xz6 小时前
CppCon 2014 学习:C++ Memory Model Meets High-Update-Rate Data Structures
java·开发语言·c++·学习
攒了一袋星辰6 小时前
Spring @Autowired自动装配的实现机制
java·后端·spring
Bug缔造者6 小时前
若依+vue2实现模拟登录
java·前端框架
潘yi.6 小时前
Nginx+Tomcat负载均衡群集
nginx·tomcat·负载均衡