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