JSP
之前我们写登录的时候,为了响应登录失败的错误信息,特意创建一个LoginErrorServlet用来动态拼接错误信息。
【总结一下】
在servlet中,能够直接获取后台服务器中的数据:获取数据方便。
通过拼接字符串的形式,给浏览器响应html:操作麻烦,效率太低,阅读性差。
现在可以用JSP技术,既能直接书写html代码,又能书写servlet代码。这样就能够在客户端直接进行数据交互了。
JSP全名为Java Server Pages,中文名叫java服务器页面,其本质是一个简化的Servlet 设计,它是由Sun 公司倡导、许多公司参与一起建立的一种动态网页 技术标准。其实就是一个既能书写Servlet代码又能书写HTML代码的文件。
新建的JSP文件长这样:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
</body>
</html>
试着在JSP中写代码
<head>
<title>Title</title>
</head>
<body>
<%--在jsp页面上获取当前日期,将其格式化成字符串“yyyy-MM-dd HH:mm:ss”--%>
<%
LocalDateTime now=LocalDateTime.now();
LocalDate now1= LocalDate.now();
LocalTime now2=LocalTime.now();
System.out.println(now);
%>
</body>
</html>
JSP运行原理
我们通过浏览器访问到的jsp页面,最终访问的是tomcat服务器中的jsp页面。所以,我们可以到tomcat中查看一下上面案例中的jsp页面是怎么样的一种存在。IntilliJ IDEA借助tomcat发布web项目的机制是动态发布(为每一个web项目创建一个单独的发布文件)。
我们可以通过tomcat其中日志中的CATALINA_BASE路径找到我们当前这个JSP页面在tomcat中的位置,打开之后会发现demo01.jsp编译为demo01.java文件,再编译成.class文件运行。
打开demo01_jsp.java文件后,发现我们在JSP页面上写的代码都在_jspService方法中:
- <% %> 中书写的代码被直接解析成java代码;
- html部分都被out.write("")方法以字符串的形式拼接,然后响应给浏览器;
- 在这个java文件中有个_jspService,这个方法有两个参数request,response。由此可看出JSP本质上就是一个Servlet。
JSP中写java代码的三种方式
在JSP页面的body标签中,可以直接书写html代码和JS代码。但是,如果在JSP页面中书写java代码。必须遵循固定的格式,才能够生效;JSP页面中书写java代码有三种方式:1.脚本片段;2.脚本声明;3.脚本表达式;
方式一:脚本片段
脚本片段指的是一段java代码。书写格式:<% java 代码 %>
方式二:脚本声明
脚本片段虽然可以嵌入java代码,但是如果,我们要给当前的jsp中定义一些成员方法或者成员变量,就行需要一个新的技术——脚本声明.
脚本声明的格式:<%! 书写Java代码 %>
<%!
int a = 46;
public void method(){
System.out.print("");
}
%>
方式三:脚本表达式
虽然脚本声明和脚本片段已经可以书写Java代码了,但是如果我们要使用java代码向页面输出一些内容,还是需要 使用原来的response对象,比较繁琐,因此,我们需要一个更加简便的方式,可以代替response向页面输出内容 ——这个就是脚本表达式。
脚本表达式的格式:<%= 内容 %> 等价于:out.print(内容)
<%="开发使人聪明"%>
JSP页面常用对象
在JSP页面中写的代码最终都会翻译到_jspService()方法中,这个方法中有两个入参:HttpServletRequest对象 ,HttpServletResponse对象 。所以说,JSP的本质就是一个Servlet。我们可以直接在JSP页面上使用这两个对象。
EL表达式
因为,脚本表达式在JSP页面上书写起来比较麻烦。而在页面上取值在开发中使用的又比较多,所以Sun公司为了简化在页面上的取值操作。
EL表达式从session中取值:${sessionScope.msg}
——记得:要去Java中访问LoginServlet,才能访问JSP页面
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>登录页面</title>
<link href="css/bootstrap.min.css" rel="stylesheet">
<link href="css/login.css" rel="stylesheet">
<script src="js/jquery.js"></script>
<script src="js/bootstrap.js"></script>
</head>
<body>
<%
// String msg = (String) request.getAttribute("msg");
%>
<%--
EL表达式${msg} 从域对象中取值 session servletContext request
<%=%> 浏览器输出内容
优势:方便 简化开发 pageContext--%>
<div class="container text-center">
<form class="form-signin" action="/loginServlet" method="post">
<h2 class="form-signin-heading">登录页面</h2>
<%--<font color="red"><%=msg%></font>--%>
<font color="red">${msg}</font>
<input type="text" name="username" class="form-control" placeholder="用户名" required autofocus>
<input type="password" name="password" class="form-control" placeholder="密码" required>
<button class="btn btn-lg btn-primary btn-block" type="submit">登录</button>
</form>
</div>
</body>
EL简介
全称:Expression Language
作用:代替jsp中脚本表达式的功能,简化对java代码的操作,从【域对象】中取值。EL表达式简化<%= %>方法取值。
EL语法表达式:${表达式内容}
EL取值
JSP的四大域对象:
page域、request域、session域、application域。我们通常使用EL表达式从这四大域对象取值。四大域对象的详细信息:EL表达式从这四大域中取值
实践:
在一个jsp页面中,使用脚本表达式分别往request域、session域、ServletContext域和pageContext域中存取数据。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>四大域对象</title>
</head>
<body>
<%
//向四大域对象中存储值 EL表达式来获取值 ${}
pageContext.setAttribute("pageValue","page的值");
request.setAttribute("requestValue","request的值");
request.setAttribute("pageValue","request储存的其他值");
session.setAttribute("sessionValue","session的值");
application.setAttribute("applicationValue","application的值");
%>
<%--
直接通过KEY来获取域对象中的值-->key相同的时候
默认从范围小的开始检索,取值。
--%>
pageContext:${pageScope.pageValue}<br>
request:${requestScope.requestValue}<br>
session:${sessionScope.sessionValue}<br>
application:${applicationScope.applicationValue}<br>
request:${requestValue}<br>
相同key情况:${pageValue}
</body>
</html>
EL表达式搜索数据
EL表达式取值的时候也可以不指定域,如果取值的时候不指定域对象。就会按照从page域—>request域—>session域—>servletContext域从小到大逐级根据name属性值查找。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>EL表达式运算符</title>
</head>
<body>
<%
request.setAttribute("n1",40);
request.setAttribute("n2",30);
request.setAttribute("n3","20");
request.setAttribute("n4","10");
String str = "";
request.setAttribute("str",str);
User user = null;
request.setAttribute("user",user);
List<String> list = new ArrayList<>();
list.add("a");
request.setAttribute("list",list);
%>
<%--
三元运算符:表达式1?表达式2:表达式3
empty 空
String str=""
User user null empty true
List<T> size() 0 empty true
--%>
算数运算符:<br>
n1+n2:${n1+n2}<br>
n3-n4:${n3-n4}<br>
n1*n3:${n1*n3}<br>
关系运算符:<br>
n1==n2:${n1==n2}<br>
n4>=n3:${n4>=n3}<br>
n2!=n3:${n2 ne n3}<br>
逻辑运算符:<br>
false && true:${false && true}<br>
!true:${!true}<br>
三元运算符:<br>
${n1!=n2?"不等于":"等于"}<br>
empty运算符<br>
${empty str}<br>
${empty user}<br>
${not empty list}<br>
</body>
</html>
EL表达式从cookie中取值
servlet生成cookie
要去访问Java代码CreatCookieServlet,才能将cookie存储在浏览器中。
@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取用户提交信息
String username = request.getParameter("username");
String password = request.getParameter("password");
String check = request.getParameter("check");
//用户是否点击
if ("on".equals(check)){
//用户点击了 创建cookie
//创建cookieAPI
Cookie cookieName = new Cookie("username",username);
cookieName.getValue();
Cookie cookiePwd = new Cookie("pwd",password);
cookieName.setMaxAge(60*60*24*7);
cookiePwd.setMaxAge(60*60*24*7);
//将cookie响应回浏览器
response.addCookie(cookieName);
response.addCookie(cookiePwd);
}else {
//没有记住用户名和密码
}
}
}
empty运算(判空运算)
empyt运算符对以下数据运算返回true:
- 字符串:"";
- 空集合(size=0):List list = new ArrayList();
- 空对象(null):Student stu = null;
【注】not empty可以用在EL表达式中,判断非空的情况。
EL表达式小结:
- EL:Expression Language;
- EL语法:${ }
- 作用:简化脚本表达式的取值,简化<%= request.getAttribute(“name”) %> ===> ${name}
- jsp的四大域对象
- page域:pageContext pageContext.setAttrubute() pageContext.getAttribute() JSP特有 作用范围:当前的JSP页面
- requst域:request request.setAttribute() request.getAttribute() 作用范围:一次请求和响应之间
- session域: session session.setAttribute() session.getAttribute() 作用范围:会话期间(多次请求和响应)
- servletContext域:application application.setAttribute() application.getAttribute() 作用范围:整个项目;
- jsp从四大域中取值(指定域对象):
- ${pageScope .name}
- ${requestScope .name}
- ${sessionScope .name}
- ${applicationScope .name}
- JSP搜索域对象中的值:page — request — session — servletContext
- ${name}
- 运算
- 算术运算
- 关系运算
- 逻辑运算:&& || !
- 三元运算
- empty运算:empty notempty
- 空字符串:""
- 空对象:null
- 空集合:list.size = 0;
JSTL标签库
举个栗子:在页面中遍历数组
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>JSTL</title>
</head>
<body>
//缺点
代码复杂出现问题,前端工程师,后端工程师,维护成本过高。
java程序员抽取,方便复用,节约时间
JSTL
jsp页面尽量都是标签,不要出现java代码
标签底层都是java代码实现 实现了复用
<%
int[] arr = {123,456,789};
for (int i : arr) {
out.println("<h1>"+i+"</h1>");
}
%>
</body>
</html>
JSTL是什么
从JSP 1.1规范开始JSP就支持使用自定义标签,使用自定义标签大大降低了JSP页面的复杂度,同时增强了代码的重用性,因此自定义标签在WEB应用中被广泛使用。
许多WEB应用厂商都开发出了自己的一套标签库提供给用户使用,这导致出现了许多功能相同的标签,令网页制作者无所适从,不知道选择哪一家的好。
为了解决这个问题,
Apache Jakarta小组归纳汇总了那些网页设计人员经常遇到的问题,
开发了一套用于解决这些常用问题的自定义标签库,
这套标签库被SUN公司定义为标准标签库(The JavaServer Pages Standard Tag Library),简称JSTL。
使用JSTL可以解决用户选用不同WEB厂商的自定义标签时的困惑,JSP规范同时也允许WEB容器厂商按JSTL标签库的
标准提供自己的实现,以获取最佳性能
JSTL核心标签库需要两个包(依赖)
javax.servlet.jsp.jar
jstl-impl.jar
将标签库资源引入jsp页面
在JSP页面中通过以下标签,通过taglib标签引入JSTL资源:
<%@taglib prefix=“c” uri=“http://java.sun.com/jsp/jstl/core” %>
注意:prefix:是jstl标签在使用的时候的前缀
uri:是标签库的资源路径。
在JSP页面中使用JSTL标签
在JSP页面中书写"<c: ",如果出现如下图的提示则说明标签库引入成功,我们可以根据提示信息使用自己需要的标签。
<%@ 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>
<c:out value="你爱柳岩"></c:out>
</body>
</html>
常用的JSTL标签
<c:if test="">标签的作用相当于java中的if判断语句。
【需求】在success.jsp页面上进行如下判断
- 使用<c:if> 标签判断session中的用户信息是否为空;
- 如果不为空:获取session中的用户信息,并将其展示在页面上;
- 如果为空:提示用户登录;
<%
session.setAttribute("user",new User());
session.setAttribute("users",null);
int[] arr = {1,2,3,4,5};
for(int i: arr){
}
for(int i=0; i< 10; i++){
}
request.setAttribute("arr",arr);
%>
<c:if test="${user == null}">
用户登陆
</c:if>
<c:if test="${users == null}">
请登陆
</c:if>
<br>
<c:forEach var="i" items="${arr}">
${i}
</c:forEach>
<c:foreach>标签的作用相当于java中的for循环。主要是对数据和集合进行遍历。
c:foreach标签的属性
var:在不循环对象的时候,保存的是控制循环的变量;在循环对象的时候,保存的是被循环对象中的元素
items:指定要循环的对象
varStatus:保存了当前循环过程中的信息(循环的开始、结束、步长、次数等)
begin:设置循环的开始
end:设置循环的结束
step:设置步长——间隔几次循环,执行一次循环体中的内容
【案例】c:foreach遍历案例
【需求】
- 遍历普通数组;
- 遍历实体类对象list集合;
- 遍历map集合;
<html>
<head>
<title>商品列表</title>
</head>
<body>
<c:forEach var="item" items="${list}">
商品名:${item.name}--惊爆价:<font color="red">${item.price}</font><br>
</c:forEach>
</body>
</html>
@WebServlet("/product")
public class ProductServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//去数据库查询所有商品信息
//页面展示5 select * from product limit 0,5
List<Product> list = new ArrayList<>();
list.add(new Product("电脑",9.9));
list.add(new Product("手机",2.8));
list.add(new Product("键盘",1.3));
//将查询的数据存放request域中
request.setAttribute("list",list);
//使用jsp来展示页面
request.getRequestDispatcher("list.jsp").forward(request,response);
}
}
遍历map集合
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<%
Map map = new HashMap();
map.put("one","抹茶妹妹");
map.put("two","刘强东");
map.put("thr","王宝强");
request.setAttribute("beiju",map);
%>
<c:forEach var="item" items="${beiju}">
map的key:${item.key}:map的value值:${item.value}<br>
</c:forEach>
</body>
</html>
choose标签
用于指定多个条件选择的组合边界,它必须与c:when和c:otherwise标签一起使用。三个标签组合与switch语法类似。
choose标签子标签
介绍 c:when,相当于case。
c:when标签含有test属性,作用与if相同 c:otherwise,相当于default。
choose标签注意事项
三个标签必须组合使用,一组标签中不能出现两个c:otherwise