servlet中的类适合繁复翻看文档,熟悉各个类的常用方法,看一些经典的案例代码。
ServletConfig
每个项目有多个servlet,每个servlet对应一个ServletCOnfigt对象。ServletConfig中封装的是每个servlet的配置信息,具体而言就是web.xml中<servlet></servlet>中的配置内容。
可以使用HttpSerlet的this.getSerletConfig方法获得servletconfig
ServletContext:
每个项目对应一个ServletContext,ServletContext实体封装的内容对应web.xml中的配置信息,这包含的内容就比较的多了。在一个servlet中可以使用thi.getServletConfig().getServletContext()获取ServletContext也可以使用直接使用this.getServletContext()直接获取,后者中也是调用的第一个的方法。
从上面就就可以看出来,ServletContext的范围比ServletConfig的范围更大一些。
servlet中的域对象
ServletContext,HttpServletRequest,HttpSession。
jsp中的域对象(当然都是jsp9大内置对象)
applicaltion,HttpServletRequest,HttpSession,PageContext。application其实就是ServletContext(可以直接查看jsp翻译成的java文件)
servlet中的域对象只有三个,jsp中的域对象是servlet中的三个域对象再加一个jsp特有的pagecontext。
pageContext是使用最多的一个内置对象,可以通过pageContext获取其余八个内置对象。
#获取数据
1)默认情况下,从page域获取
pageContext.getAttribute("name")
2)可以从四个域中获取数据
pageContext.getAttribute("name",域范围常量)
域范围常量:
PageContext.PAGE_SCOPE
PageContext.REQUEST_SCOPE
PageContext.SESSION_SCOPE
PageContext.APPLICATION_SCOPE
3)自动在四个域中搜索数据
pageContext.findAttribute("name");
顺序: page域 -> request域 -> session域- > context域(application域)这展示了四个域的大小
page域: 只能在当前jsp页面中使用(当前页面)
request域: 只能在同一个请求中使用(转发)
session域: 只能在同一个会话(session对象)中使用(私有的)
context域: 只能在同一个web应用中使用。(全局的)
Servlet技术: 开发动态资源。是一个java类,最擅长写java代码
jsp技术: 开发动态资源。通过java代码最擅长输出html代码。
有个不成文的准则,尽量在jsp页面中不写java脚本,为了达到这一目的,jsp中的标签应运而生。
jsp中的标签替换java脚本。
jsp中的EL表达式替换jsp中的输出脚本。
EL表达式
其初衷是为了替换掉,jsp中向浏览器中输出内容的脚本:<%= %> <% %>
基本语法:{$变量或者表达式},集体如下:
1)输出基本数据类型变量
1.1 从四个域获取
${name},会自动按照从小到大的域搜索,相当于pageContext.findAttribute(“name”) page->request->session->application
1.2 指定域获取
${pageScope.name}
域范围: pageScoep / requestScope / sessionScope / applicationScope
分别对应于: page域 request域 session域 application域
2)输出对象的属性值
Class Student
{
String name,id;
Public void setId();
Public void setName();
Public String getId();
Public String getName();
}
{$stu.name}就是输出Student就会调用getName,一定注意el表达式中的后面应当就是getName方法去掉get的内容。
3)输出集合对象
List 和 Map,一样遵守上面的规则。
假设list和map中中存放了若干个Student,那么获取list中student的属性:
{$list[0].id} - {$list[0].name},list[0]相当于((List)pageContext.findAttribute(“list”)).get(0)
{$map[‘100’.name]}
4)EL表达式计算
${10*5 }
${10!=10 }
${true && false }
判断null: ${name==null }
判断空字符: ${name=="" }
jsp中标签的分类
- 内置标签(action动作标签): 不需要在jsp页面导入标签
- jstl标签: 需要在jsp页面中导入标签
- 自定义标签 : 开发者自行定义,需要在jsp页面导入标签
下面就是分别围绕这三种标签展开介绍
动作标签(内置标签)
内置标签 就是在jsp的空间里面
转发标签: <jsp:forward />
参数标签: <jsp:pararm/>
包含标签: <jsp:include/>
原理: 包含与被包含的页面先各自翻译成java源文件,然后再运行时合并在一起,相当于一种调用。
(先翻译再合并),动态包含
静态包含 vs 动态包含的区别?
1) 语法不同
静态包含语法: <%@inclue file="被包含的页面"%>
动态包含语法: <jsp:include page="被包含的页面">
2)参数传递不同
静态包含不能向被包含页面传递参数
动态包含可以向被包含页面传递参数
3)原理不同
静态包含: 先合并再翻译
动态包含: 先翻译再合并
======================================
JSTL标签
JSTL (全名:java standard tag libarary - java标准标签库 )
核心标签库 (c标签库) 天天用 c core
国际化标签(fmt标签库)
EL函数库(fn函数库)
xml标签库(x标签库)
sql标签库(sql标签库)
使用jstl标签的步骤
1) 导入jstl支持的jar包(标签背后隐藏的java代码)<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
注意:使用javaee5.0的项目自动导入jstl支持jar包,否则就要自己导入。
2)使用taglib指令导入标签库
<%@taglib uri="tld文件的uri名称" prefix="简写" %>
3)在jsp中使用标签
核心标签库的重点标签:
保存数据:
<c:set></c:set>
获取数据:
<c:out value=""></c:out>
单条件判断
<c:if test=""></c:if>
多条件判断
<c:choose></c:choose>
<c:when test=""></c:when>
<c:otherwise></c:otherwise>
循环数据
<c:forEach></c:forEach>
<c:forTokens items="" delims=""></c:forTokens>
重定向
<c:redirect></c:redirect>
在jsp文件的html标签之前使用tablib导入标签库
<%@taglib uri = “路径” prifix = “shotname”/>其中uri和prefix可以到对应标签包的tld文件中查看
核心标签forEach的使用实例:
<body>
<%--使用标签 --%>
<%--set标签 :保存数据(保存到域中)默认保存到page域 --%>
<c:set var="name" value="rose" scope="request"></c:set>
<%
String msg = null;
pageContext.setAttribute("msg",msg);
%>
${msg }
<br/>
<%--out标签: 获取数据(从域中)
default: 当value值为null时,使用默认值
escapeXml: 是否对value值进行转义,false,不转义,true,转义(默认)
--%>
<c:out value="${msg}" default="<h3>标题3</h3>" escapeXml="true"></c:out>
<hr/>
<%--if标签 :单条件判断--%>
<c:if test="${!empty msg}">
条件成立
</c:if>
<hr/>
<%--choose标签+when标签+otherwirse标签: 多条件判断 --%>
<c:set var="score" value="56"></c:set>
<c:choose>
<c:when test="${score>=90 && score<=100}">
优秀
</c:when>
<c:when test="${score>=80 && score<90}">
良好
</c:when>
<c:when test="${score>=70 && score<80}">
一般
</c:when>
<c:when test="${score>=60 && score<70}">
及格
</c:when>
<c:otherwise>
不及格
</c:otherwise>
</c:choose>
<%-- forEach标签:循环 --%>
<%
//List
List<Student> list = new ArrayList<Student>();
list.add(new Student("rose",18));
list.add(new Student("jack",28));
list.add(new Student("lucy",38));
//放入域中
pageContext.setAttribute("list",list);
//Map
Map<String,Student> map = new HashMap<String,Student>();
map.put("100",new Student("mark",20));
map.put("101",new Student("maxwell",30));
map.put("102",new Student("narci",40));
//放入域中
pageContext.setAttribute("map",map);
%>
<hr/>
<%--
begin="" : 从哪个元素开始遍历,从0开始.默认从0开始
end="": 到哪个元素结束。默认到最后一个元素
step="" : 步长 (每次加几) ,默认1
items="": 需要遍历的数据(集合)
var="": 每个元素的名称
varStatus="": 当前正在遍历元素的状态对象。(count属性:当前位置,从1开始)
--%>
<c:forEach items="${list}" var="student" varStatus="varSta">
序号:${varSta.count} - 姓名:${student.name } - 年龄:${student.age}<br/>
</c:forEach>
<hr/>
<c:forEach items="${map}" var="entry">
${entry.key } - 姓名: ${entry.value.name } - 年龄:${entry.value.age }<br/>
</c:forEach>
<hr/>
<%-- forToken标签: 循环特殊字符串 --%>
<%
String str = "java-php-net-平面";
pageContext.setAttribute("str",str);
%>
<c:forTokens items="${str}" delims="-" var="s">
${s }<br/>
</c:forTokens>
<%--redrict:重定向 --%>
<c:redirect url="http://www.baidu.com"></c:redirect>
</body>
自定义标签
2.1 引入
需求: 向浏览器输出当前客户的IP地址 (只能使用jsp标签)
2.2 第一个自定义标签开发步骤
1)编写一个普通的java类,继承SimpleTagSupport类,叫标签处理器类
/** * 标签处理器类 * @author APPle * 1)继承SimpleTagSupport * */ public class ShowIpTag extends SimpleTagSupport{ private JspContext context; /** * 传入pageContext */ @Override public void setJspContext(JspContext pc) { this.context = pc; } /** * 2)覆盖doTag方法 */ @Override public void doTag() throws JspException, IOException { //向浏览器输出客户的ip地址 PageContext pageContext = (PageContext)context; HttpServletRequest request = (HttpServletRequest)pageContext.getRequest(); String ip = request.getRemoteHost(); JspWriter out = pageContext.getOut(); out.write("使用自定义标签输出客户的IP地址:"+ip); } } |
2)在web项目的WEB-INF目录下建立itcast.tld文件,这个tld叫标签库的声明文件。(参考核心标签库的tld文件)
<?xml version="1.0" encoding="UTF-8" ?> <taglib xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd" version="2.1"> <!-- 标签库的版本 --> <tlib-version>1.1</tlib-version> <!-- 标签库前缀 --> <short-name>itcast</short-name> <!-- tld文件的唯一标记 --> <uri>http://gz.itcast.cn</uri> <!-- 一个标签的声明 --> <tag> <!-- 标签名称 --> <name>showIp</name> <!-- 标签处理器类的全名 --> <tag-class>gz.itcast.a_tag.ShowIpTag</tag-class> <!-- 输出标签体内容格式 --> <body-content>scriptless</body-content> </tag> </taglib> |
3) 在jsp页面的头部导入自定义标签库
<%@taglib uri="http://gz.itcast.cn" prefix="itcast"%>
4) 在jsp中使用自定义标签
<itcast:showIp></itcast:showIp>
2.3 自定义标签的执行过程
问题: http://localhost:8080/day14/01.hellotag.jsp 如何访问到自定义标签?
前提: tomcat服务器启动时,加载到每个web应用,加载每个web应用的WEB-INF目录下的所有文件!!!例如。web.xml, tld文件!!!
1)访问01.hellotag.jsp资源
2)tomcat服务器把jsp文件翻译成java源文件->编译class->构造类对象->调用_jspService()方法
3)检查jsp文件的taglib指令,是否存在一个名为http://gz.itcast.cn的tld文件。如果没有,则报错
4)上一步已经读到itcast.tld文件
5)读到<itcast:showIp> 到itcast.tld文件中查询是否存在<name>为showIp的<tag>标签
6)找到对应的<tag>标签,则读到<tag-class>内容
7)得到 gz.itcast.a_tag.ShowIpTag
构造ShowIpTag对象,然后调用ShowIpTag里面的方法
2.4 自定义标签处理器类的生命周期
SimpleTag接口:
void setJspContext(JspContext pc) --设置pageContext对象,传入pageContext(一定调用)
通过getJspCotext()方法得到pageContext对象
void setParent(JspTag parent) --设置父标签对象,传入父标签对象,如果没有父标签,则不 调用此方法。通过getParent()方法得到父标签对象。
void setXXX(值) --设置属性值。
void setJspBody(JspFragment jspBody) --设置标签体内容。标签体内容封装到JspFragment对象 中,然后传入JspFragment对象。通过getJspBody()方法 得到标签体内容。如果没有标签体内容,则不会调 用此方法
void doTag() --执行标签时调用的方法。(一定调用)
2.5 自定义标签的作用
1)控制标签体内容是否输出
2)控制标签余下内容是否输出
3)控制重复输出标签体内容
4)改变标签体内容
5)带属性的标签
步骤:
5.1 在标签处理器中添加一个成语变量和setter方法
//1.声明属性的成员变量 private Integer num; //2.关键点: 必须提供公开的setter方法,用于给属性赋值 public void setNum(Integer num) { this.num = num; } |
2.6 输出标签体内容格式
JSP: 在传统标签中使用的。可以写和执行jsp的java代码。
scriptless: 标签体不可以写jsp的java代码
empty: 必须是空标签。
tagdependent : 标签体内容可以写jsp的java代码,但不会执行。
案例
核心标签库: c:if c:choose+c:when+c:otherwise c:forEach
高仿核心标签库
在Myeclipse中,alt+shift+z可以进入一种选择模式
选中一块内容,然后ctrl+f,使用正则表达式 ^(.*)$ ^表示行首,$表示行为,.代表任意字符,*表示至少一次。替换为1”;其中1表示前面组()的引用,表示把前面的内容后面替换为”;
制作<itcast:login>标签:
对应的标签处理器类LoginTag.class
public class LoginTag extends SimpleTagSupport{ private String username; private String password; public void setUsername(String username) { this.username = username; } public void setPassword(String password) { this.password = password; } @Override public void doTag() throws JspException, IOException { HttpServletResponse response = (HttpServletResponse)((PageContext)this.getJspContext()).getResponse(); //设置输出内容类型和编码 response.setContentType("text/html;charset=utf-8"); String html = ""; html += "<center><h3>用户登陆页面</h3></center>"; html += "<table border='1' align='center' width='400px'>"; html += " <tr>"; html += " <th>用户名:</th>"; html += " <td><input type='text' name='"+username+"'/></td>"; html += " </tr>"; html += " <tr>"; html += " <th>密码:</th>"; html += " <td><input type='password' name='"+password+"'/></td>"; html += " </tr>"; html += " <tr>"; html += " <td colspan='2' align='center'><input type='submit' value='登陆'/> <input type='reset' value='重置'/></td>"; html += " </tr>"; html += "</table>"; JspWriter out = this.getJspContext().getOut(); out.write(html); } } |
对应的tld文件
<tag> <name>login</name> <tag-class>gz.itcast.b_cases.LoginTag</tag-class> <body-content>scriptless</body-content> <attribute> <name>username</name> <required>true</required> <rtexprvalue>false</rtexprvalue> </attribute> <attribute> <name>password</name> <required>true</required> <rtexprvalue>false</rtexprvalue> </attribute> </tag> |
实现自己的<itcast:choose><itcast:when><itcast:otherwise>标签。注意对应的编前处理类中的设计技巧,这里的choose标签是when和otherwise的父标签,我们给父标签处理类中设置一个变量用来在子标签之间传递信息,但是注意父标签中的这个变量不是父标签的属性。
先看自定义标签的使用:
<body> <itcast:choose> <itcast:when test="${10<5}"> 条件成立 </itcast:when> <itcast:otherwise> 条件不成立 </itcast:otherwise> </itcast:choose> </body> |
各个标签处理类的设计
public class ChooseTag extends SimpleTagSupport { //不是属性,而是临时变量,用于在子标签之间传递数据 private boolean flag; public boolean isFlag() { return flag; } public void setFlag(boolean flag) { this.flag = flag; } @Override public void doTag() throws JspException, IOException { //输出标签体内容,可能是when或者otherwise中的内容 this.getJspBody().invoke(null); } } |
public class WhenTag extends SimpleTagSupport { private boolean test; public void setTest(boolean test) { this.test = test; } @Override public void doTag() throws JspException, IOException { //根据test的返回值决定是否输出标签体内容 if(test){ this.getJspBody().invoke(null); } //获取父标签 ChooseTag parent = (ChooseTag)this.getParent(); parent.setFlag(test); } } |
public class OtherwiseTag extends SimpleTagSupport { @Override public void doTag() throws JspException, IOException { //通过父标签传递,when标签中test的值 //获取父标签 ChooseTag parent = (ChooseTag)this.getParent(); boolean test = parent.isFlag(); if(!test){ this.getJspBody().invoke(null); } } } |
线面是自定义的foreach标签
Tld文件 <tag> <name>forEach</name> <tag-class>myjstl.ForEachTag</tag-class> <body-content>scriptless</body-content> <attribute> <!-- 标签名称 --> <name>var</name> <!-- 这个属性是不是必须的 --> <required>true</required> <!-- 是否支持el表达式 --> <rtexprvalue>false</rtexprvalue> </attribute> <attribute> <name>items</name> <required>true</required> <rtexprvalue>true</rtexprvalue> </attribute> </tag> |
标签处理类 public class ForEachTag extends SimpleTagSupport { private Object items; // 需要遍历的数据,list或者map private String var; // 遍历的变量的名称 public void setItems(Object items) { this.items = items; } public void setVar(String var) { this.var = var; } @Override public void doTag() throws JspException, IOException { PageContext context = (PageContext) this.getJspBody().getJspContext(); Collection coll = null; if(items instanceof List){ coll = (Collection) items; } if(items instanceof Map){ Map map = (Map) items; coll = map.entrySet(); } for(Object obj : coll){ context.setAttribute(var, obj); //每次循环 都显示 标签体的内容 this.getJspBody().invoke(null); } } } |
Jsp页面中的使用 <%@taglib uri="http://gz.itcast.cn" prefix="itcast" %> <% List<Student> list = new ArrayList<Student>(); list.add(new Student("100", "mike")); list.add(new Student("101", "jane")); list.add(new Student("102", "mary")); list.add(new Student("103", "jordan")); pageContext.setAttribute("list", list);
Map <String, Student> map = new HashMap<String, Student>();
map.put("001", new Student("101", "mike")); map.put("002", new Student("102", "kang")); map.put("003", new Student("103", "mary")); map.put("004", new Student("104", "jane")); pageContext.setAttribute("map", map); %> <itcast:forEach var = "stu" items = "${list }"> ${stu.id }--${stu.name }<br/> </itcast:forEach> <itcast:forEach var = "entry" items = "${map}"> ${entry.key }--${entry.value.id}--${entry.value.name }<br/> </itcast:forEach> |
JavaBean
JavaBean, 咖啡豆。 JavaBean是一种开发规范,可以说是一种技术。
JavaBean就是一个普通的java类。只有符合以下规定才能称之为javabean:
1)必须提供无参数的构造方法
2)类中属性都必须私有化(private)
3)该类提供公开的getter 和 setter方法
JavaBean的作用: 用于封装数据,保存数据。
访问javabean只能使用getter和setter方法
以下方法哪些属于javabean的规范的方法? 答案 :( 1,3,5,6 )
注意: boolean类型的get方法名称叫 isXXX()方法
1)getName() 2)getName(String name)
3)setName(String name) 4)setName()
5) setFlag(boolean flag) 6)isFlag()