JSP全称是Java Server Pages,它和Servlet技术一样,都是SUN公司定义的一种用于开发动态Web页面(资源)的技术。 JSP技术允许在页面中编写Java代码,并且允许开发人员在页面中获取request、response等Web开发常用对象,实现与浏览器的交互,所以JSP也是一种动态Web资源的开发技术。
每个JSP页面在第一次被访问时,Web容器都会把请求交给JSP引擎(即一个Java程序)去处理。JSP引擎先将JSP翻译成一个_jspServlet(实质上也是一个Servlet),然后按照Servlet的调用方式进行调用。(翻译后的Servlet保存在Tomcat的work目录,如:H:\MySoftware\Tomcat\apache-tomcat-9.0.0.M4\work\Catalina\localhost\JavaWeb\org\apache\jsp) 由于JSP第一次访问时会翻译成Servlet,所以第一次访问通常会比较慢,但第二次访问,JSP引擎如果发现JSP没有变化,就不再翻译,而是直接调用,所有程序的执行效率不会受到影响。
不管是JSP还是Servlet,虽然都可以用于开发动态Web资源。但由于这两门技术各自的特点,在长期的软件实践中,人们逐渐把Servlet作为Web应用中的控制器组件来使用,而把JSP技术作为数据显示模板来使用。 根据这两门技术的特点,让它们各自负责各的,Servlet只负责响应请求产生数据,并把数据通过转发技术带给JSP,由JSP来进行数据的显示。
3. 如果设置了某个页面的Page指令的errorPage属性,那么在web.xml文件中设置的错误处理将不对该页面起作用。 4. 服务器抛404时显示的页面设置:(在web.xml中设置)
<error-page> <error-code>404</error-code> <location>/errors/404.jsp</location> </error-page>include指令,通过该指令可以在一个JSP页面中包含另一个JSP页面。不过该指令是静态包含,也就是说被包含文件中所有内容会被原样包含到该JSP页面中,即使被包含文件中有JSP代码,在包含时也不会被编译执行。 include指令为静态包含(编译时包含),它包含的所有JSP页面都只会同原来的JSP页面编译成一个servlet。语法:
<%@ include file="relativeURL"%>其中的file属性用于指定被引入文件的路径。路径以“/”开头,表示代表当前Web应用。 被引入的文件可以使用任意的扩展名,即使其扩展名是html,JSP引擎也会按照处理JSP页面的方式处理它里面的内容,为了见名知意,JSP规范建议使用.jspf(JSP fragments)作为静态引入文件的扩展名。 被引入的JSP页面的指令不能冲突(除了pageEncoding和导包除外)。 示例: index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ include file="/public/header.jsp"%> <h4>页面主体内容...</h4> <% // 注释 out.write("测试中文输出"); %> <%@ include file="/public/footer.jsp"%>被包含页面:header.jsp、footer.jsp(这里以.jspf后缀更好) header.jsp
<%@ page import="java.util.Date" contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Header</title> </head> <body> <p><%=new Date().toLocaleString()%></p>footer.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <p>这是页脚</p> </body> </html>动态包含(运行时包含):包含过程中,所涉及到的所有JSP页面都将对应单独编译成一个servlet。 示例: index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <% request.getRequestDispatcher("/public/header.jsp").include(request, response); %> <h4>页面主体内容...</h4> <% // 注释 response.getWriter().write("测试中文输出"); %> <% request.getRequestDispatcher("/public/footer.jsp").include(request, response); %>此外,静态包含比动态包含的效率要好。
taglib指令,用于在JSP页面中导入标签库。
JSP引擎在调用JSP对应的_jspServlet时,会传递或创建9个与Web开发相关的对象供_jspServlet使用。JSP技术的设计者为便于开发人员在编写JSP页面时获得这些Web对象的引用,特意定义了9个相应变量。 JSP中的内置对象 request、response、session、application、config、page、exception、out、pageContext。
pageContext对象,代表JSP页面的运行环境,封装了对其他8大隐式对象的引用。
getException方法 返回exception隐式对象 getPage方法 返回page隐式对象 getRequest方法 返回request隐式对象 getResponse方法 返回response隐式对象 getServletConfig方法 返回config隐式对象 getServletContext方法 返回application隐式对象 getSession方法 返回session隐式对象 getOut方法 返回out隐式对象pageContext对象也是一个域对象(拥有getAttribute和setAttribute方法),作用于页面范围,即page域,不同页面不能共享pageContext中存储的数据。 pageContext对象中包含findAttribute方法,用于查找各个域中的属性。findAttribute方法的查找顺序为page域(PageContext对象)、request域、session域、application域(ServletContext对象)。(由小到大)如:
<% pageContext.findAttribute("data"); %>相当于EL表达式中的
${data}pageContext还拥有forward和include方法用来分别简化和替代RequestDispatcher.forward方法和include方法。方法接收的参数为资源的路径,如果以“/”开头,“/”代表当前Web应用。
JSP标签也称之为Jsp Action(JSP动作)元素,它用于在JSP页面中提供业务逻辑功能,避免在JSP页面中直接编写Java代码,造成JSP页面难以维护。 JSP常用标签: - <jsp:include>标签
<jsp:include page="/1.jsp"></jsp:include>相当于(属于动态包含)
pageContext.include("/1.jsp"); <jsp:forward>标签 <jsp:forward page="/1.jsp"></jsp:forward> <jsp:param>标签 示例: param.jsp <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>JSP常用标签</title> </head> <body> <jsp:forward page="/ServletDemo1"> <jsp:param name="username" value="DreamBoy"/> <jsp:param name="password" value="123456"/> </jsp:forward> </body> </html>ServletDemo1.java
import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * Created by DreamBoy on 2017/5/9. */ @WebServlet(name = "ServletDemo1", urlPatterns = {"/ServletDemo1"}) public class ServletDemo1 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"); System.out.println(username); System.out.println(password); } }在web.xml中配置jsp页面映射的URL路径(别忘了访问JSP实际上就是访问JSP编译后的Servlet):
<servlet> <servlet-name>ServletDemo1</servlet-name> <jsp-file>/index.jsp</jsp-file> </servlet> <servlet-mapping> <servlet-name>ServletDemo1</servlet-name> <url-pattern>/index.html</url-pattern> </serlvet-mapping>JSP声明可用于定义JSP页面转换成Servlet程序的静态代码块、成员变量和方法。 多个静态代码块、变量和函数可以定义在一个JSP声明中,也可以分别单独定义在多个JSP声明中。 我们可以理解为在Servlet中定义了一些属性。 4. JSP隐式对象的作用范围仅限于Servlet的_jspService方法,所以在JSP声明中不能使用这些隐式对象(JSP九大内置对象)。
JavaBean是一个遵循特定写法的Java类,它通常具有如下特点: - 该Java类必须具有一个无参的构造函数 - 属性必须私有化 - 私有化的属性提供public访问权限的get、set方法暴露给其他程序 JavaBean的属性可以是任意类型,并且一个JavaBean可以有多个属性。每个属性通常都需要具有相应的getter、setter方法。其中getter方法称为属性访问器;setter方法称为属性修改器。 一个JavaBean的某个属性也可以只有set方法或get方法,这样的属性通常也称之为只写、只读属性。 示例: Person.java
package com.wm103.domain; import java.util.Date; /** * Created by DreamBoy on 2017/5/9. */ public class Person { private String name; private int age; public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } private Date birthday; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }其中scope属性的取值只能为page、request、session和application等四个值中的一个,其默认值是page。
<jsp:setProperty>标签:用于在JSP页面中设置一个JavaBean组件的属性。<jsp:getProperty>标签:用于在JSP页面中获取一个JavaBean组件的属性。 读取JavaBean对象的属性,也就是调用JavaBean对象的getter方法,然后将读取的属性值转换成字符串后插入进输出的相应正文中。 如果一个JavaBean实例对象的某个属性的值为null,那么,使用<jsp:getProperty>标签输出该属性的结果将是一个内容为“null”的字符串。 示例: <%-- Created by IntelliJ IDEA. User: DreamBoy Date: 2017/5/9 Time: 10:46 To change this template use File | Settings | File Templates. --%> <%@ page import="java.util.Date" contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>jsp:setProperty标签的使用</title> </head> <body> <p> 请求 <pre> http://localhost:8080/day09/2.jsp?name=xiaoxiao&age=18 </pre> </p> <jsp:useBean id="person" class="com.wm103.domain.Person"/> <!-- 手工为bean属性赋值 --> <jsp:setProperty name="person" property="name" value="DreamBoy"/> <h4>手工为bean属性赋值</h4> <p><%=person.getName()%></p> <!-- 用请求参数给bean属性赋值 --> <jsp:setProperty name="person" property="name" param="name"/> <jsp:setProperty name="person" property="age" param="age"/> <!-- 支持8种基本数据类型的转换(把客户机提交的字符串,转成相应的8种基本数据类型,赋值到bean的属性上 --> <jsp:setProperty name="person" property="birthday" value="<%=new Date()%>"/> <h4>用请求参数给bean属性赋值</h4> <p><%=person.getName()%></p> <p><%=person.getAge()%></p> <p><%=person.getBirthday()%></p> <!-- 用所有的请求参数为bean赋值 --> <jsp:setProperty name="person" property="*"/> <h4>用所有的请求参数为bean赋值</h4> <p><%=person.getName()%></p> <p><%=person.getAge()%></p> <!-- 获取bean的属性 --> <jsp:getProperty name="person" property="name"/> <jsp:getProperty name="person" property="age"/> </body> </html>实现计算器案例: JavaBean CalculatorBean.java
package com.wm103.domain; /** * Created by DreamBoy on 2017/5/9. */ import java.math.BigDecimal; /** * 封装计算器数据的Bean */ public class CalculatorBean { private String firstNum; private char operator; private String secondNum; private String result; public String getFirstNum() { return firstNum; } public void setFirstNum(String firstNum) { this.firstNum = firstNum; } public char getOperator() { return operator; } public void setOperator(char operator) { this.operator = operator; } public String getSecondNum() { return secondNum; } public void setSecondNum(String secondNum) { this.secondNum = secondNum; } public String getResult() { return result; } public void setResult(String result) { this.result = result; } public void calculate() { if(this.firstNum == null || this.secondNum == null) { return; } BigDecimal first = new BigDecimal(this.firstNum); BigDecimal second = new BigDecimal(this.secondNum); switch (this.operator) { case '+': this.result = first.add(second).toString(); break; case '-': this.result = first.subtract(second).toString(); break; case '*': this.result = first.multiply(second).toString(); break; case '/': if(second.doubleValue() == 0) { throw new RuntimeException("被除数不能为0!"); } this.result = first.divide(second, 2, BigDecimal.ROUND_HALF_UP).toString(); break; default: throw new RuntimeException("该运算符不存在!"); } } }calculator.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! --> <title>计算器</title> <!-- Bootstrap --> <link href="./public/assets/bootstrap-3.3.7/css/bootstrap.min.css" rel="stylesheet"> <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries --> <!-- WARNING: Respond.js doesn't work if you view the page via file:// --> <!--[if lt IE 9]> <script src="https://cdn.bootcss.com/html5shiv/3.7.3/html5shiv.min.js"></script> <script src="https://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script> <![endif]--> </head> <body> <div class="container"> <div style="padding: 50px 20px;" data-example-id="table-within-panel"> <div class="panel panel-primary"> <!-- Default panel contents --> <div class="panel-heading"> <h3>简易计算器</h3> </div> <jsp:useBean id="calculatorBean" class="com.wm103.domain.CalculatorBean"/> <jsp:setProperty name="calculatorBean" property="*"/> <div class="panel-body"> <% try { calculatorBean.calculate(); } catch (Exception e) { out.write("<h4>" + e.getMessage() + "</h4>"); } %> <% if (calculatorBean.getResult() != null) { %> <h3> 计算结果是: <jsp:getProperty name="calculatorBean" property="firstNum"/> <jsp:getProperty name="calculatorBean" property="operator"/> <jsp:getProperty name="calculatorBean" property="secondNum"/> = <jsp:getProperty name="calculatorBean" property="result"/> </h3> <% } %> </div> <form action="calculator.jsp" method="post"> <!-- Table --> <table class="table table-striped table-hover"> <tbody> <tr> <th scope="row">第一个参数</th> <td><input type="text" class="form-control" name="firstNum" placeholder=""></td> </tr> <tr> <th scope="row">运算符</th> <td> <select name="operator" class="form-control"> <option value="+">+</option> <option value="-">-</option> <option value="*">*</option> <option value="/">/</option> </select> </td> </tr> <tr> <th scope="row">第二个参数</th> <td> <input type="text" class="form-control" name="secondNum" placeholder=""> </td> </tr> <tr> <td colspan="2"> <button type="submit" class="btn btn-info btn-block">提交</button> </td> </tr> </tbody> </table> </form> </div> </div> </div> <!-- jQuery (necessary for Bootstrap's JavaScript plugins) --> <script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script> <!-- Include all compiled plugins (below), or include individual files as needed --> <script src="./public/assets/bootstrap-3.3.7/js/bootstrap.min.js"></script> </body> </html>运行效果: