JSP(Java Server Pages “Java服务器端页面”)
JSP(Java Server Pages “Java服务器端页面”)
JSP简介
JSP全称是Java Server Pages,是一种动态网页技术,JSP其实就是在html中插入了java代码和JSP标签之后形成的文件,文件名以.jsp结尾。其实JSP就是一个servlet。
在servlet中编写html比较痛苦,而写JSP就像在写html,但它相比html而言,html只能为用户提供静态数据即静态页面,而Jsp技术允许在页面中嵌套java代码,为用户提供动态数据,从而形成动态页面。
需要注意的是最好只在JSP中编写动态输出的java代码。
JSP原理
假设存在一个jsp页面叫a.jsp,则:
- 当浏览器第一次访问a.jsp的时候,会被服务器翻译成a_jsp.java ,
- jdk将a_jsp.java编译成a_jsp.class文件 , 执行class中的代码,给浏览器进行响应
- 当浏览器再次访问a.jsp的时候,如果class已经存在就不在翻译而是直接执行
JSP的运行机制:
将JSP文件转换为.java文件并将其编译为.class文件的过程都是由tomcat完成的,在tomcat内部有一个翻译引擎,当JSP页面第一次被访问时由翻译引擎转换为.java文件并编译出.class文件。之后再运行该class文件。
在JSP中的html代码都会翻译到servlet中的out.write()中。
运行过程:
- 当Web容器接收到用户的第一个jsp页面请求时,jsp引擎将这个jsp页面转换为java源代码(Java Servlet源程序),若在转换过程中发现jsp文件中有任何语法错误,转换过程将中断,并向服务器和客户端返回错误信息。
- 转换成功后,jsp引擎用javac将java源代码编译成相应的字节码文件*.class(一个Servlet)。然后由Servlet容器处理。
- Servlet容器加载*.class文件,创建该Servlet实例,并执行Servlet的jspInit()方法(该方法在Servlet整个生命周期中只执行一次。它的作用是可以在其里面进行一些初始化设置,诸如建立与数据库的连接、建立网络连接、获取配置文件的参数等)。
- 执行_jspService()方法来处理客户端的请求。对于每一个请求,JSP引擎都会创建一个新的线程来处理。
- 如果.jsp文件被修改了,则服务器会根据设置决定是否对该文件重新编译,如果需要重新编译则将编译后的结果取代内存中的Servlet,并继续上述过程。
- 虽然JSP的效率很高,但在第一次调用是往往由于需要转换和编译过程而产生一些轻微的延迟。此外,可能由于系统资源不足等原因,JSP容器会以某种不确定的方式将Servlet从内存中移去。在这种情况下,将会调用jspServlet()方法进行清除工作,接着Servlet实例便被加入到“垃圾收集”收集。
- 当请求处理完成后,响应对象由JSP容器接受,并将HTML格式的响应信息发送回客户端。
当你查看jsp文件被服务器翻译成的 _jsp.java文件时,可以发现 _jsp.java这个类,它继承了HttpJspBase类,而HttpJspBase类又继承了HttpServlet类,故而jsp本质就是一个Servlet
JSP类中有三个重要的方法
//初始化jsp
public void _jspInit() {
}
//销毁jsp
public void _jspDestroy() {
}
//jspService
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
throws java.io.IOException, javax.servlet.ServletException {
if (!javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {
final java.lang.String _jspx_method = request.getMethod();
if ("OPTIONS".equals(_jspx_method)) {
response.setHeader("Allow","GET, HEAD, POST, OPTIONS");
return;
}
if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method)) {
response.setHeader("Allow","GET, HEAD, POST, OPTIONS");
response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSP 只允许 GET、POST 或 HEAD。Jasper 还允许 OPTIONS");
return;
}
}
JSP类中内置的一些对象
final javax.servlet.jsp.PageContext pageContext;//页面上下文
javax.servlet.http.HttpSession session = null;//session
final javax.servlet.ServletContext application;//applicationContext
final javax.servlet.ServletConfig config;//config
javax.servlet.jsp.JspWriter out = null;//out 输出
final java.lang.Object page = this; //page 当前页面
javax.servlet.jsp.JspWriter _jspx_out = null;
javax.servlet.jsp.PageContext _jspx_page_context = null;
//由于继承了HttpServlet,肯定有请求和响应对象
HttpServletRequest
HttpServletResponse
以上的对象可以在jsp页面中直接使用
在JSP页面中:
只要是java代码就会原封不动输出
如果是html文本,就会转化成 out.write()类型,输出到前端
例如:
out.write("<html>\n");
JSP基础语法
任何语言都有自己的语法,JSP作为java技术的一种应用,自然支持java所有语法,同时其也拥有一些扩充的语法
1.<%= %> <%--jsp表达式--%>
2.<% %> <%--jsp脚本片段--%>
3.<%! %> <%--jsp声明--%>
4.<%--jsp的注释--%>
关于JSP的注释和HTML的注释的区别:JSP的注释不会在客户端显示,而HTML的注释是可以显示在客户端的。(即用户通过浏览器查看网页源代码时,看不到JSP的注释,却可以看到HTML的注释)
JSP表达式
<%--jsp表达式
作用:将程序的结果输出到客户端
<%= 变量或表达式%>
--%>
<%=new Date() %>
JSP脚本片段
<%--jsp脚本片段--%>
<%
int sum = 0;
for (int i = 0; i <= 100; i++) {
sum+=i;
}
out.print("<h1>sum="+sum+"<h1>");
%>
<%--在代码中嵌入html元素--%>
<%
for (int i = 0; i < 5; i++) {
%>
<h1> Hello,World <%= i%></h1>
<%
}
%>
JSP声明
<%--jsp声明,JSP声明用于定义JSP中的变量、方法以及静态方法,实际上相当于java类中定义一个全局变量或方法--%>
<%!
static {
System.out.println("Loading Servlet");
}
private int globalVar = 0;
public void yue(){
System.out.println("进入方法yue");
}
%>
jsp声明中的代码块在jsp被编译成java类时,直接被翻译为该类的全局变量,而其他的,比如jsp表达式,jsp脚本片段则被翻译在_jspService( )方法内
JSP指令
page指令
定义JSP文件的全局属性,描述了与页面相关的信息,作用域为所在的JSP页面和其包含的文件,同一个JSP页面可以有多个page属性:<%@page %>
,其属性除了import之外其他的只能使用一次。
<%@page args... %>
inclue指令
用于在当前JSP页面中加载需要插入的文件代码,即为页面插入一个静态文件,如JSP页面、HTML页面、文本文件或一段Java程序,这些加载的代码和原有的JSP代码合并成一个新的JSP文件;常见的有网站所有页面的共同页面
格式为:
<%@include file=”文件名”%>
Include指令只有一个file属性
例:让网页头尾显示公有页面
<%--jsp指令
%@include file= 将多个页面合起来变成一个页面
--%>
<%@include file="common/header.jsp"%>
<h1>
网页主体
</h1>
<%@include file="common/footer.jsp"%>
<hr>
也可使用JSP标签的方式实现同样的效果:
<%--jsp标签
jsp:include 拼接页面,本质是三个页面,只是从jsp翻译成的java类中的静态资源调用进行拼接
--%>
<jsp:include page="common/header.jsp"/>
<h1>
网页主体2
</h1>
<jsp:include page="common/footer.jsp"/>
<%--标签耦合性低,用的较多--%>
Include指令由于是直接将多个页面合二为一,可能会出现变量名重复的现象,比如:
在主体页面中定义一个i :
<%@include file="common/header.jsp"%>
<h1>网页主体</h1>
<% int i = 10; %>
<%@include file="common/footer.jsp"%>
<hr>
在header.jsp中也定义一个i :
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<h1>我是头部</h1>
<% int i = 2; %>
此时就会报错,提示 变量 i 以在作用域中存在,以及 i 属性值冗余
taglib指令
用于指定页面中使用的标签库及自定义标签的前缀
<%@ taglib prefix="c" uri=""%>
其中,uri用于指定标记库存放分位置,prefix用于指定标记库中所有动作元素名中使用的前缀。
九大内置对象
按照内置对象的功能来划分,可以分为以下四类:
输出输入对象
request对象(存数据)
response对象
out对象(输出)
通信控制对象
pageContext对象(存数据)
session对象(存数据)
application对象(存数据)
Servlet对象
page对象(几乎不用)
config对象
错误处理对象
exception对象(异常,跟java一样)
在内置对象中存东西
<body>
<%--内置对象--%>
<%
pageContext.setAttribute("name1","阿飞1");//保存的数据只在一个页面中有效
request.setAttribute("name2","阿飞2");//保存的数据只在一次请求中有效,请求转发时也会携带这个数据
session.setAttribute("name3","阿飞3");//保存的数据在一次会话中都有效,数据存在周期为从打开浏览器到关闭浏览器
application.setAttribute("name4","阿飞4");//保存的数据在服务器中有效,数据存在周期为从打开服务器到关闭服务器
%>
<%--取出我们保存的值--%>
<%--不能在jsp脚本片段中使用jsp的注释方式,因为这些代码会原封不动的生成到_jsp.java中,所以要使用java的注释方式,以保证java语法的正确性--%>
<%
//从pageContext取出保存的值,通过寻找的方法,从底层到高层(作用域)来一层层的寻找 page——>request——>session——>application
//JVM存在一个“双亲委派机制”
String name1 = (String) pageContext.findAttribute("name1");
String name2 = (String) pageContext.findAttribute("name2");
String name3 = (String) pageContext.findAttribute("name3");
String name4 = (String) pageContext.findAttribute("name4");
String name5 = (String) pageContext.findAttribute("name5");//name5不存在
%>
<%--使用EL表达式输出 ${}--%>
<h1>取出的值为:</h1>
<h3>${name1}</h3>
<h3>${name2}</h3>
<h3>${name3}</h3>
<h3>${name4}</h3>
</body>
JSP标签,JSTL标签,EL表达式
需要的依赖:
<!--jstl表达式依赖-->
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
<version>1.2</version>
</dependency>
<!--standard标签库依赖-->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
EL表达式(Expression Language):${}
- 获取数据
- 执行运算
- 获取web开发的常用对象
JSP标签:
<body>
<h1>1</h1>
<%--
相当于http://localhost:8080/javawebjsp/jsptag.jsp?name=afei&age=1000
--%>
<jsp:forward page="/jsptag02.jsp">
<jsp:param name="name" value="afei"/>
<jsp:param name="age" value="1000"/>
</jsp:forward>
</body>
<body>
<h1>2</h1>
<%--取出参数--%>
名字:<%=request.getParameter("name")%>
年龄:<%=request.getParameter("age")%>
</body>
JSTL标签:
JSTL标签库的使用就是为了弥补HTML标签的不足;它自定义了许多的标签可以供我们使用,标签的功能和java代码一样。
需在jsp文件中引入JSTL对应的标签库(taglib),才可以使用对应的JSTL标签
如果引入标签后依然报错(JSTL解析错误),则还需要将JSTL的jar包复制到tomcat的lib目录下
-
核心标签
核心标签的标签库:
<%@ taglib prefix="c" url="http://java.sun.com/jsp/jstl/core" %>
该标签库是c开头的额,代表core,核心的意思
c:if
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title> </title> </head> <body> <h4>if测试</h4> <hr> <form action="coreif.jsp" method="get"> <%--EL表达式获取表单中的数据 格式为:${param.参数名} --%> <input type="text" name="username" value="${param.username}"> <input type="submit" value="登陆"> </form> <%--判断如果提交的用户名是管理员,则登陆成功--%> <c:if test="${param.username=='admin'}" var="isAdmin"> <c:out value="管理员登陆"/> </c:if> <c:out value="${isAdmin}"/> </body> </html>
c:set and c:when
<body> <%--定义一个变量score,值为85--%> <c:set var="score" value="85"/> <%--判断--%> <c:choose> <c:when test="${score>=90}"> 你的成绩为优 </c:when> <c:when test="${score>=75&&score<90}"> 你的成绩为良 </c:when> <c:when test="${score>=60&&score<75}"> 你的成绩为及格 </c:when> <c:when test="${score<60}"> 你的成绩为不及格 </c:when> </c:choose> </body>
c:forEach
<body> <% ArrayList<String> people = new ArrayList<>(); people.add(0,"张三"); people.add(1,"李四"); people.add(2,"王五"); people.add(3,"赵六"); people.add(4,"孙七"); people.add(5,"姬八"); request.setAttribute("list",people); %> <%-- var:每一次遍历出来的变量 items:要遍历的对象 --%> <c:forEach var="people" items="${list}"> <c:out value="${people}"/><br> </c:forEach> <hr> <%-- 可以设置begin,end,step begin:设置开始的位置 end:设置结束的位置 step:遍历的间隔,相当于i+? --%> <c:forEach var="people" items="${list}" begin="1" end="4" step="2"><%--输出李四和赵六,对应的下标是1和3--%> <c:out value="${people}"/><br> </c:forEach> </body>
-
格式化标签
-
SQL标签
-
XML标签
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战