1 什么是JSP
1)为什么说,Servlet是一个动态Web开发技术呢?
Servlet是基于服务端的一种动态交互技术,
HttpServletRequest表示客户端到服务端的对象
HttpServletResponse表示服务端到客户端的对象
2)JSP是SUN公司开发的一个基于服务端的一种动态WEB开发技术
3)JSP的代码结构/内容=HTML+JSP所有元素内容
4)在IDE工具中,开发JSP,pageEncoding有二层含义:
a)指明当前JSP中的中文采用什么方式编码(如果在IDE工具外)
b)指明当前JSP页面保存时采用什么方式编码
5)项目中,JSP最佳实践模式:
Servlet:适合控制器
Jsp:适合显示
JavaBean:模型
不管是JSP还是Servlet,虽然都可以用于开发动态web资源。但由于这2门技术各自的特点,在长期的软件实践中,人们逐渐把servlet作为web应用中的控制器组件来使用,而把JSP技术作为数据显示模板来使用。
其原因为,程序的数据通常要美化后再输出:
•让jsp既用java代码产生动态数据,又做美化会导致页面难以维护。
•让servlet既产生数据,又在里面嵌套html代码美化数据,同样也会导致程序可读性差,难以维护。
•因此最好的办法就是根据这两门技术的特点,让它们各自负责各的,servlet只负责响应请求产生数据,并把数据通过转发技术带给jsp,数据的显示jsp来做。
package cn.itcast.web.servlet; import java.io.IOException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import cn.itcast.web.domain.TableBean; public class TableServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
//调用模型对象
TableBean tableBean = new TableBean();
List<String> stringList = tableBean.getList();
//绑定到域对象
request.setAttribute("stringList",stringList);
//转发到jsp页面
request.getRequestDispatcher("/WEB-INF/table.jsp").forward(request,response);
}
}
package cn.itcast.web.servlet; import java.io.IOException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import cn.itcast.web.domain.TableBean; public class TableServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
//调用模型对象
TableBean tableBean = new TableBean();
List<String> stringList = tableBean.getList();
//绑定到域对象
request.setAttribute("stringList",stringList);
//转发到jsp页面
request.getRequestDispatcher("/WEB-INF/table.jsp").forward(request,response);
}
}
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<body>
<%
//取得域对象中的内容
List<String> stringList = (List<String>)request.getAttribute("stringList");
%>
<table border="1" align="center">
<caption>学员信息</caption>
<tr>
<th>姓名</th>
<td>操作</td>
</tr>
<%
for(String username : stringList){
%>
<tr>
<th><%=username%></th>
<td><a href="#">查看</a></td>
</tr>
<%
}
%>
</table>
</body>
</html>
*2 JSP工作原理
1)Web容器根据客户端访问的资源类别(Web容器会根据资源的第一行代码确定),如果你访问的是JSP资源,就交由JSP引擎处理
如果你访问的是Servlet资源,就交由Servlet引擎处理
2)如果是JSP资源,JSP引擎会将其翻译成Servlet资源,传入相关的对象,如果是静态资源,以out.write()形式输出,如果是动态 资源,以out.print()形式输出
3)此时JSP引擎在翻译正确后,将其输出给Servlet引擎,当作Servlet处理。
4)如果再次访问同一个date.jsp文件,翻译工作依然进行,Servlet引擎工作可以减化,所以这是为会么第N次较第1次快的原因
3 JSP语法
1)JSP模版元素
模版元素就是HTML中的静态内容,即<body>,<table>,<form>标签。。。
2)JSP表达式
a)语法:<%="字符串变量或表达式"%>
b)结束无分号
c)默认输出到浏览器
d)JSP引擎在翻译脚本表达式时,会将程序数据转成字符串,然后在相应位置用out.write(…) 将数据输给客户端。
3)JSP脚本片断
a)语法:<% ...java代码; %>
b)脚本片断中的注释符号与java代码一致
注意:JSP修改后,无需重新部署,直接刷新,Web容器会自动比较新旧二个版本的JSP
c)多个JSP脚本片断中定义的变量,本质是_jspService()方法中的局部变量,可以相互访问
在一个JSP页面中可以有多个脚本片断,在两个或多个脚本片断之间可以嵌入文本、HTML标记和其他JSP元素。
举例:
多个脚本片断中的代码可以相互访问,犹如将所有的代码放在一对<%%>之中的情况。如:out.println(x);
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<body>
<%="这是JSP的脚本输出表达式"%>
<hr/>
<%=new Random().nextInt(1000)%>
<hr/>
<%
//以下代码是JSP的脚本
Random r = new Random();
double num = r.nextDouble();
%>
随机数是:<%=num%><br/>
</body>
</html>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<body>
<%
for(int i=1;i<=6;i++){
%>
<h<%=i%>>JavaWebGood!</h<%=i%>>
<%
}
%>
<hr/>
<%
String name = "喜喜";
%>
用户名:<font color=""><%=name%>
</body>
</html>
4)JSP声明
a)语法:<%! ...java代码 %>
b)JSP声明的变量或方法,会成为Servlet的实例变量或实例方法或普通方法
c)JSP脚本片断中不能定义局部方法,方法只能定义在JSP声明中
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ page import="java.io.*"%>
<%@ page import="java.net.*"%>
<%@ page buffer="8kb" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<body>
<!--
HTML注释
-->
<%--
JSP
注释(写JSP优先推荐使用)引擎不会加载
--%>
<%!
String name = "呵呵";
%>
<%!
public String getName(){
return name;
}
%>
<%
String name = "局部变量";
%> 该实例变量为:<%=getName()%>
</body>
</html>
5)JSP注释
1)语法:<%-- 注释的内容 --%>
2)对于HTML注释来说,JSP引擎会将其翻译成servlet内容,
对于JSP注释来说,JSP引擎不会将其翻译成servlet内容
3)注释不能嵌套使用
6)JSP指令
1)指令是程序员控制JSP引擎做什么的依据
2)有三类:
a)page
b)include
c)tablib
JSP指令的基本语法格式:
<%@ 指令属性名="值" %>
举例:<%@ page contentType="text/html;charset=UTF-8"%>
如果一个指令有多个属性,这多个属性可以写在一个指令中,也可以分开写。
例如:
<%@ page contentType="text/html;charset=UTF-8"%>
<%@ page import="java.util.Date"%>
也可以写作:
<%@ page contentType="text/html;charset=UTF-8" import="java.util.Date"%>
*3)page指令的属性有
language="指明JSP支持的语言,默认为java语言"
*import="当前JSP页面中,需要导入的包,其中import可以写多次"
session="true表示需要服务器创建session/false不需要服务器创建session",默认true
buffer="none|8kb|sizekb"JSP输出使用的缓存大小,默认8kb
autoFlush="true表示当缓存满时,web容器是自动刷新到客户端/false需要手工刷新到客户端",默认true
isThreadSafe="true表示web服务器确保线程安全/false不确保线程安全",默认true
info="text"表示jsp的相关描述信息,可以通过getServletInfo()取得该jsp的信息
三种错误处理方式,try-catch->jsp页面处理->webxml配置处理
*errorPage="当前jsp页面出错后,转发到的目标页面"
*isErrorPage="true"(当某个jsp页面有该属性时,web容器会自动创建exception对象
上述异常处理属于局部异常处理
在web.xml文件:
<error-page>
<error-code>500</error-code>
<location>/s_500.jsp</location>
</error-page>
<error-page>
<exception-type>java.lang.NumberFormatException</exception-type>
<location>/s1_500.jsp</location>
</error-page>
上述异常处理属于全部异常处理.如果全局中有code又有type,此时二者同时显示.当全局和局部异常同时出现时,局部异常优先
<%@ page language="java" pageEncoding="UTF-8"%>
<%@ page errorPage="error.jsp" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<body>
<%
Integer.parseInt("abc");
%>
</body>
</html>
<%@ page language="java" pageEncoding="UTF-8"%>
<%@ page isErrorPage="true" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<body>
出错了:原因如下<br/>
<%=exception.getMessage()%>
</body>
</html>
*pageEncoding="UTF-8"
前提在IDE工具中
a)JSP页面的中文采用UTF-8方式编码
b)JSP保存时采用UTF-8方式编码
c)指示浏览器以UTF-8方式查看
contentType="text/html;charset=UTF-8"
*isELIgnored="false表法JSP引擎不忽略EL表达式语言/true表法JSP引擎忽略EL表达式语言"
9)如何查找JSP页面中的错误
4 JSP出错后处理方法
5 M(Javabean)V(Jsp)C(Servlet)模式
6 @include指令[静态包含]
1)include指令包含多个JSP页面,最后JSP引擎只翻译总JSP页面,即index.jsp页面
2)include指令包含多个JSP页面,那么被包含的JSP页面原封不动的进入总JSP页面,即index.jsp页面,造成HTML结构非常混乱
3)include指令包含多个JSP页面,多个JSP最终会翻译成一个Servlet,即index_jsp.java页面
<%@ page language="java" pageEncoding="UTF-8"%>
<%@ page errorPage="error.jsp" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<body>
<%-- 包含head.jsp和foot.jsp --%>
<%@ include file="common/head.jsp"%>
<hr/>
include指令的用法
<hr/>
<%@ include file="common/foot.jsp"%>
<%--
Integer.parseInt("abc");
--%>
</body>
</html>
*7 jsp九大隐式/内置对象
1)request
<%@ page language="java" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<body>
<%
//进行以请求体为主的中文编码[输入]
request.setCharacterEncoding("UTF-8"); //收集客户端提交的数据
String username = request.getParameter("username"); //使用response对象输出到浏览器
response.getWriter().write("用户名:" + username);
%>
</body>
</html>
<%@ page language="java" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<body>
<%
//进行以请求体为主的中文编码[输入]
request.setCharacterEncoding("UTF-8"); //收集客户端提交的数据
String username = request.getParameter("username"); //使用response对象输出到浏览器
response.getWriter().write("用户名:" + username);
%>
</body>
</html>
2)response
3)session
访问jsp页面时,默认web服务器创建session
访问servlet时,必须通过request.getSession()才能创建session
在转发和重定向情况下,session域不会销毁
<%@ page language="java" pageEncoding="UTF-8"%>
<%@ page import="java.util.*" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<body>
<%
session.setAttribute("name","杰克");
//转发到result.jsp页面
//request
// .getRequestDispatcher("/result.jsp")
// .forward(request,response);
//重定向到result.jsp页面
response.sendRedirect("/day09/result.jsp");
%>
</body>
</html>
<%@ page language="java" pageEncoding="UTF-8"%>
<%@ page import="java.util.*" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<body>
<%!
//比较后并返回结果
public String guess(int numClient,int numServer){
if(numClient < numServer){
return "猜小了";
}else if(numClient > numServer){
return "猜大了";
}else{
return "中了";
}
}
%>
<%
String name = (String)session.getAttribute("name");
response.getWriter().write("用户名:" + name); //取得客户端猜的数字
//int numClient = Integer.parseInt(request.getParameter("numClient"));
//随机产生1-10整数,作为服务器猜的
//Random r = new Random();
//int numServer = r.nextInt(10)+1;
//比较
//String msg = guess(numClient,numServer);
//response.getWriter().write("客户数字是:" + numClient + "<br/>");
//response.getWriter().write("系统数字是:" + numServer + "<br/>");
//response.getWriter().write("<font color='red'>"+msg+"</font>");
%>
</body>
</html>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<body>
欢迎<%=session.getAttribute("username")%>光临<br/>
<a href="/day09/ExitServlet">安全退出</a>
</body>
</html>
package cn.itcast.web.servlet; import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; public class LoginServlet extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
String username = request.getParameter("username");
if(username!=null && username.trim().length()>0){
//取得ServletContext对象
ServletContext application = this.getServletContext();
//检证ServletContext对象中的用户名列表
List<String> usernameList = (List<String>) application.getAttribute("usernameList");
//用户名列表空
if(usernameList==null){
//创建用户名列表集合
usernameList = new ArrayList<String>();
//将用户加入列表信合
usernameList.add(username);
//绑定到ServletContext域对象
application.setAttribute("usernameList",usernameList);
//绑定到sesison域对象中
request.getSession().setAttribute("username",username);
//转发
request.getRequestDispatcher("/WEB-INF/welcome.jsp").forward(request,response);
//用户名列表非空
}else{
//循环迭代
for(String un : usernameList){
//如果用户名存在于列表名
if(un.equals(username)){
request.getRequestDispatcher("/WEB-INF/message.jsp").forward(request,response);
return;
}
}
//必定该用户名未在用户名列表中
//绑定到sesison域对象中
request.getSession().setAttribute("username",username);
//转发
request.getRequestDispatcher("/WEB-INF/welcome.jsp").forward(request,response);
}
}
}
}
package cn.itcast.web.servlet; import java.io.IOException;
import java.util.List; import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession; public class ExitServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
HttpSession session = request.getSession();
ServletContext application = this.getServletContext();
List<String> usernameList = (List<String>) application.getAttribute("usernameList");
boolean flag = usernameList.remove(session.getAttribute("username"));
session.invalidate();
response.sendRedirect("/day09/login.jsp");
}
}
4)application=ServletContext对象
<%@ page language="java" pageEncoding="UTF-8"%>
<%@ page import="java.util.*" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<body>
<%
application.setAttribute("name","jack");
application.removeAttribute("name");
String name = (String)application.getAttribute("name");
if(name!=null){
response.getWriter().write("用户名:"+name);
}else{
response.getWriter().write("用户名:"+name);
}
%>
</body>
</html>
5)config:取得jsp在web.xml文件中的映射信息
6)exception:该对象只能在<%@isErroPage="true"%>的情况下,容器才会创建,否则容器不予创建
7)out:out的类型是JspWriter,它是具体缓存功能的PrintWriter对象
•out隐式对象用于向客户端发送文本数据。
•out对象是通过调用pageContext对象的getOut方法返回的,其作用和用法与ServletResponse.getWriter方法返回的PrintWriter对象非常相似。
•JSP页面中的out隐式对象的类型为JspWriter,JspWriter相当于一种带缓存功能的PrintWriter,设置JSP页面的page指令的buffer属性可以调整它的缓存大小,甚至关闭它的缓存。
•只有向out对象中写入了内容,且满足如下任何一个条件时,out对象才去调用ServletResponse.getWriter方法,并通过该方法返回的PrintWriter对象将out对象的缓冲区中的内容真正写入到Servlet引擎提供的缓冲区中:
设置page指令的buffer属性关闭了out对象的缓存功能
out对象的缓冲区已满
整个JSP页面结束
<%@ page language="java" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<body>
<%
//out内置对象的类型是JspWriter,它是一个带有缓冲的PrintWriter对象
out.write("先");
//response内置对象输出
response.getWriter().write("后");
%>
</body>
</html>
8)pageContext: 表示Jsp行运过程中的环境对象。pageContext对象是JSP技术中最重要的一个对象,它代表当前JSP页面的运行环境,这个对象不仅封装了对其它8大隐式对象的引用,它自身还是一个域对象,可以用来保存数据。并且,这个对象还封装了web开发中经常涉及到的一些常用操作,例如包含和跳转其它资源、检索其它域对象中的属性等。
a)能够取得其它8个内置对象
b)具有转发和包含的功能
c)域对象
d)通过pageContext获得其他对象
•getException方法返回exception隐式对象
•getPage方法返回page隐式对象
•getRequest方法返回request隐式对象
•getResponse方法返回response隐式对象
•getServletConfig方法返回config隐式对象
•getServletContext方法返回application隐式对象
•getSession方法返回session隐式对象
•getOut方法返回out隐式对象
<%@ page language="java" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<body>
<%
//HttpServletRequest requestCopy = (HttpServletRequest)pageContext.getRequest();
//JspWriter outCopy = pageContext.getOut(); //String ip = requestCopy.getRemoteAddr();
//outCopy.write("你是IP是:" + ip); pageContext.forward("/guess.jsp");
%>
</body>
</html>
a)PageContext域对象仅限于当前jsp页面中,出了该jsp页面,原PageContext域对象销毁,如果取不到值,返回null
b)PageContext域对象可以将对应的值保存在指定的四个域对象之一
pageContext.setAttribute("name","丝丝",PageContext.REQUEST_SCOPE);
c)PageContext域对象可以将对应的值从指定的四个域对象之一取出
<%=pageContext.getAttribute("name",PageContext.APPLICATION_SCOPE) %>
d)PageContext.findAttribute("name")
它会以name为key,依次去四个域对象中查询对应的值,找到即止,如果找不到,返回null
<%@ page language="java" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<body>
<%
//pageContext.setAttribute("name","丝丝2",PageContext.REQUEST_SCOPE);
//pageContext.setAttribute("name","丝丝3",PageContext.SESSION_SCOPE);
//pageContext.setAttribute("name","丝丝1",PageContext.PAGE_SCOPE);
//pageContext.setAttribute("name","丝丝4",PageContext.APPLICATION_SCOPE);
%> 用户名:<%=pageContext.findAttribute("name")%>
</body>
</html>
<%@ page language="java" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<body>
<%
pageContext.removeAttribute("name",PageContext.SESSION_SCOPE);
%>
用户名:<%=pageContext.getAttribute("name",PageContext.SESSION_SCOPE) %>
</body>
</html>
[pageContext/request/session/application]
9)page