JSP核心技术
什么是JSP
JSP全称是Java Server Pages,它和servle技术一样,都是SUN公司定义的一种用于开发动态web资源的技术。JSP/Servlet规范。JSP实际上就是Servlet
JSP这门技术的最大的特点在于,写jsp就像在写html,但它相比html而言,html只能为用户提供静态数据,而Jsp技术允许在页面中嵌套java代码,为用户提供动态数据
JSP和servlet
都可以用于开发动态web资源
servlet作为web应用中的控制器组件:
servlet只负责响应请求产生数据,并把数据通过转发技术带给jsp
JSP技术作为数据显示模板:
数据的显示
JSP语法
JSP模板元素
JSP页面中的HTML内容称之为JSP模版元素。
JSP模版元素定义了网页的基本骨架,即定义了页面的结构和外观
JSP脚本表达式
JSP脚本表达式(expression)用于将程序数据输出到客户端
语法:<%= 变量或表达式 %>
注意:SP脚本表达式中的变量或表达式后面不能有分号
JSP脚本片段
JSP脚本片断,用于在JSP页面中编写多行Java代码。
语法: <% 多行java代码 %>
注意: 每执行语句后面必须用分号(;)结束。
JSP声明
JSP页面中编写的所有代码,默认会翻译到servlet的service方法中,而Jsp声明中的java代码被翻译到_jspService方法的外面。
语法 <%! java代码 %>
理解:就是把局部变量变成成员变量【全局变量】
JSP注释
JSP注释的格式: <%-- 注释信息 --%>
JSP引擎在将JSP页面翻译成Servlet程序时,忽略JSP页面中被注释的内容.
JSP指令
JSP指令(directive)是为JSP引擎而设计的,它们并不直接产生任何可见输出,而只是告诉引擎如何处理JSP页面中的其余部分。
分类
在JSP 2.0规范中共定义了三个指令:
- page指令:导包,响应编码格式
- include指令 :导外界的jsp
- taglib指令 :导标准标签库,函数库
语法: <%@ 指令 属性名=“值” %>
如果一个指令有多个属性,这多个属性可以写在一个指令中,也可以分开写。
<%@ page contentType=“text/html;charset=utf-8” import=“java.util.Date”%>
也可以这样写
<%@ page contentType=“text/html;charset=utf-8”%><%@ page import=“java.util.Date”%>
EL
EL表达式:expression language 表达式语言
它不是一种开发语言,是jsp中获取数据的一种规范
注意:EL表达式查找的范围顺序,以及如何获取请求的参数信息
查找的范围顺序
EL获取四大域里的数据
优先级别:页面域>请求域>会话域>全局域
一层层的找
el底层理解:${msg}
<% Object msg = pageContext.getAttribute("msg"); if(msg != null){ out.print(msg); return; } msg = request.getAttribute("msg"); if(msg != null){ out.print(msg); return; } msg = session.getAttribute("msg"); if(msg != null){ out.print(msg); return; } msg = application.getAttribute("msg"); if(msg != null){ out.print(msg); return; } %>
使用:
1.获取到请求参数
<%
String msg = (String) request.getAttribute("msg");
%>
<%=(msg!=null)?msg:""%>
el: ${msg}
2.获取对象属性
<%@ page import="com.ckl.pojo.Student" %>
<%
Student student = (Student) request.getAttribute("student");
%>
<%=student.getUsername()%>
el : ${student.username}
底层反射,但找的get()set()
4.获取List的元素
<%
List<Book> list = new ArrayList<Book>();
list.add(new Book(01,"a",1));
list.add(new Book(02,"b",2));
list.add(new Book(03,"c",3));
request.setAttribute("list", list);
%>
el : ${list[0].bookName}
5.获取Map的元素
<%
Map<String,String> map = new HashMap<String,String>();
map.put("01", "a");
map.put("02", "b");
map.put("03", "c");
request.setAttribute("map", map);
%>
el : ${map[“01”]}
6.三元运算符结合结果来做信息提示
<input type="radio" name="sex" value="man" <%=(student.getSex().equals("man"))?"checked='checked'":""%>/>男
其中三元运算符el : ${(student.sex eq ‘man’)?“checked=‘checked’”:"}
注意
EL表达式对于null情况的处理,即不存在对应的key时,是怎么显示的?
如果EL表达式在全部的范围中都没有找到对应的key,就回传null,但EL表达式会做出优化,在页面上显示空白,而不是直接打印输出NULL
JSTL
JSTL(JavaServerPages Standard Tag Library)JSP标准标签库
作用:使用JSTL实现JSP页面中逻辑处理。优化JSP页面的逻辑代码(分支、循环)
使用
1)在JSP页面添加taglib指令
<%@ taglib uri=“http://java.sun.com/jsp/jstl/core” prefix=“c”%>
2)使用JSTL标签
<input type="checkbox" name="hobbies" value="football" <%=(student.getHobbies().contains("football"))?"checked='checked'":""%>/>足球
其中分支语句
<c:if test=“${fn:contains(student.hobbies, ‘football’)}”>
checked=‘checked’
</c:if >
<%for(StudentDto studentDto:studentDtos){%>
<tr>
<th>
</th>
</tr>
<%}%>
其中循环语句
<c:forEach items=“${page.list}” var=“studentDto”>
</c:forEach >
格式化
引入
<%@taglib uri=“http://java.sun.com/jsp/jstl/fmt” prefix=“fmt”%>
格式化
1.日期格式化
比如对象保存的属性为日期类型,希望展示的结果是我们期望的日期格式
<% Data date = new Data();
request.setAttribute("data",data);
%>
<fmt:formaDate value="${date}" pattern="yyy年MM月dd日HH点mm分ss秒"/>
2.格式化小数,保留两位小数点
<fmt:formatNumber value="123.123456789"pattern="0.00"/>
3.百分比格式化
<fmt:formatNumber type="percent" value="0.2345"/>
<fmt:formatNumber type="percent" value="0.2345"pattern="0.8%"/>
JSP标签
JSP标签也称之为Jsp Action(JSP动作)元素,它用于在Jsp页面中提供业务逻辑功能,避免在JSP页面中直接编写java代码,造成jsp页面难以维护。
<jsp:include >标签
优化分页
就是存起来,el用的时候就简化拼接即可【服务端设置好,客户端拼接】
原代码
<a href="GetStuListServlet?curPage=1">首页</a>
<%if(curPage > 1){%>
<a href="GetStuListServlet?curPage=<%=curPage-1%>">上一页</a>
<%}%>
<%if(curPage < totalPage){%>
<a href="GetStuListServlet?curPage=<%=curPage+1%>">下一页</a>
<%}%>
<a href="GetStuListServlet?curPage=<%=totalPage%>">尾页</a>
修改GetStuListServlet
不但简化GetStuListServlet?curPage=,还进一步将分页数据封装
//设置URL
String url = "GetStuListServlet?curPage=";
//封装Page对象
Page<StudentDto> page = new Page<>(url, curPage, totalPage, studentDtos);
//将数据存入到请求对象中
request.setAttribute("page",page);
el和JSTL处理,page.jsp存数据
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<a href="${page.url}1">首页</a>
<c:if test="${page.curPage > 1}">
<a href="${page.url}${page.curPage-1}">上一页</a>
</c:if>
<c:if test="${page.curPage < page.totalPage}">
<a href="${page.url}${page.curPage+1}">下一页</a>
</c:if>
<a href="${page.url}${page.totalPage}">尾页</a>
page.jsp,把展示代码写到其中,在其他jsp要用时进行导入
<jsp:include page="page.jsp"></jsp:include>
导入区别:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3nj5faeb-1722529879082)(https://i-blog.csdnimg.cn/direct/d5b601d6cd474b0288a6e78e55e0d67f.webp#pic_center)]
逻辑包含【动态】
将page.jsp里的数据通过IO流一点一点读取到当前页面(底层会有page_jsp.java文件)
<jsp:include page="page.jsp"></jsp:include>
物理包含【静态】
将rememberMe.jsp里的代码直接拷贝到当前JSP中(底层不会有rememberMe_jsp.java文件)
修改login.jsp
<%@ include file="rememberMe.jsp"%>
将login.jsp里面的记住我代码进行封装
<%@ page import="java.net.URLDecoder" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
Cookie[] cookies = request.getCookies();
if(cookies != null){
int count = 0;
for (Cookie cookie : cookies) {
String name = cookie.getName();
String value = URLDecoder.decode(cookie.getValue(),"UTF-8");
if("username".equals(name)){
session.setAttribute("username",value);
count++;
}
if("name".equals(name)){
session.setAttribute("name",value);
count++;
}
if("role".equals(name)){
session.setAttribute("role",value);
count++;
}
}
if(count == 3){
response.sendRedirect("index.jsp");
}
}
%>
<jsp:forward >标签
用于把请求转发给另外一个资源。
语法:<jsp:forward page=“relativeURL | <%=expression%>” /> page属性用于指定请求转发到的资源的相对路径
<jsp:param >标签
当使用jsp:include和jsp:forward标签引入或将请求转发给其它资源时,可以使用jsp:param标签向这个资源传递参数。
语法1: <jsp:include page=“hhy.jsp | <%=expression%>”>
<jsp:param name=“parameterName” value=“parameterValue|<%= expression %>” />
</jsp:include >
语法2: <jsp:forward page=“relativeURL | <%=expression%>”>
<jsp:param name=“parameterName” value=“parameterValue|<%= expression %>” />
</jsp:forward >
JSP的内置对象
每个JSP 页面在第一次被访问时,WEB容器都会把请求交给JSP引擎(即一个Java程序)去处理。JSP引擎先将JSP翻译成一个jspServlet(实质上也是一个servlet) ,然后按照servlet的调用方式进行调用。 由于JSP第一次访问时会翻译成servlet,所以第一次访问通常会比较慢,但第二次访问,JSP引擎如果发现JSP没有变化,就不再翻译,而是直接调用,所以程序的执行效率不会受到影响。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b21hq2VN-1722529879087)(https://i-blog.csdnimg.cn/direct/fba29b835fc64c698c0567c7cedcdeb9.webp#pic_center)]
JSP引擎在调用JSP对应的jspServlet时,会传递或创建9个与web开发相关的对象供_jspServlet使用。JSP技术的设计者为便于开发人员在编写JSP页面时获得这些web对象的引用,特意定义了9个相应的变量,开发人员在JSP页面中通过这些变量就可以快速获得这9大对象的引用。
- request – HttpServletRequest
- response – HttpServletResponse
- config – ServletConfig
- application – ServletContext exception(只有在page指令中具有属性isErrorPage="true"时才有效)–
- Exception
- session – HttpSession
- page – 当前类
- out – JspWriter
- pageContext – PageContext
常用:request、session、PageContext
Exception使用:
1.新建exception.jsp
2.在其他jsp再写上<%@ page isErrorPage=“true” errorPage=“exception.jsp” %>,当其报错就会跳转到exception.jsp
注意:必须导包jsp-api.jar,pageContext才可以在获取八大对象后,调用到对应的方法
查看底层
场景:login.jsp
底层代码:login_jsp.java --> login_jsp.class
请求,就会触发该方法
1.初始化九大内置对象
2.执行jsp代码【导包,运行java代码,html和展示信息代码输出到客户端】
注意:HttpJspBase继承于HTTPServlet
根据底层代码编写的伪代码:
//导包
import java.net.URLDecoder;
public class login_jsp extends nds org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent,
org.apache.jasper.runtime.JspSourceImports{
/**
发送请求,就会触发该方法
*/
public void _jspService(HttpServletRequest request, HttpServletResponse response){
//九大内置对象
HttpServletRequest request;//请求对象(请求域对象)
HttpServletResponse response;//响应对象
HttpSession session;//会话域对象
ServletConfig config;//当前JSP(Servlet)的配置文件对象
ServletContext application;//全局域对象(表示整个项目)
JSPWriter out;//当前JSP的输出流对象【将jsp的页面或数据传给客户端】
//当前JSP的上下文关系对象(相当于国家的外交官,可以获取其他8大内置对象)
PageContext pageContext;
Object page = this;//当前JSP页面对象(表示当前页面)
Exception exception;//当前JSP页面的异常对象
//九大内置对象的初始化
pageContext = _jspxFactory.getPageContext
(this, request, response,null, true, 8192, true);
this.request = request;
this.response = response;
session = pageContext.getSeesion();
config = pageContext.getServletConfig();
application = pageContext.getServletContext();
out = pageContext.getOut();
page = this;
exception = pageContext.getException();
//java代码运行
response.setContentType("text/html;charset=UTF-8");
out.writer("<html>\r\n");
out.writer("<head>\r\n");
out.writer(" <title>Title</title>\r\n");
out.writer("</head>\r\n");
out.writer("<body>\r\n");
out.writer("\r\n");
out.writer("<html>\r");
out.writer("<html>\r");
out.writer("<html>\r");
Cookie[] cookies = request.getCookies();
if(cookies != null){
int count = 0;
for (Cookie cookie : cookies) {
String name = cookie.getName();
String value = URLDecoder.decode(cookie.getValue(),"UTF-8");
if("username".equals(name)){
session.setAttribute("username",value);
count++;
}
if("name".equals(name)){
session.setAttribute("name",value);
count++;
}
if("role".equals(name)){
session.setAttribute("role",value);
count++;
}
}
if(count == 3){
response.sendRedirect("index.jsp");
}
}
String msg = (String) request.getAttribute("msg");
//展示信息
out.print((msg!=null)?msg:"");
out.writer("\r\n");
out.writer(" <h1>登录页面</h1>");
.....
}
}
jsp九大对象域
<%
//JSP九大内置对象:
// request;
// response;
// session;
// out;
// application;
// config;
// page;
// pageContext;
// exception;
//JSP九大内置对象里有四大域
// request;
// session;
// application;
// pageContext;
//注意:页面域存储的数据只能在当前页面有效
pageContext.setAttribute("msg","aaa");
//注意:请求域存储的数据只能在本次请求中有效
request.setAttribute("msg","bbb");
//注意:会话域存储的数据只能在对应的客户端中有效
session.setAttribute("msg","ccc");
//注意:全局域存储的数据在整个项目中都有效
application.setAttribute("msg","ddd");
%>