JSP简介
JSP:Java Server Page,java服务器页面,是一个简化的Servlet设计。是在html中嵌入java代码。在执行时会被翻译为Servlet,然后编译执行。
Servlet的缺点: (1)Servlet需要进行配置,不方便维护;(2)Servlet很难向网页中输出HTML页面内容;
JSP一般作为请求发起页面,例如显示表单,超链接;或者作为请求结束页面,例如显示数据。
而Servlet作为请求中处理数据的环节。
运行结果:
JSP和Servlet分工案例
jsp页面:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="/web_test2_war_exploded/AServlet" method="post">
整数1:<input type="text" name="num1"> <br>
整数1:<input type="text" name="num2"> <br>
<input type="submit" value="提交">
</form>
</body>
</html>
Servlet计算:
public class AServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
int number1 = Integer.parseInt(req.getParameter("num1"));
int number2 = Integer.parseInt(req.getParameter("num2"));
int sum = number1 + number2;
// 保存结果到request域中
req.setAttribute("result", sum);
// 转发到result.jsp
req.getRequestDispatcher("/jsp/result.jsp").forward(req, resp);
}
}
内容展示:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%= request.getAttribute("result") %>
</body>
</html>
JSP运行原理
JSP文件会被服务器翻译成Java文件,会将Java文件编译生成class文件,最后来运行class文件。
JSP脚本元素
JSP = HTML + Java代码 + JSP自身内容
JSP的脚本元素就是在JSP中嵌入Java代码
声明标签(!)
语法:(写在这个脚本中的代码,会翻译成Servlet内部的成员变量或成员方法)
<%! 变量或方法声明 %>
<%!
// 声明变量
int i = 3;
%>
表达式标签(=)
语法:(写在这个脚本中的代码,会翻译成方法内部的out.print()当中的内容)
<%= 表达式 %>
<%= i+1 %>
程序代码标签(▲)
语法:(写在这个脚本中的代码,会翻译成方法内部的局部变量或代码片段)
<% 程序代码 %>
<%
int x = 5;
%>
<%= x %>
JSP指令元素
用于指示JSP执行的某些步骤、用于指示JSP表现的特定行为
语法:
<%@ 指令名称 属性名称=属性值 属性名称=属性值 ... %>
指令的分类:
- page指令:指示JSP页面的设置的属性和行为
- include指令(静态包含):指示JSP包含哪些其他的页面
- taglib指令(导入标签库):指示JSP页面要包含哪些标签库
page指令
page属性用来定义JSP文件的全局属性
这些属性是可以单独使用的,也可以多个同时使用。
在JSP页面中,只有import属性可以出现多次,其他属性都只能出现一次。
写法:
<%@ page 属性名称=属性值 属性名称=属性值 ...%>
Page指令属性:
- language:声明所使用的脚本语言,只能是Java
- extends:标明JSP编译成Servlet的时候所继承的类。默认值:"HttpJspBase"
- session:标明JSP中是否可以直接使用Session对象。默认值就是true
- buffer:标明JSP对客户端输出缓冲区的大小。默认值是8k
- autoFlush:如果缓冲区大小溢出了,是否会自动刷出。默认值是true
- import:导入Java的包或类(重要)
- contentType: 标明JSP被浏览器解析和打开的时候,采用的默认的字符集。它表示添加一个响应头:Content-Type!等同与
response.setContentType("text/html;charset=utf-8"); - pageEncoding: JSP文件及JSP翻译后的Servlet保存到硬盘上所采用的字符集
- isErrorPage:处理JSP页面异常,它指定当前页面是否为处理错误的页面!当该属性为 true 时,这个页面会设置状态码为 500!可以使用内置对象exception。
- errorPage:处理JSP页面异常,当前页面如果抛出异常,那么要转发到哪一个页面,由 errorPage来指定
- isElIgnore:通知JSP是否忽略EL表达式,默认false不忽略
- info :JSP说明性信息;
例子:
<%@page import="java.util.ArrayList"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" session="true"
errorPage="error.jsp" isElIgnore="false"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
session.setAttribute("key", "value");
List list = null;
ArrayList arrayList = null;
// int i = 1/0;
%>
</body>
</html>
include指令
作用:在JSP页面中去静态包含一个文件,同时由该JSP解析包含的文件内容(一起被翻译成servlet)
写法:
<%@ include 属性名称=属性值 属性名称=属性值 ...%>
include指令属性:
- file:指示JSP页面所包含的页面的路径
例子:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<%@ include file="logo.jsp" %>
<%@ include file="menu.jsp" %>
<h1>index.jsp 的 BODY 部分</h1>
</body>
</html>
taglib指令
作用:用于在JSP页面中引入标签库
写法:
<%@ taglib 属性名称=属性值 属性名称=属性值 ...%>
taglib指令属性:
- uri:引入的标签库的路径
- prefix:引入的标签库的别名
JSP的内置对象
JSP内置对象:指的是可以直接在JSP页面中使用的对象(无需创建)。
在Javaweb中一共四个域对象,其中Servlet中可以使用的是request、session、application三个对象。
而在JSP中可以使用pageContext、request、session、application四个域对象。
内置对象分类
内置对象分类:
- request【HttpServletRequest】:从客户端向服务器发送的请求对象
- response【HttpServletResponse】:从服务器端向客户端浏览器做出的响应对象
- session【HttpSessionre】:服务器为客户端创建的会话对象
- application【ServletContext】:代表整个应用,实际是获得的ServletContext对象(一个应用只有一个)
- out【JspWriter】:等同response.getWriter(),向输出流写入内容的对象
- page【Object】:当前的JSP被翻译成Servlet后的对象的引用
- pageContext【PageContext】: 当前的JSP页面的上下文对象
- config【ServletConfig】:本JSP的ServletConfig对象
- exception【Throwable】:表示JSP页面所运行时产生的异常对象
PageContext对象
pageContext:页面上下文对象,代表当前页面运行的一些属性。包路径:javax.servlet.jsp.PageContext
作用:
- 提供了page范围的数据存取的方法;
- getAttribute()
- setAttribute()
- removeAttribute()
- findAttribute() :全局查找,四大域查找
- 通过这个对象获得其他的8个内置对象;
- getXXX()--对应对象
- getOut()--父类中
JSP四个作用范围
- PageScope:页面范围
- 指的是当前页面范围内有效,出了这个页面后pageContext保存的数据就无效了
- RequestScope:请求范围
- 从客户端向服务器发送一次请求,服务器对这次请求做出响应之后,用request保存的数据就无效了
- SessionScope:会话范围
- 每个浏览器向服务器发送请求(可以多次请求),将该会话结束后,保存的数据就无效了
- ApplicationScope:应用范围
- 在整个应用任意的地方都可以获取。
例子:
<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>JSP的四个作用范围</h1>
<%
// page范围(pageContext对象)
pageContext.setAttribute("name", "pageContext-张三");
// request范围
request.setAttribute("name", "request-李四");
pageContext.setAttribute("name", "request-李四", PageContext.REQUEST_SCOPE);
// session范围
session.setAttribute("name", "session-王五");
pageContext.setAttribute("name", "session-王五", PageContext.SESSION_SCOPE);
// application范围
application.setAttribute("name", "application-赵六");
pageContext.setAttribute("name", "application-赵六", PageContext.APPLICATION_SCOPE);
%>
<h1>当前页面获取值(四种都有效)</h1>
<%= pageContext.getAttribute("name") %>
<%= request.getAttribute("name") %>
<%= pageContext.getAttribute("name", PageContext.REQUEST_SCOPE) %>
<%= session.getAttribute("name") %>
<%= pageContext.getAttribute("name", PageContext.SESSION_SCOPE) %>
<%= application.getAttribute("name") %>
<%= pageContext.getAttribute("name", PageContext.APPLICATION_SCOPE) %>
<%-- <!-- 转发到demo2.jsp,3种可以生效(request+session+application) -->--%>
<%-- <% request.getRequestDispatcher("/jsp/demo2.jsp").forward(request, response); %>--%>
<!-- 请求跳转到demo2.jsp,2种可以生效(session+application) -->
<a href="/web_test2_war_exploded/jsp/demo2.jsp">请求跳转demo2.jsp</a>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>demo2.jsp 当前页面获取值(三种有效)</h1>
<%= pageContext.getAttribute("name") %> <%--null--%>
<%= request.getAttribute("name") %>
<%= session.getAttribute("name") %>
<%= application.getAttribute("name") %>
</body>
</html>
JSP动作标签
JSP动作标签:用于在JSP页面中提供业务逻辑功能,避免在JSP页面中直接编写Java代码。
动作标签
<jsp:forward/>:请求转发,与RequestDispatcher.forward()方法一致
<jsp:include/>:包含(动态包含,与RequestDispatcher的include方法一样)
<jsp:param/>:传递参数
例子:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>JSP Demo3</title>
</head>
<body>
<h1>jsp:forward 请求转发</h1>
<%-- <jsp:forward page="demo4.jsp"></jsp:forward>--%>
<h1>jsp:include 包含</h1>
<jsp:include page="demo4.jsp"></jsp:include>
</body>
</html>
动态包含的原理:
JavaBean相关标签
- <jsp:useBean> --> 创建或查询bean
- <jsp:setProperty> --> 给JavaBean设置属性值
- <jsp:getProperty> --> 获取属性值
<jsp:useBean id= "user1" class= "cn.itcast.domainUser" />
<jsp:setProperty property= "username" name="user1" value= "admin"/>
<jsp:setProperty property= "passvord" name= "user1" value="admin123"/>`
用户名:
<jsp:getProperty property= "username" name= "user1"/><br/>
密码:
<jsp:getProperty property= "passvord" name="user1"/><br/>
EL表达式语言
概述
EL(Expression Language)表达式语言, 是为了使JSP写起来更加简单。它提供了在JSP中简化表达式的方法,让Jsp的代码更加简化。EL可以和JSTL一起使用,取代JSP页面中嵌入Java代码的写法(<%%>)。功能:
- 获取数据
- 执行运算
- 获取web开发常用对象
- 调用Java中的方法(少)
EL 替代的是<= ... >,也就是说,EL只能做输出
EL语法:
${ EL表达式 }
获取数据
EL表达式在执行的时候,会调用pageContext.getAttribute()方法,分别从四个范围查找对应的对象,找到返回对象,找不到返回""(空字符串)
顺序:pageContext > request > response > application
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>EL获取数据</h1>
<%
pageContext.setAttribute("name", "张三");
// request.setAttribute("name", "李四");
session.setAttribute("name", "王五");
application.setAttribute("name", "赵六");
%>
<%= pageContext.getAttribute("name") %> - ${ pageScope.name } <br>
<%= request.getAttribute("name") %> - ${ requestScope.name } <br> <%--null--%>
<%= session.getAttribute("name") %> - ${ sessionScope.name } <br>
<%= application.getAttribute("name") %> - ${ applicationScope.name } <br>
<h1>EL简写</h1>
${ name } <%--张三--%>
</body>
</html>
获取数组和集合中的数据
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>EL获取数组中的数据</h1>
<%
String[] arrs = {"aaa", "bbb", "ccc"};
pageContext.setAttribute("arrs", arrs);
%>
${ arrs[0] } <%--aaa--%>
${ arrs[1] } <%--bbb--%>
${ arrs[2] } <%--ccc--%>
${ arrs[3] } <%--空--%>
<h1>EL获取List集合中的数据</h1>
<%
List<String> list = new ArrayList<>();
list.add("111");list.add("222");list.add("333");
pageContext.setAttribute("list", list);
%>
${ list[0] }
${ list[1] }
${ list[2] }
${ list[3] } <%--空--%>
<h1>EL获取Map集合中的数据</h1>
<%
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("aaa", 111);
map.put("bbb", 222);
map.put("ccc", 333);
pageContext.setAttribute("map", map);
%>
${ map.aaa }
${ map.bbb }
${ map.ccc } <%--333--%>
${ map["ccc"] } <%--333--%>
</body>
</html>
执行运算
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
pageContext.setAttribute("n1", 10);
pageContext.setAttribute("n2", "20");
pageContext.setAttribute("n3", 30);
pageContext.setAttribute("n4", 40);
%>
<h1>EL执行算数运算</h1>
${ n1+n2 } <%--30--%>
${ n2-n1 } <%--10--%>
<h1>EL执行关系运算</h1>
${ n1==n2 } <%--false--%>
${ n1 eq n2 } <%--false--%>
${ n1 < n2 } <%--true--%>
${ n1 lt n2 } <%--true--%>
${ n1 > n2 } <%--false--%>
${ n1 gt n2 } <%--false--%>
<h1>EL执行逻辑运算</h1>
${ (n1<n2) && (n3<n4) } <%--true--%>
${ (n1<n2) and (n3<n4) } <%--true--%>
<h1>EL执行三元运算</h1>
${ n1<n2 ? "n1小于n2" : "n1大于n2" } <!-- n1小于n2 -->
<h1>空运算符</h1>
${ empty user } <%--true--%>
${ not empty user } <%--false--%>
</body>
</html>
获取web开发常用对象
- pageContext:相当于JSP内置对象中的 pageContext
- 作用1:向四个域中存入对象
- 作用2:获得其他的8个内置对象
- pageScore:获取指定域下的名称的数据
- requestScore :获取指定域下的名称的数据
- sessionScore :获取指定域下的名称的数据
- applicationScore :获取指定域下的名称的数据
- param:在页面中接收请求参数(接收一个名称对应一个值的参数)
- paramValues :在页面中接收请求参数(接收一个名称对应多个值的参数)
- header:在页面上获取请求头(一个key对应一个value头)
- headerValues: 在页面上获取请求头 (一个key对应多个value头)
- cookie:获得cookie中的数据-名称和值
- initParam:获得全局初始化参数的值
<body>
<h1>EL获取web开发常用对象-param</h1>
${ param.name }
${ paramValues.hobby[0] }
${ paramValues.hobby[1] }
<h1>EL获取web开发常用对象-header</h1>
${ header["User-Agent"] }
<h1>EL获取web开发常用对象-cookie</h1>
${ cookie.key.name }
${ cookie.key.value }
</body>
pageContext.request.contextPath : 获取项目名
EL函数库
导入标签库:
<%@ tablib prefix="fn" uri=http://java.sun.com/jsp/jst1/functions%>
- string toUppercase (String input):把参数转换成大写
- String toLowercase (String input):把参数转换成小写
- int indexOf(String input,String substring):从大串,输出小串的位置
- boolean contains(String input,String substring):查看大串中是否包含小串
- boolean containsIgnoreCase(String input,String substring):忽略大小写的,是否包含
- boolean startsWith(String input,string substring):是否以小串为前缀
- boolean endsWith(String input,String substring):+是否以小串为后缀
- String substring (String input,int beginIndex,int endIndex):截取子串
- String substringAfter(String input,String substring):获取大串中,小串所在位置后面的字符串
- substringBefore(String input,String substring):获取大串中,小串所在位置前面的字符串
- string escapeXml(String input):把input中"<"、">"、"&"、"'"、""",进行转义
- string trim (String input) :去除前后空格
- String replace(String input,String substringBefore,String substringAfter):替换
- String[] split(String input,String delimiters):分割字符串,得到字符串数组
- int length(Object obj):可以获取字符串、数组、各种集合的长度
- String join(String array[],String separator):联合字符串数组
<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
String[] strs = {"a", "b", "c"};
List list = new ArrayList();
list.add("aaa");
pageContext.setAttribute("arr", strs);
pageContext.setAttribute("list", list);
%>
${ fn:length(arr) } <br> <%--3--%>
${ fn:length(list) } <br> <%--1--%>
${ fn:toLowerCase("Hello") } <br> <%--hello--%>
${ fn:toUpperCase("Hello") } <br> <%--HELLO--%>
${ fn:contains("abc", "a") } <br> <%--true--%>
${ fn:containsIgnoreCase("abc", "A") } <br> <%--true--%>
${ fn:endsWith("Hello.java", ".java") } <br> <%--true--%>
${ fn:startsWith("hello", "Hel") } <br> <%--false--%>
${ fn:indexOf("Hello-World", "Wo") } <br> <%--6--%>
${ fn:join(arr, ";") } <br> <%--a;b;c--%>
${ fn:replace("Hello-World", "-", "+") } <br> <%--Hello+World--%>
${ fn:join(fn:split("a;b;c", ";"), "-") } <br> <%-- a-b-c --%>
${ fn:substring("0123456789", 6, 9) } <br> <%--678--%>
${ fn:substring("0123456789", 5, -1) } <br> <%--56789--%>
${ fn:substringAfter("Hello-World", "-") } <br> <%--World--%>
${ fn:substringBefore("Hello-World", "-") } <br> <%--Hello--%>
${ fn:trim("a b c") } <br> <%--a b c--%>
${ fn:escapeXml("<html></html>") } <br> <%--<html></html>--%>
</body>
</html>
EL自定义函数库
JSTL标签库
JSTL(Java server pages standarded tag library,即JSP标准标签库),是apache对EL表达式的扩展,一个标准通用的标签库。可以利用这些标签取代JSP页面上的Java代码。
标签库:
- c标签(core标签库)
- fmt标签(格式化的标签库)
- xml标签(xml 标签库,过时了)
- sql标签(数据库标签库,过时了)
- JSTL函数库(EL函数)
基本使用
jar包下载地址:www.runoob.com/jsp/jsp-jst…
放入WEB-INF下面的lib文件夹中。然后引入标签库:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
代码:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<% pageContext.setAttribute("name1", "haha"); %>
${ name1 }
<!-- JSTL写法 -->
<c:set value="hahaha" var="name2" scope="page"></c:set>
${ name2 }
</body>
</html>
core标签库常用标签
- <c:out>:输出
- value:可以是字符串常量,也可以是EL表达式
- default:当要输出的内容为null时,会输出default指定的值
- escapeXml::默认值为true,表示转义。为false时不会转换<和>
- <c:set>:设置(创建域的属性)
- var:变量名
- value:变量值,可以是EL表达式
- scope:域,默认为page,可选值:page、request、session、application
- <c:remove>:删除域变量
- var:变量名
- scope:要删除哪个域里面的。如果不给出,默认删除所有域中的该名称的变量
- <c:url>:输出url、把url保存到域中
- value:指定一个路径。它会在路径前面自动添加项目名
- <c:param>子标签:用来给url后面添加参数
- var:指定变量名,一旦添加了这个属性,那么 url 标签就不会再输出到页面,而是把生成的 url 保存到域中
- scope:它与 var 一起使用,用来保存 url
- <c:if>:test为真时,执行标签体内容
- test 属性:条件(Boolean类型的值)
- var 属性:将test中条件的值赋值给一个变量,在var中定义变量
- scope属性:作用范围
- <c:choose>:when标签的test为true时,会执行这个when的内容
- when
- otherwise
- <c:forEach>:用来循环遍历数组、集合,还可以用计数方式来循环
- 用计数方式来循环
- var:循环变量
- begin:设置循环变量从几开始。
- end:设置循环变量到几结束。
- step:设置步长!等同于 Java 中的 i++,或 i+=2。Step 默认值为1
- 用来输出数组、集合
- items:指定要循环谁,它可以是一个数组或一个集合。
- var:把数组或集合中的每个元素赋值给var指定的变量。
- 用计数方式来循环
例子:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<% pageContext.setAttribute("name1", "name1"); %>
${ name1 } <br> <%--name1--%>
<c:set value="name2" var="name2" scope="page"></c:set>
${ name2 } <br> <%--name2--%>
<% request.setAttribute("code1", "<script>alert('hello');</script>"); %>
${ code1 } <%--alert弹窗--%>
<c:out value="${code1}"></c:out> <%--<script>alert('hello');</script>--%>
<c:out value="${code1}" escapeXml="false"></c:out> <%--alert弹窗--%>
<hr>
<%
pageContext.setAttribute("a", "pageContext");
request.setAttribute("a", "request");
session.setAttribute("a", "session");
application.setAttribute("a", "application");
%>
<c:remove var="a" scope="page" />
<c:out value="${a}" default="none"/> <br> <%--request(因为pageContext已经被删除了)--%>
<c:remove var="a"/>
<c:out value="${a}" default="none"/> <br> <%--none--%>
<hr>
<c:url value="/jsp/demo3.jsp" /> <br> <%--/web_test3_war_exploded/jsp/demo3.jsp--%>
<c:url value="/jsp/demo3.jsp" var="url" scope="request"/> <br>
<c:out value="${ url }"/> <br>
<c:url value="/LoginServlet"> <br> <%--/web_test3_war_exploded/LoginServlet?username=abc&password=123--%>
<c:param name="username" value="abc"/>
<c:param name="password" value="123"/>
</c:url> <hr>
<c:set var="ifvar" value="hello"/>
<c:if test="${ not empty ifvar }">
<c:out value="${ ifvar }"/> <%--hello--%>
</c:if> <hr>
<c:set var="score" value="${ param.score }"/>
<c:choose>
<c:when test="${ score>100 || score<0 }">错误的分数:${score}</c:when>
<c:when test="${score >=80}">优秀</c:when>
<c:when test="${score >=60}">及格</c:when>
<c:otherwise>不及格</c:otherwise>
</c:choose>
</body>
</html>
if标签
if标签的属性:
- test 属性:条件
- var 属性:将test中条件的值赋值给一个变量,在var中定义变量
- scope属性:作用范围
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>JSTL的if标签</h1>
<c:set var="i" value="5" scope="page"></c:set>
<c:if test="${ i>=10 }">
<font color="red">i大于等于10</font>
</c:if>
<c:if var="flag" test="${ i<10 }" scope="page">
<font color="blue">i小于10</font>
</c:if>
<c:if test="${ flag }">
<font color="blue">i小于10</font>
</c:if>
</body>
</html>
foreach标签
<%@page import="java.util.HashMap"%>
<%@page import="java.util.Map"%>
<%@page import="java.util.ArrayList"%>
<%@page import="java.util.List"%>
<%@page import="com.sun.corba.se.spi.orb.StringPair"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>JSTL的foreach标签</h1>
<h3>遍历数组</h3>
<%
String[] arrs = {"aaa", "bbb", "ccc"};
pageContext.setAttribute("arrs", arrs);
%>
<c:forEach var="s" items="${ arrs }">
${ s }
</c:forEach>
<h3>遍历List集合</h3>
<%
List<String> list = new ArrayList<String>();
list.add("qqq");list.add("www");list.add("eee");
pageContext.setAttribute("list", list);
%>
<c:forEach var="s" items="${ list }">
${ s }
</c:forEach>
<h3>遍历Map集合</h3>
<%
Map<Integer, String> map = new HashMap<Integer, String>();
map.put(1, "1111");map.put(2, "2222");map.put(3, "3333");
pageContext.setAttribute("map", map);
%>
<c:forEach var="entry" items="${ map }">
${ entry } <!-- 1=1111 2=2222 3=3333 -->
</c:forEach>
<h3>遍历1-10</h3>
<c:forEach var="i" begin="1" end="10" step="1">
${ i }
</c:forEach>
<h3>遍历100-200 到第三个数,数字变为蓝色</h3>
<c:forEach var="i" begin="100" end="200" step="2" varStatus="status">
<c:if test="${ status.count%3 ==0 }">
<font color="blue">${ i }</font>
</c:if>
<c:if test="${ status.count%3 !=0 }">
<font>${ i }</font>
</c:if>
</c:forEach>
</body>
</html>
foreach循环状态变量
forEach 标签还有一个属性: varStatus,这个属性用来指定接收“循环状态“的变量名,例如:<forEach varStatus="vs" …/>,这时就可以使用vs这个变量来获取循环的状态。
- count:int 类型,当前已遍历元素的个数;
- index:int 类型,当前元素的下标;
- first:boolean类型,是否为第一个元素;
- last:boolean类型,是否为最后一个元素;
- current:Object 类型,表示当前项目。
<%@ page import="java.util.ArrayList" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
ArrayList list = new ArrayList<String>();
list.add("1⃣️一一一");
list.add("2⃣️二二二");
list.add("3⃣️三三三");
pageContext.setAttribute("list", list);
%>
<c:forEach items="${list}" var="element" varStatus="vs">
${element},当前已遍历元素的个数:${vs.count},当前元素的下标:${vs.index},
当前是否是第一个:${vs.first},当前是否是最后一个:${vs.last}。当前元素是:${vs.current}
<br>
</c:forEach>
</body>
</html>
fmt格式化标签
用来格式化输出的,通常需要格式化的有时间和数字
- 格式化时间
- value:指定一个Date类型的变量
- pattern:用来指定输出的模板!例如:yyyy-MM-dd HH:mm:ss
- 格式化数字
- 0.00 四舍五入,且以0进行补位
- #.## 四舍五入,不补位
<%@ page import="java.util.Date" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
Date date = new Date();
pageContext.setAttribute("date", date);
%>
<fmt:formatDate value="${date}" pattern="yyyy-MM-dd HH:mm:ss" /> <br> <%--2022-10-03 16:34:28--%>
<%
double d1 = 3.1415926;
double d2 = 4.4;
pageContext.setAttribute("d1", d1);
pageContext.setAttribute("d2", d2);
%>
<fmt:formatNumber value="${d1}" pattern="0.000"/> <br> <%--3.142--%>
<fmt:formatNumber value="${d2}" pattern="0.000"/> <br> <%--4.400--%>
<fmt:formatNumber value="${d1}" pattern="#.###"/> <br> <%--3.142--%>
<fmt:formatNumber value="${d2}" pattern="#.###"/> <br> <%--4.4--%>
</body>
</html>
MVC开发模式
动态网页开发模式
| 开发模式不同阶段 | 缺点/优点 |
|---|---|
| 第一阶段:Servlet | 缺点:显示HTML元素时非常麻烦 |
| 第二阶段:JSP | 优点:显示数据方便;缺点:数据的封装和处理 |
| 第三阶段:JSP+JavaBean | 优点:显示数据和封装数据方便;缺点:维护麻烦 |
| 第四阶段:JSP+Servlet+JavaBean | 优点:JSP显示数据、JavaBean封装和处理数据、Servlet控制调度 |
JSP+Servlet+JavaBean,称为MVC开发模式。MVC解释如下:
- M(Model):模型层
- V(View):视图层
- C(Controller):控制层
流转链路:
请求 --> Servlet(控制层)--> JavaBean(模型层)--> JSP(视图层)
Request作为域对象存取数据
作用范围: Request对象中所保存的数据有效期是一次请求范围。
一次请求范围:从浏览器向服务器发送一次请求,服务器针对这次请求做出响应,响应后请求被销毁,保存的数据就失效了。
请求转发 & 重定向
请求转发:
- 通过ServletRequest对象获得RequestDispatcher对象;
- 根据RequestDispatcher中的forward()方法进行请求的转发;
重定向:
- 使用HttpServletResponse里面的sendRedirect()方法实现重定向;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 方式1:请求转发
RequestDispatcher requestDispatcher = request.getRequestDispatcher("/demo3/dem1.jsp");
requestDispatcher.forward(request, response);
// 方式2:重定向
response.sendRedirect("/web02/demo3/demo1.jsp");
}
两者区别:
- 请求转发是一次请求一次响应,而重定向是两次请求两次响应
- 请求转发地址栏是不会变化的,重定向地址栏发生变化
- 请求转发路径不带工程名,重定向需要带工程名路径
- 请求转发只能在本网站内部,重定向可以定向到任意网站
如果需要使用request进行值传递,需要通过请求转发完成;
如果页面需要跳转到其他网站,必须要使用重定向完成;
实践案例1(登录)
1、需求分析
需求:
- 提供登录页面,用户名密码查询数据库;
- 登录失败时回到登录页面(给提示信息);
- 登录成功,页面跳转,显示登录成功的总人数;
2、准备:创建库表
create database web_test;
use web_test;
create table user2(
uid int primary key auto_increment,
username varchar(20),
password varchar(20),
nickname varchar(20)
);
insert into user2 values (null, 'zhangsan', '123', '张三');
insert into user2 values (null, 'lisi', '123', '李四');
insert into user2 values (null, 'wangwu', '123', '王五');
3、创建项目工程
4、引入相关资源
数据库驱动包、C3P0连接池jar包、DBUtils
C3P0配置文件:
工具类:
package com.login.utils;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class JDBCUtils {
// 创建一个连接池,只需要创建一次即可
private static final ComboPooledDataSource dataSource = new ComboPooledDataSource();
/**
* 获得连接的方法
*/
public static Connection getConnection() {
Connection connection = null;
try {
connection = dataSource.getConnection();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return connection;
}
public static DataSource getDataSource() {
return dataSource;
}
/**
* 释放资源的方法
*/
public static void release(Statement statement, Connection connection) {
if (statement != null) {
try {
statement.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
statement = null;
}
if (connection != null) {
try {
connection.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
connection = null;
}
}
public static void release(Statement statement, Connection connection, ResultSet resultSet) {
release(statement, connection);
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
resultSet = null;
}
}
}
5、登录实现
登录流程:
登录页面(login.jsp)->登录的Servlet(LoginServlet,接收数据,封装到JavaBean)->调用另一个JavaBean处理数据,根据处理结果进行页面跳转
登录页面:
<%--
Created by IntelliJ IDEA.
User: wanghao39
Date: 2022/9/18
Time: 下午1:41
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<h1>登录页面</h1>
<%
String msg = "";
// 判断request域中是否存在错误信息
if (request.getAttribute("msg") != null) {
msg = (String) request.getAttribute("msg");
}
%>
<h3><%= msg %></h3>
<form action="/web_login_war_exploded/LoginServlet" method="post">
<table border="1" width="400">
<tr>
<td>用户名</td>
<td><input type="text" name="username" /></td>
</tr>
<tr>
<td>密码</td>
<td><input type="password" name="password" /></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="登录" /></td>
</tr>
</table>
</form>
</body>
</html>
登录Servlet:
package com.login.controller;
import com.login.domain.User;
import com.login.model.UserModel;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
// 接收数据
req.setCharacterEncoding("UTF-8");
String username = req.getParameter("username");
String password = req.getParameter("password");
// 封装数据
User user = new User();
user.setUsername(username);
user.setPassword(password);
// 处理数据
UserModel userModel = new UserModel();
User existUser = userModel.login(user);
// 页面跳转
if (existUser == null) {
// 登录失败,向request域保存失败信息
req.setAttribute("msg", "用户名或密码错误");
// 使用请求转发进行页面跳转
req.getRequestDispatcher("/index.jsp").forward(req, resp);
} else {
// 登录成功,记录人数
int count = (int) this.getServletContext().getAttribute("count") + 1;
this.getServletContext().setAttribute("count", count);
// 使用重定向进行页面跳转
resp.sendRedirect("/success.jsp");
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
数据处理:
package com.login.model;
import com.login.domain.User;
import com.login.utils.JDBCUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import java.sql.SQLException;
public class UserModel {
public User login(User user) throws SQLException {
// 处理数据
QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource());
User existUser = queryRunner.query("select * from user2 where username = ? and password = ?",
new BeanHandler<User>(User.class), user.getUsername(), user.getPassword());
return existUser;
}
}
初始化:
package com.login.controller;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
public class InitServlet extends HttpServlet {
@Override
public void init() throws ServletException {
int count = 0;
this.getServletContext().setAttribute("count", count);
}
}
成功页面:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>恭喜登录成功!</h1>
<%
int count = 0;
if(request.getServletContext().getAttribute("count") !=null) {
count = (int)request.getServletContext().getAttribute("count");
}
%>
<h3>目前登录成功总人数:<%=count %></h3>
</body>
</html>