JSP核心技术
1.什么是JSP
JSP和servle技术一样,都是SUN公司定义的一种用于开发动态web资源的技术。
JSP实际上就是Servlet
JSP这门技术的最大的特点在于,写jsp就像在写html,但它相比html而言,html只能为用户提供静态数据,而Jsp技术允许在页面中嵌套java代码,为用户提供动态数据
场景:login.jsp
底层代码:login_jsp.java --> login_jsp.class
理解:jsp底层就是一个类,就是一个servlet,里面有九大内置对象供我们程序员使用,还有一个_jspService方法,就像servlet的service()方法一样,前端只要发送请求,就会触发该方法,初始化九大内置对象,运行jsp代码
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的输出流对象
PageContext pageContext;//当前JSP的上下文关系对象(相当于国家的外交官,可以获取其他8大内置对象)
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();
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>");
.....
}
}
- 浏览器第一次访问
hello.jsp
页面 tomcat
会将hello.jsp
转换为名为hello_jsp.java
的一个Servlet
tomcat
再将转换的servlet
编译成字节码文件hello_jsp.class
tomcat
会执行该字节码文件,向外提供服务
2.JSP最佳实践
不管是JSP还是Servlet,虽然都可以用于开发动态web资源。但由于这2门技术有各自的特点。
servlet只负责请求响应产生数据,并把数据通过转发技术带给jsp,数据的显示交给jsp来做,在长期的软件实践中,人们逐渐把servlet作为web应用中的控制器组件来使用,而把JSP技术作为数据显示模板来使用。
3.JSP语法
JSP模版元素
JSP表达式
JSP脚本片断
JSP注释
JSP指令
JSP标签
JSP内置对象
3.1 JSP模板元素
JSP页面中的HTML内容称之为JSP模版元素。
3.2 JSP脚本表达式
JSP脚本表达式(expression)用于将程序数据输出到客户端(显示到页面上的表达式)
语法:<%= 变量或表达式 %>
<%= (msg!=null)?msg:""%>
JSP脚本表达式中的变量或表达式后面不能有分号
3.3 JSP脚本片段
JSP脚本片断,用于在JSP页面中编写多行Java代码。
语法:<% 多行java代码 %>
注意:
JSP脚本片断中只能出现java代码,不能出现其它模板元素
JSP脚本片断中的Java代码必须严格遵循Java语法,例如,每执行语句后面必须用分号(;)结束。
3.4 JSP声明
JSP页面中编写的所有代码,默认会翻译到servlet的service方法中,而Jsp声明中的java代码被翻译到_jspService方法的外面。语法
<% ! java代码 %>
观察生成的代码效果(就是成员变量)
总结:
<%…%>:内容会直接放到_jspService()方法之中
<%=…%>:内容会放到out.print()中,作为out.print()的参数
<%!…%>:内容会放到_jspService()方法之外,被类直接包含
3.5 JSP注释
JSP注释的格式:<%-- 注释信息 --%>
3.6 JSP指令
JSP指令 是为JSP引擎而设计的,它们并不直接产生任何可见输出,而只是告诉引擎如何处理JSP页面中的其余部分。
定义了三个指令:page指令,include指令,taglib指令
JSP指令的基本语法格式:<%@ 指令 属性名=“值” %>
3.6.1 JSP的page指令
作用:导包,设置响应编码格式
page指令用于定义JSP页面的各种属性,无论page指令出现在JSP页面中的什么地方,它作用的都是整个JSP页面,为了保持程序的可读性和遵循良好的编程习惯,page指令最好是放在整个JSP页面的起始位置。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
3.6.2 include指令
jsp中如果需要写java代码一律写在另外一个jsp里,然后导进去
<%@include file="xxx.jsp"%>
include指令用于引入其它JSP页面,如果使用include指令引入了其它JSP页面,那么JSP引擎将把这两个JSP翻译成一个servlet。所以include指令引入通常也称之为静态引入。
导入代码,有两种写法
<!-- 导入代码:逻辑包含
将page.jsp里的数据通过IO流一点一点读取到当前页面(底层会有page_jsp.java文件)-->
<jsp:include page="page.jsp"></jsp:include> 动态引入
<!-- 导入代码:物理包含
将rememberMe.jsp里的代码直接拷贝到当前JSP中(底层不会有rememberMe_jsp.java文件)
-->
<%@ include file="rememberMe.jsp"%> 静态引入
3.6.3 taglib指令
taglib指令用于在JSP页面中导入标签库,即使用JSTL
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> //核心库
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%> //函数方法库
3.7 JSP的内置对象
每个JSP 页面在第一次被访问时,WEB容器都会把请求交给JSP引擎(即一个Java程序)去处理。JSP引擎先将JSP翻译成一个_jspServlet(实质上也是一个servlet) ,然后按照servlet的调用方式进行调用。
由于JSP第一次访问时会翻译成servlet,所以第一次访问通常会比较慢,但第二次访问,JSP引擎如果发现JSP没有变化,就不再翻译,而是直接调用,所以程序的执行效率不会受到影响。
JSP引擎在调用JSP对应的_jspServlet时,会传递或创建9个与web开发相关的对象供_jspServlet使用。
这9个对象分别是哪些,以及作用也是笔试经常考察的知识点。
//九大内置对象 HttpServletRequest request;//请求对象(请求域对象) HttpServletResponse response;//响应对象 HttpSession session;//会话域对象 ServletConfig config;//当前JSP(Servlet)的配置文件对象 ServletContext application;//全局域对象(表示整个项目) JSPWriter out;//当前JSP的输出流对象 PageContext pageContext;//当前JSP的上下文关系对象(相当于国家的外交官,可以获取其他8大内置对象) Object page = this;//当前JSP页面对象(表示当前页面) Exception exception;//当前JSP页面的异常对象(只有在page指令中具有属性isErrorPage="true"时才有效))
JSP九大内置对象里有四大域
request; 请求域对象
session; 会话域对象
application; 全局域对象
pageContext; 当前JSP的上下文关系对象
3.8 JSP标签
JSP标签也称之为Jsp Action(JSP动作)元素,它用于在Jsp页面中提供业务逻辑功能,避免在JSP页面中直接编写java代码,造成jsp页面难以维护。
< jsp:include >标签
< jsp:forward >标签
< jsp:param >标签
3.8.1 < jsp:include >标签
< jsp:include >标签用于把另外一个资源的输出内容插入进当前JSP页面的输出内容之中,这种在JSP页面执行时的引入方式称之为动态引入。
语法:<jsp:include page=“relativeURL” />
page属性用于指定被引入资源的相对路径
注意:< jsp:include >与include指令的比较:一个是动态导入,一个是静态导入
4.EL
EL:
用于简化 JSP 页面内的 Java 代码
jsp中简化获取四大域的代码(获取四大域里的数据),EL不能操作if,EL只是取值
EL 表达式的主要作用是获取数据,其实就是从域对象中获取数据,然后将数据展示在页面上
而 EL 表达式的语法也比较简单, e x p r e s s i o n 。例如: {expression}。例如: expression。例如:{brands} 就是获取域中存储的 key 为 brands 的数据。
//注意:页面域存储的数据只能在当前页面有效
pageContext.setAttribute("msg","aaa");
//注意:请求域存储的数据只能在本次请求中有效
request.setAttribute("msg","bbb");
//注意:会话域存储的数据只能在对应的客户端中有效
session.setAttribute("msg","ccc");
//注意:全局域存储的数据在整个项目中都有效
application.setAttribute("msg","ddd");
优先级别:页面域 --> 请求域 --> 会话域 --> 全局域
注意:EL表达式查找的范围顺序,以及如何获取请求的参数信息
案例一:
<%-- JSP脚本来存放值,然后采用EL表达式来获取值 --%>
<%
String msg = (String) request.getAttribute("msg"); //直接省略
%>
<%= (msg != null)? msg : "" %>
改:
<%-- 通过EL表达式获取该值 --%>
${msg}
el底层理解:${msg}:四大域,一个一个往上找
通过设置多个区域的数据,来观察EL表达式获取值的顺序
例如: ${msg},el 表达式获取数据,会先从page域对象中获取数据,如果没有再到 requet 域对象中获取数据,如果再没有再到 session 域对象中获取,如果还没有才会到 application 中获取数据。
<%
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;
}
%>
案例二:
EL表达式对于null情况的处理,即不存在对应的key时,是怎么显示的?
不显示
5.JSTL
5.1 什么是JSTL
JSTL:JSP标准标签库;优化JSP页面的逻辑代码(解决分支、循环语句)
需要导包
使用标签取代JSP页面上的Java代码
5.2 使用JSTL
1.在JSP页面头部导入taglib指令
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> //核心库
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%> //函数方法库
2.使用JSTL标签
5.2.1 if 标签
<c:if>
:相当于 if 判断属性:test,用于定义条件表达式
<c:if test="${flag == 1}">
男
</c:if>
<c:if test="${flag == 2}">
女
</c:if>
案例:
<c:if test="${role eq 'student'}">
<a href="StuInitModifyServlet?username=${username}">修改信息</a>
</c:if>
<%if("student".equals(role)){%>
<!-- 在这个servlet通过username找到这个学生,再跳转到信息修改页面 -->
<a href="StuInitModifyServlet?username=<%=username%>">修改信息</a>
<%}%>
改:
<input type="checkbox" name="hobbies" value="football"
<c:if test="${fn:contains(student.hobbies, 'football')}">checked='checked'</c:if>/>足球
5.2.2 forEach 标签
<c:forEach>
:相当于 for 循环。
6.3.1 用法一
类似于 Java 中的增强for循环。涉及到的
<c:forEach>
中的属性如下 items:被遍历的容器
var:遍历产生的临时变量
如下代码,是从域对象中获取名为 brands 数据,该数据是一个集合;遍历遍历,并给该集合中的每一个元素起名为
brand
,是 Brand对象。在循环里面使用 EL表达式获取每一个Brand对象的属性值
<c:forEach items="${brands}" var="brand">
<tr>
<td>${brand.id}</td>
<td>${brand.brandName}</td>
<td>${brand.companyName}</td>
<td>${brand.description}</td>
</tr>
</c:forEach>
循环
<c:forEach items="${page.list}" var="studentDto">
<tr>
<th>${studentDto.student.username}</th>
<th>${studentDto.student.name}</th>
<th>${studentDto.sex}</th>
<th>${studentDto.student.age}</th>
<th>${studentDto.hobbies}</th>
</tr>
</c:forEach>
标签:Java,对象,Day60,jsp,msg,JSP,out,页面
From: https://blog.csdn.net/weixin_69595694/article/details/140813238