- 浏览: 76577 次
- 性别:
- 来自: 广州
最新评论
-
wayilau:
第24条,是不是有问题呀。。。
教你认人 -
xiaoBaoProgramme:
很好的一篇文章,顶。
html页面嵌套html页面 -
JUnique:
...
SSH -
yihuijie2011:
...
SSH -
linpark:
没事来看看~
SSH
Servlet JSP
配置tomcat:
Tomcat有zip包和exe版,本配置针对非安装zip包使用:
1 在myEclipse中加载Tomcat
2 选择tomcat的安装路径,并选择服务器Enable此时会在myEclipse中多一个图标
3选择tomcat对于的jdk
4 启动Tomcat
5 添加一个J2EE的配置工程
每次修改web.xml后重新配置tomcat
Web-inf 站点内容 web.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
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-app_2_5.xsd">
<servlet>
<!-- name写的只自己命名的一个servlet,可以不是那个servlet类名 -->
<servlet-name>MyServlet</servlet-name>
<!-- servletd类名,注意加上完整的包名 -->
<servlet-class>ServletDemo</servlet-class>
</servlet>
<servlet-mapping>
<!-- name写的只自己命名的一个servlet,可以不是那个servlet类名 ,注意与上面的要一致-->
<servlet-name>MyServlet</servlet-name>
<!--这是一个虚拟路径 -->
<url-pattern>/Servlet/web</url-pattern>
</servlet-mapping>
<welcome-file-list>
<!-- 这里放的是页面html,包括具体的路径,这个顺序是文件在-->
<!-- 当用http://127.0.0.1:8080/html(html是该项目名称)打开时 -->
<!-- 将会出现下面的第一个html的界面 -->
<welcome-file>right.html</welcome-file>
<welcome-file>Form.html</welcome-file>
</welcome-file-list>
</web-app>
Lib:存放所以的包文件
Class存放所有的类文件
配置tomcat环境,启动在bin,配置在config
Servlet做好配置,本身是一个基本java类,只有再继承了httpservlet才能称为servlet,这样才有可能响应页面的请求(比如接受页面数据)
Response可以想象为通向页面的一个socket,可以通过其方法获得一些IO流
Servlet中访问报头
HTTP报头,提交请求和服务器向客户端做出响应时 ,浏览器和服务器都会再请求和响应后自动添加的一些附加信息,这些附加信息称之为报头,这些都是浏览器自动附加上去的,用户并不知道!
报头分类
请求报头
应用:反爬虫系统:首先查看报头信息,比如User-Agent(请求的浏览器或者其他客户程序),如果能够识别某些报头那么则是正常的浏览器访问,否则就是爬虫来获得信息,予以制止。
应用:国际化使用:对于不同的范围浏览器给予不同的反映页面,这是可以获得accept-lanugae,通过判断这个语言从而给于不同的反映。
响应报头
如何设置编码和解码格式;request.setcharactset()…..
CGI变量
它是传统的CGI编程中常用的,汇集了各种信息,如来自于HTTP命令和请求头,Socket本身等的信息。
Request.get…( )方法
Servlet生命周期(servlet是单例的,并且是多线程并发)
第一次被访问时:
产生实例(调用构造函数)
初始化(调用init函数)
然后自动调用service()方法,并去执行doget或者dopost方法
我们可以重写这些方法,已获得自己的一些效果。。。。。这些方法都由tomcat自动调用。。。。
以后被访问时:
以后同一个实例启动多个线程执行用户操作(首先调用service函数,然后由service函数根据请
求类型决定调用doGet函数或doPost函数)
这时多个并发线程共享servelet的成员变量,因此对于这样的数据注意使用线程锁。
站台被重新部署等时候,调用destroy函数或者Tomcat关机的时候关闭
配套的HTML文件
JSP
Jsp机制
所有JSP页面,在执行的时候都会被服务器端的JSP引擎转换为Servelet(.java),然后又由JSP引擎调用Java编译器,将Servelet(.java)编译为Class文件(.class),并由Java虚拟机(JVM)解释执行。同时在%CATALINA_HOME%\work\Catalina\localhost下多出两个文件:_Test_jsp.java和_Test_jsp.class,他们分别就是Servelet和Class文件。
然后由Servlet产生HTML页面传回客户端以供显示
在D:\tomcat6\work\Catalina\localhost路径下可以看到被tomcat解释的java文件
JSP组成:
声明:
<%! %>中间的部分。
这里申明的变量,将成为Jsp生成的对应的类的成员变量
这里申明的函数,将成为Jsp生成的对应的类的成员函数
JSP执行
<% %>中间的部分。
这里的代码会在Jsp页面显示的同时被执行,如同写在main函数里的代码一样。
JSP表达式
<%= %>中间的部分
取得某个变量的值。
在页面显示部分直接使用表达式,即为直接显示某个变量的值。
JSP注释
两种注释方式:
<%-- 客户端的源码看 不 见我 --%>
<!-- 客户端的源码看 得 见我 -->
俗称:在Html里写Java代码
<%@ page language="java" import="java.util.Date" pageEncoding="utf-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
</head>
<body>
<%-- 这是JSP注释 ,好像不能嵌套啊! --%>
<%-- 这时JSP申明部分 --%>
<%!
String myDate = null;
String path = null;
String basePath = null;
void getDate(){
Date my = new Date();
this.myDate = my.toLocaleString();
}
%>
<%--这是JSP执行部分 --%>
<%
this.getDate();
%>
欢迎光临,今天是:<%= this.myDate %><br>
</body>
</html>
在IE上直接运行:http://127.0.0.1:8080/项目名/**.jsp即可
08.12.23 JSP高级应用 Jsp和Servlet联合应用 web高级应用
JSP高级应用
Jsp指令-page
<%@ page import="java.util.*" %>
<%@ page session=”false" %>
<%@ page errorPage=”error.jsp" %>
JSP指令 - page的错误处理方案
解决办法
在可能发生异常的页面添加
<%@ page errorPage="error.jsp" %>
在显示错误信息的页面添加
<%@ page isErrorPage="true" %>
在显示错误信息的页面获取异常
通过JSP的隐含exception直接获得异常(这里的exception是jsp的内置对象)象征着从其他页面传递过来的异常实例。
<%
String e = exception.getMessage();
%>
index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%-- 异常错误重定向 --%>
<%@ page errorPage="./Error.jsp" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'index.jsp' starting page</title>
</head>
<body>
<%!
int i;
int j;
%>
<%
i = 0;
j = 7/i;
%>
</body>
</html>
Error.jsp
<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%>
<%@ page isErrorPage = "true" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'Error.jsp' starting page</title>
</head>
<body>
<%
String msg = exception.getMessage();
%>
</body>
</html>
JSP指令 - include
功能:嵌入外部页面,用来把子页面引入母页面
<%@ include file="head.jsp" %>
应用:一个jsp放框架模板,而其他的jsp放一些具体内容,则可以在框架jsp中用include引入其他的内容jsp即可实现复杂的页面。
<a href = “#”> 这里的#表示当前页面
这样一个页面就由三个人处理,而这三个人都可以分开处理:首先由模板工程师定义模板,由美工通过css来处理,内容由内容工程师自行完成,并通过include指令加载到框架中。
JSP动作 - include
功能:嵌入外部页面,实现的效果和jsp的include指令一致。
<jsp:include flush="true" page="head.jsp" / >
JSP动作 - forward
功能:跳转到其他页面
<jsp:forward page="welcome.jsp" />
使用:目前是一种过期技术,用处不大,在早期使用较多。
JSP动作 - param
功能:在跳转的页面间传递数据
<jsp:forward page="welcome.jsp">
<jsp:param name="user_name" value="Eric"/>
</jsp:forward>
JSTL
引入:一个jsp含有html标签,也有java代码,让谁来维护呢?如果不想增加谁的负担,解决办法是:在jsp页面只实现一些逻辑顺序,并且把java的一些逻辑用类似于xml的标签的形式表达,这样美工易于理解和掌握。
JSP 标准标记库(JSP Standard Tag Library,JSTL)是一个实现 Web 应用程序中常见的通用功能的定制标记库集,这些功能包括迭代和条件判断、数据管理格式化、XML 操作以及数据库访问。
具体而言就是能实现一些java的操作,但是有不出现真正的java代码,而是用一些标签来表示java的操作。
但是目前在表现层又不使用:访问数据库,解析xml这些功能了,放到后面的持久层等。目前已被后面的东东标记库所逐渐替代。
JSTL的意义
为了方便网页设计师,他们即使没有学过Java,也可以轻松处理应用程序数据。
主要功能:
访问存储对象
简化JavaBean的访问方式
对集合的简化访问
简单运算符
条件输出
JSP与Servlet联合
JSP的隐含对象
Request(当前人当前请求的线程)
session(针对某个具体客户使用,所以的线程使用,比如判断某人是否登陆)
exception
Application(针对任何人,任何线程共享使用,比如网站浏览计数)
Page
Out
Out:直接应用在jsp页面中(<% out.();%>),往页面输出数据。
JSP(表现层)与Servlet(控制层)间数据传递
从JSP到Servlet
从JSP发送数据:
通过form提交,一旦一个form被submit则数据自动从jsp传递到Servlet中
在Servlet中接收数据:
String userName = request.getParameter( "userName" );
“userName”为Jsp中form对应的标签的name属性
从Servlet到JSP
要主动的在Servlet中传,要在jsp中主动的去接受数据。
从Servlet发送数据:
// 将数据作为attribute存入request中
request.setAttribute( "user_name", userName );//这里的user_name仅仅是一个标记
// 跳转到指定页面并传递数据
RequestDispatcher rd = request.getRequestDispatcher( "../shu_ju_chuan_di/Welcome.jsp" );
rd.forward( request, response );
这两语句仅仅是进行保存,等全部语句执行完毕后,Servlet就会检查post是否有保存东西和foword东西,如果有就进行重定向,因此在一个forward后面不要再有其他的forward方法了。
再次注意:requset里的保存和重定向得到的数据都是单线程使用的,不能被其他线程共享。如果要实现多个线程中数据的共享需要使用application对象。
在JSP中接收数据:
String userName = ( String )request.getAttribute( "user_name" );
//这个user_name就是前面的setAttribute中的标记。
session
访问范围
当前客户的所有组件
请参照配套登录实例
用同一个浏览器多次访问
用不同浏览其多次访问
HttpSession se = request.getSession();
Se.setAttribute();
application
访问范围
这是一个全局单例共享空间
服务器上所有组件
请参照配套登录实例
用同一个浏览器多次访问
用不同浏览其多次访问
在servlet中用:ServletContext application = this.getServletContext()
在jsp中用application
Web中文显示问题
解决页面显示中文问题
<%@ page language="java" import="java.util.*" pageEncoding=“UTF-8"%>
解决request传递中文问题
request.setCharacterEncoding( "UTF-8" );
在接受数据之前使用上述语句
并且页面表单使用form中的post方法,而不用get方法,使用get时其提交的信息会出现在IE中,需要进行特殊的处理才能正常显示中文。
JSP动态显示table方案
WebDemoServlet.java
import java.io.IOException;
import java.util.Hashtable;
import java.util.Map;
import javax.servlet.RequestDispatcher;
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 WebDemoServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// TODO Auto-generated method stub
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse resp)
throws ServletException, IOException {
// TODO Auto-generated method stub
//准备接受数据,为了实现中文传递,向先定义解码方式
request.setCharacterEncoding("UTF-8");
//如果是发送的话,那么也要设置其字符格式
resp.setCharacterEncoding("UTF-8");
//通过 request.getParameter()方法接受数据,
//下面方法中的"userName"对于表单中的文本框的名字
String userName = request.getParameter("userName");
String passWord = request.getParameter("passWord");
//以上就是从jsp中得到的各个数据,可以直接打印处理
System.out.println(userName + "-" + passWord);
//下面的部分实现将从Jsp读来的数据发送到另外一个Jsp页面中去
//第一步:将数据作为attribute存入request中
//下面的语句表示将userName保存在代号为USER_NAME的requset中
request.setAttribute("USER_NAME", userName);
request.setAttribute("PASSWORD", passWord);
//下面练习关于session的使用,使用范围是当前客户的所有组件,这是系统通过
//关于http报头和CGI变量来识别的
HttpSession hs = request.getSession();
//下面这句话和requset类似,就是把username保存到一个session里面,这个
//session的名字是"USER_NAME_SESSION",这样在其他的jsp里面就可以用到这个session的值了
//似乎这种数据的保存方式有点像Map
hs.setAttribute("USER_NAME_SESSION", userName);
//下面是关于全局变量application的使用
//因为用到的是全局变量,因此用到this,这里也不是直接说applicaton,而是context
ServletContext sc = this.getServletContext();
//这里的count用来计数,并且表面值为0
sc.setAttribute("COUNT", 0);
//下面演示动态table的形成,其实这表达了jsp编程的灵活性,
//对此的理解关键是要知道jsp的机制,其是被tomcat翻译成一个Servlet,
Map<String,Integer> list = new Hashtable<String,Integer>();
list.put("zheng", 25);
list.put("zhu", 25);
list.put("ma", 26);
//将这个数据用reques传递到jsp中去
request.setAttribute("LIST", list);
//采用request进行数据传递的时候一定要把他放到跳转的页面的前面。跳转到哪里,就到哪里去接受!
//第二步:跳转到指定页面并传递数据,制定转到当前路径的reslult.jsp文件中
//注意在使用相对路径的时候,这里的相对指得是Servlet与要转向的文件之间的相对性
RequestDispatcher rd = request.getRequestDispatcher("../Result.jsp");
rd.forward(request, resp);
}
}
index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<!-- 下面通过表单实现从Jsp向Servlet进行数据传递,主要是通过request -->
<!-- 当选择submit时,自动的将表单的各个数据向Servlet发送 -->
<h2 >用户登陆</h2>
<form action = "./Servlet/web" method = "post">
请输入用户名:
<input type = "text" name ="userName" ><br>
请输入密码:
<input type = "password" name ="passWord" ><br><br><br>
<input type = "submit" value = 确认>
<input type = "reset" value = 重写>
</form>
</body>
</html>
Result.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'Result.jsp' starting page</title>
</head>
<body>
<%!
String userName;
int count;
%>
<%
userName = (String)request.getAttribute("USER_NAME");
String passWord = (String)request.getAttribute("PASSWORD");
%>
用户名为:<%= userName %><br><!-- 这是jsp表达式 -->
密码为:<% out.print(passWord); %><!-- 这是jsp的执行部分 -->
采用session的方式得到用户名为:<br>
<%
userName = (String)session.getAttribute("USER_NAME_SESSION");
out.println(userName);
%>
<%
count =(Integer) application.getAttribute("COUNT");
count++;
out.println("您是第" +count +"人访问该网站");
application.setAttribute("COUNT",count);
%>
<br>
下面的部分接受Servlet传来的数据,并进行动态的表格打印
<table border = 1>
<tr>
<th>姓名</th>
<th>年龄</th>
</tr>
<%
Hashtable<String,Integer> list =(Hashtable<String,Integer>) request.getAttribute("LIST");
Set<String > nameSet = list.keySet();
for(String name:nameSet){
int age = list.get(name);
%>
<tr>
<td>
<%= name %>
</td>
<td>
<%= age %>
</td>
</tr>
<%
}
%>
</table>
</body>
</html>
SessionTest.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'SessionTest.jsp' starting page</title>
</head>
<body>
<%!
String userName;
int count;
%>
<%
userName = (String )session.getAttribute("USER_NAME_SESSION");
out.println("这是第二个浏览器访问的情况,但是可以用同一个session<br>");
out.println("用户名为:" + userName);
%>
<br>
<%
count =(Integer) application.getAttribute("COUNT");
count++;
out.println("您是第" +count +"人访问该网站");
application.setAttribute("COUNT",count);
%>
</body>
</html>
堆栈和队列容器的实现
容器 保存(堆栈,队列),最大长度,为空(等待再来拿,类似池的概念),多个堆栈,多个队列
类加载: 第一:如果要new一个子类,则JVM会先new一个父类(调用其默认构造器)。
第二:如果父类没有默认构造器(无参构造器)那么子类必须明确的用super来指明调用父类的那个构造器。
注意系统的结构良好性:可重用!,可读性好!(利用继承和多态减少代码的重复)
项目实施过程:功能(一期工程),安全(二期工程),性能(三期工程)
内核(关键的东西)+外壳(相当于一个工厂):这样可以降低模块之间的耦合度,提高模块的独立性,可以任意修改内核的东西,而不会影响外壳的东西。
Container.java
package container;
/**
* 这是一个容器类的父类,该容器主要是为了实现队列,堆栈等存储方式
* @author
*
*/
import java.util.List;
import java.util.Vector;
import util.DataManager;
public class Container{
//容器的最大容量
protected int containerSize;
//当存入数据时的最大尝试次数
protected int popRetryTime;
//当存入数据时的每次尝试等待时间
protected int popWaitTime;
//当读数据时的最大尝试次数
protected int pushRetryTime;
//当读数据时的每次尝试等待时间
protected int pushWaitTime;
private String curContainerType;
//这里用了Vector主要是考虑线程安全的问题
public List dataList = new Vector();
//构造函数,因为后面的队列和堆栈都要传递参数,因此写在父类的构造器里面
//以免代码重复
public Container(int containerSize,int popRetryTime,int popWaitTime,int pushRetryTime,int pushWaitTime,String containerType){
this.containerSize = containerSize;
this.popRetryTime = popRetryTime;
this.popWaitTime = popWaitTime;
this.pushRetryTime = pushRetryTime;
this.pushWaitTime = pushWaitTime;
this.curContainerType = containerType;
}
/**
* 读取数据的方法 ,并且根据不同的容器类型,采用不同的读方法
* @return
* @throws Exception
*/
public Object pop()throws Exception {
Object data =null ;
data = DataManager.waitForPop(this,0);
return data;
}
/**
* 插入数据方法
* @author
*/
public void push(Object data)throws Exception {
// TODO Auto-generated method stub
DataManager.waitForPush(this, 0, data);
}
public int getLength(){
return dataList.size();
}
/**
* 判断容器是否为空
* @return 如果为空则返回true,否则返回false
* @author
*/
public boolean isEmpty(){
int length = dataList.size();
if (length <= 0){
return true;
}
return false;
}
/**
* 判断容器是否为满,
* @return 如果为满则返回true,否则返回false
* @author
*/
public boolean isFull(){
if(this.containerSize ==-1){
return false;
}
if(this.containerSize <= this.dataList.size()){
return true;
}
return false;
}
public int getPopRetryTime() {
return popRetryTime;
}
public int getPopWaitTime() {
return popWaitTime;
}
public int getPushRetryTime() {
return pushRetryTime;
}
public int getPushWaitTime() {
return pushWaitTime;
}
public String getCurContainerType() {
return curContainerType;
}
}
DataManager.java
/**
*
* 这是一个工具类,主要实现了对容器中的数据插入和获取操作,
* 其关键点在于能够根据用户的需要进行等待或不等待
* @author
*
*/
import container.Container;
public class DataManager {
/**
* 等待获取数据方法,
* @param container 待获取的容器
* @param ct 要获取的容器的类型
* @param curRetryTime 当前尝试获取的次数
* @return 返回的获取数据
* @throws Exception 不能获取时抛出异常
* @author
*/
public static Object waitForPop (Container container,int curRetryTime) throws Exception {
Object data;
int indexData = 0;
//不为空的话直接取值
if(!container.isEmpty()){
if(container.getCurContainerType().equals("stack")){
indexData = container.getLength()-1;
}else if(container.getCurContainerType().equals("queue")){
indexData = 0;
}else if(container.getCurContainerType().equals("random")){
indexData = (int)(Math.random()*container.getLength());
}
data = container.dataList.get(indexData);
container.dataList.remove(indexData);
return data;
}
//为空的话,等待,再测试是否能够拿到,并且要判断是否需要无穷等待
if(container.getPopRetryTime()>-1){
if(curRetryTime >= container.getPopRetryTime()){
throw new Exception("容器为空,请稍候再试!");
}else{
curRetryTime++;
}
}
Thread.sleep(container.getPopWaitTime());
return waitForPop (container,curRetryTime);
}
/**
* 插入数据的方法
* @param container 待插入的容器
* @param curRetryTime 以尝试插入的次数
* @param data 待插入的数据
* @throws Exception 不能插入时抛出异常
* @author
*/
public static void waitForPush(Container container,int curRetryTime,Object data)throws Exception{
//判断容器是否已满,如果不满的话则直接添加进去
if(!container.isFull()){
container.dataList.add(data);
return ;
}
//如果容器满的话,等待,再测试是否能够插入,并且要判断是否需要无穷等待
if(container.getPushRetryTime()>-1){
if(curRetryTime >= container.getPushRetryTime()){
throw new Exception("容器已满,请稍候再试!");
}else{
curRetryTime++;
}
}
//等待片刻
Thread.sleep(container.getPushWaitTime());
waitForPush(container,curRetryTime,data);
}
}
XMLUtil.java
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
/**
* 本类主要实现对xml文件的解析
* @author hp
*
*/
public class XMLUtil {
/**
* 根据制定的配置文件xml构建一棵DOM数,并返回改树的根节点
* @param filePath
* @return
* @throws Exception
* @author
*/
public static Element getDOMTree(String filePath)throws Exception {
//取得DOM树
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(filePath);
Element root = doc.getDocumentElement();
return root;
}
/**
* 取得已知节点某属性的值
* @param Element
* @param String
* @return
* @author
*/
public static String getAttributeOfElement(Element e,String type){
return e.getAttribute(type);
}
/**
* 本方法只适用于每个标记中只有一个相同类型的子标记的情况,直接读取其文本值
* @param parent 父标记
* @param childType 子标记值
* @return
* @author
*/
public static String getTextValueOfElement(Element parent,String childType){
NodeList childList = parent.getElementsByTagName(childType);
Element curElement = (Element) childList.item(0);
String childValue ;
//这里主要进行处理,保证能够独到数据,如果读不到数据,则赋值为空
try{
childValue = curElement.getFirstChild().getNodeValue().toString();
}catch(NullPointerException n){
childValue = "";
}
return childValue;
}
}
TaoZhi.java
import java.util.Hashtable;
import java.util.Map;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import util.XMLUtil;
import container.Container;
public class TaoZhi {
Map<String,Container> containerList = new Hashtable<String,Container>();
/**
* 对配置文件的解析方法,并生成相应的容器实例
* @param configFilePath
* @param containerType
* @throws Exception
* @author
*/
public void parse(String configFilePath,String containerType) throws Exception{
//得到DOM树的根节点
Element root = XMLUtil.getDOMTree(configFilePath);
//得到子节点
NodeList containerTypeList = root.getElementsByTagName(containerType);
//遍历该节点列表,为不同ID的节点进行实例化操作
for(int i = 0 ; i< containerTypeList.getLength() ; i++ ){
Element curElement = (Element)containerTypeList.item( i );
//得到该节点的ID
String id = curElement.getAttribute("id");
//String id = XMLUtil.getAttributeOfElement(curElement, "id");
//取得该节点下各个子节点的值
int containerSize = Integer.valueOf( XMLUtil.getTextValueOfElement(curElement, "containerSize"));
int popRetryTime = Integer.valueOf( XMLUtil.getTextValueOfElement(curElement, "popRetryTime"));
int popWaitTime = Integer.valueOf( XMLUtil.getTextValueOfElement(curElement, "popWaitTime"));
int pushRetryTime = Integer.valueOf( XMLUtil.getTextValueOfElement(curElement, "pushRetryTime"));
int pushWaitTime = Integer.valueOf( XMLUtil.getTextValueOfElement(curElement, "pushWaitTime"));
Container curContainer = new Container(containerSize,popRetryTime,popWaitTime,pushRetryTime,pushWaitTime,containerType);
//下面的判断表示,如果存在重复的ID则不能使用
if(containerList.get(id) == null && curContainer !=null){
containerList.put(id, curContainer);
}else{
System.out.println("不能存在重复的ID或者配置文件设置有误,请修改配置文件");
}
}
}
/**
* 构造器,实现对配置文件的解析,将生成的容器加入到容器列表
* @param configFilePath
* @throws Exception
* @author
*/
public TaoZhi(String configFilePath) throws Exception{
//解析配置文件,并开始构造对象实例
this.parse(configFilePath,"stack");
this.parse(configFilePath,"queue");
this.parse(configFilePath,"random");
}
/**
* 获取数据
* @param ID 要获取数据的容器的id号
* @return 返回获取的数据
* @throws Exception 如果找不到数据,抛出异常
* @author
*/
public Object pop(String ID) throws Exception{
Object data;
Container curContainer = this.containerList.get(ID);
if( curContainer == null){
throw new Exception("您要取数据的容器不存在!请重新设定ID号!");
}else{
data = curContainer.pop();
}
return data;
}
/**
* 往容器插入数据
* @param ID 要插入的容器号
* @param data 要插入的数据
* @throws Exception
* @author
*/
public void push(String ID,Object data)throws Exception{
Container curContainer = this.containerList.get(ID);
if( curContainer == null){
throw new Exception("您要插入的容器不存在!请重新设定ID号!");
}else{
curContainer.push(data);
}
}
/**
* @param args
*/
public static void main(String[] args) throws Exception{
TaoZhi tz = new TaoZhi("./config.xml");
tz.push("1", 1);
tz.push("1", 2);
tz.push("1", 3);
System.out.println(tz.pop("1"));
System.out.println(tz.pop("5"));
System.out.println(tz.pop("1"));
}
}
上午 Servlet 中的Filter & Listener…
Servlet监听器
在web应用中响应特定对象的特定事件,这样就比较方便的控制application,session,request对象发生的特定事件,实现对特定事件的集中处理。
Servlet监听器用于监听一些重要事件的发生,监听器对象可以在事情发生前、发生后可以做一些必要的处理。
分类及介绍:(红色表示重要)
1、ServletContextListener:用于监听WEB 应用启动和销毁的事件,监听器类需要实现javax.servlet.ServletContextListener 接口。
这个其实就是对于application应用对象。
2. ServletContextAttributeListener:用于监听WEB应用属性改变的事件,包括:增加属性、删除属性、修改属性,监听器类需要实现javax.servlet.ServletContextAttributeListener接口。
3. HttpSessionListener:用于监听Session对象的创建和销毁,监听器类需要实现javax.servlet.http.HttpSessionListener接口或者javax.servlet.http.HttpSessionActivationListener接口,或者两个都实现。
配置文件如下:
<listener> <listener-class>类名</ listener-class ></ listener >
4. HttpSessionActivationListener:用于监听Session对象的钝化/活化事件,监听器类需要实现javax.servlet.http.HttpSessionListener接口或者javax.servlet.http.HttpSessionActivationListener接口,或者两个都实现。
5. HttpSessionAttributeListener:用于监听Session对象属性的改变事件,监听器类需要实现javax.servlet.http.HttpSessionAttributeListener接口。该接口要实现的方法,和对于的触发事件如下:
统计在线人数的时候应该用实现HttpSessionListener接口,也就是当一个用户来到是,实现创建一个session对象,从而计数一次。而上面的触发事件是不同的,表示一个Attribute增加一个就触发一次。
部署:
监听器的部署在web.xml文件中配置
过滤器
1.1 什么是过滤器
过滤器是一个程序,它先于与之相关的servlet或JSP页面运行在服务器上。过滤器可附加到一个或多个servlet或JSP页面上,并且可以检查进入这些资源的请求信息。在这之后,过滤器可以作如下的选择:
①以常规的方式调用资源(即,调用servlet或JSP页面)。
②利用修改过的请求信息调用资源。
③调用资源,但在发送响应到客户机前对其进行修改。
④阻止该资源调用,代之以转到其他的资源,返回一个特定的状态代码或生成替换输出。
1.2 Servlet过滤器的基本原理
在Servlet作为过滤器使用时,它可以对客户的请求进行处理。处理完成后,它会交给下一个过滤器处理,这样,客户的请求在过滤链里逐个处理,直到请求发送到目标为止。例如,某网站里有提交“修改的注册信息”的网页,当用户填写完修改信息并提交后,服务器在进行处理时需要做两项工作:判断客户端的会话是否有效;对提交的数据进行统一编码。这两项工作可以在由两个过滤器组成的过滤链里进行处理。当过滤器处理成功后,把提交的数据发送到最终目标;如果过滤器处理不成功,将把视图派发到指定的错误页面。
2.Servlet过滤器开发步骤
开发Servlet过滤器的步骤如下:
①编写实现Filter接口的Servlet类。
②在web.xml中配置Filter。
上面中的/*表示对所有的信息过滤。
开发一个过滤器需要实现Filter接口,Filter接口定义了以下方法:
①destory()由Web容器调用,初始化此Filter。
②init(FilterConfig filterConfig)由Web容器调用,初始化此Filter。
③doFilter(ServletRequest request,ServletResponse response,FilterChain chain)具体过滤处理代码。
FilterChain 的作用是:FilterChain是servlet容器提供给开发者的一个对象,用于资源请求调用的一个链表(可以参考CoR模式)! 过滤器使用FilterChain(过滤器链表)来调用链表里的下一个过滤器!调用完链表里最后一个过滤器以后,再继续调用其它的资源。 doFilter:(没有返回值) 如果过滤器链表里没有其它过滤器的话,这个过滤链的调用就会转到其它资源的调用。 FilterChain是由容器来管理的!
也是就是说多个过滤器会形成一个链结构,且就是通过这个FilterChain来实现转发嘚。
常用:权限管理,字符过滤等等
配置tomcat:
Tomcat有zip包和exe版,本配置针对非安装zip包使用:
1 在myEclipse中加载Tomcat
2 选择tomcat的安装路径,并选择服务器Enable此时会在myEclipse中多一个图标
3选择tomcat对于的jdk
4 启动Tomcat
5 添加一个J2EE的配置工程
每次修改web.xml后重新配置tomcat
Web-inf 站点内容 web.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
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-app_2_5.xsd">
<servlet>
<!-- name写的只自己命名的一个servlet,可以不是那个servlet类名 -->
<servlet-name>MyServlet</servlet-name>
<!-- servletd类名,注意加上完整的包名 -->
<servlet-class>ServletDemo</servlet-class>
</servlet>
<servlet-mapping>
<!-- name写的只自己命名的一个servlet,可以不是那个servlet类名 ,注意与上面的要一致-->
<servlet-name>MyServlet</servlet-name>
<!--这是一个虚拟路径 -->
<url-pattern>/Servlet/web</url-pattern>
</servlet-mapping>
<welcome-file-list>
<!-- 这里放的是页面html,包括具体的路径,这个顺序是文件在-->
<!-- 当用http://127.0.0.1:8080/html(html是该项目名称)打开时 -->
<!-- 将会出现下面的第一个html的界面 -->
<welcome-file>right.html</welcome-file>
<welcome-file>Form.html</welcome-file>
</welcome-file-list>
</web-app>
Lib:存放所以的包文件
Class存放所有的类文件
配置tomcat环境,启动在bin,配置在config
Servlet做好配置,本身是一个基本java类,只有再继承了httpservlet才能称为servlet,这样才有可能响应页面的请求(比如接受页面数据)
Response可以想象为通向页面的一个socket,可以通过其方法获得一些IO流
Servlet中访问报头
HTTP报头,提交请求和服务器向客户端做出响应时 ,浏览器和服务器都会再请求和响应后自动添加的一些附加信息,这些附加信息称之为报头,这些都是浏览器自动附加上去的,用户并不知道!
报头分类
请求报头
应用:反爬虫系统:首先查看报头信息,比如User-Agent(请求的浏览器或者其他客户程序),如果能够识别某些报头那么则是正常的浏览器访问,否则就是爬虫来获得信息,予以制止。
应用:国际化使用:对于不同的范围浏览器给予不同的反映页面,这是可以获得accept-lanugae,通过判断这个语言从而给于不同的反映。
响应报头
如何设置编码和解码格式;request.setcharactset()…..
CGI变量
它是传统的CGI编程中常用的,汇集了各种信息,如来自于HTTP命令和请求头,Socket本身等的信息。
Request.get…( )方法
Servlet生命周期(servlet是单例的,并且是多线程并发)
第一次被访问时:
产生实例(调用构造函数)
初始化(调用init函数)
然后自动调用service()方法,并去执行doget或者dopost方法
我们可以重写这些方法,已获得自己的一些效果。。。。。这些方法都由tomcat自动调用。。。。
以后被访问时:
以后同一个实例启动多个线程执行用户操作(首先调用service函数,然后由service函数根据请
求类型决定调用doGet函数或doPost函数)
这时多个并发线程共享servelet的成员变量,因此对于这样的数据注意使用线程锁。
站台被重新部署等时候,调用destroy函数或者Tomcat关机的时候关闭
配套的HTML文件
JSP
Jsp机制
所有JSP页面,在执行的时候都会被服务器端的JSP引擎转换为Servelet(.java),然后又由JSP引擎调用Java编译器,将Servelet(.java)编译为Class文件(.class),并由Java虚拟机(JVM)解释执行。同时在%CATALINA_HOME%\work\Catalina\localhost下多出两个文件:_Test_jsp.java和_Test_jsp.class,他们分别就是Servelet和Class文件。
然后由Servlet产生HTML页面传回客户端以供显示
在D:\tomcat6\work\Catalina\localhost路径下可以看到被tomcat解释的java文件
JSP组成:
声明:
<%! %>中间的部分。
这里申明的变量,将成为Jsp生成的对应的类的成员变量
这里申明的函数,将成为Jsp生成的对应的类的成员函数
JSP执行
<% %>中间的部分。
这里的代码会在Jsp页面显示的同时被执行,如同写在main函数里的代码一样。
JSP表达式
<%= %>中间的部分
取得某个变量的值。
在页面显示部分直接使用表达式,即为直接显示某个变量的值。
JSP注释
两种注释方式:
<%-- 客户端的源码看 不 见我 --%>
<!-- 客户端的源码看 得 见我 -->
俗称:在Html里写Java代码
<%@ page language="java" import="java.util.Date" pageEncoding="utf-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
</head>
<body>
<%-- 这是JSP注释 ,好像不能嵌套啊! --%>
<%-- 这时JSP申明部分 --%>
<%!
String myDate = null;
String path = null;
String basePath = null;
void getDate(){
Date my = new Date();
this.myDate = my.toLocaleString();
}
%>
<%--这是JSP执行部分 --%>
<%
this.getDate();
%>
欢迎光临,今天是:<%= this.myDate %><br>
</body>
</html>
在IE上直接运行:http://127.0.0.1:8080/项目名/**.jsp即可
08.12.23 JSP高级应用 Jsp和Servlet联合应用 web高级应用
JSP高级应用
Jsp指令-page
<%@ page import="java.util.*" %>
<%@ page session=”false" %>
<%@ page errorPage=”error.jsp" %>
JSP指令 - page的错误处理方案
解决办法
在可能发生异常的页面添加
<%@ page errorPage="error.jsp" %>
在显示错误信息的页面添加
<%@ page isErrorPage="true" %>
在显示错误信息的页面获取异常
通过JSP的隐含exception直接获得异常(这里的exception是jsp的内置对象)象征着从其他页面传递过来的异常实例。
<%
String e = exception.getMessage();
%>
index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%-- 异常错误重定向 --%>
<%@ page errorPage="./Error.jsp" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'index.jsp' starting page</title>
</head>
<body>
<%!
int i;
int j;
%>
<%
i = 0;
j = 7/i;
%>
</body>
</html>
Error.jsp
<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%>
<%@ page isErrorPage = "true" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'Error.jsp' starting page</title>
</head>
<body>
<%
String msg = exception.getMessage();
%>
</body>
</html>
JSP指令 - include
功能:嵌入外部页面,用来把子页面引入母页面
<%@ include file="head.jsp" %>
应用:一个jsp放框架模板,而其他的jsp放一些具体内容,则可以在框架jsp中用include引入其他的内容jsp即可实现复杂的页面。
<a href = “#”> 这里的#表示当前页面
这样一个页面就由三个人处理,而这三个人都可以分开处理:首先由模板工程师定义模板,由美工通过css来处理,内容由内容工程师自行完成,并通过include指令加载到框架中。
JSP动作 - include
功能:嵌入外部页面,实现的效果和jsp的include指令一致。
<jsp:include flush="true" page="head.jsp" / >
JSP动作 - forward
功能:跳转到其他页面
<jsp:forward page="welcome.jsp" />
使用:目前是一种过期技术,用处不大,在早期使用较多。
JSP动作 - param
功能:在跳转的页面间传递数据
<jsp:forward page="welcome.jsp">
<jsp:param name="user_name" value="Eric"/>
</jsp:forward>
JSTL
引入:一个jsp含有html标签,也有java代码,让谁来维护呢?如果不想增加谁的负担,解决办法是:在jsp页面只实现一些逻辑顺序,并且把java的一些逻辑用类似于xml的标签的形式表达,这样美工易于理解和掌握。
JSP 标准标记库(JSP Standard Tag Library,JSTL)是一个实现 Web 应用程序中常见的通用功能的定制标记库集,这些功能包括迭代和条件判断、数据管理格式化、XML 操作以及数据库访问。
具体而言就是能实现一些java的操作,但是有不出现真正的java代码,而是用一些标签来表示java的操作。
但是目前在表现层又不使用:访问数据库,解析xml这些功能了,放到后面的持久层等。目前已被后面的东东标记库所逐渐替代。
JSTL的意义
为了方便网页设计师,他们即使没有学过Java,也可以轻松处理应用程序数据。
主要功能:
访问存储对象
简化JavaBean的访问方式
对集合的简化访问
简单运算符
条件输出
JSP与Servlet联合
JSP的隐含对象
Request(当前人当前请求的线程)
session(针对某个具体客户使用,所以的线程使用,比如判断某人是否登陆)
exception
Application(针对任何人,任何线程共享使用,比如网站浏览计数)
Page
Out
Out:直接应用在jsp页面中(<% out.();%>),往页面输出数据。
JSP(表现层)与Servlet(控制层)间数据传递
从JSP到Servlet
从JSP发送数据:
通过form提交,一旦一个form被submit则数据自动从jsp传递到Servlet中
在Servlet中接收数据:
String userName = request.getParameter( "userName" );
“userName”为Jsp中form对应的标签的name属性
从Servlet到JSP
要主动的在Servlet中传,要在jsp中主动的去接受数据。
从Servlet发送数据:
// 将数据作为attribute存入request中
request.setAttribute( "user_name", userName );//这里的user_name仅仅是一个标记
// 跳转到指定页面并传递数据
RequestDispatcher rd = request.getRequestDispatcher( "../shu_ju_chuan_di/Welcome.jsp" );
rd.forward( request, response );
这两语句仅仅是进行保存,等全部语句执行完毕后,Servlet就会检查post是否有保存东西和foword东西,如果有就进行重定向,因此在一个forward后面不要再有其他的forward方法了。
再次注意:requset里的保存和重定向得到的数据都是单线程使用的,不能被其他线程共享。如果要实现多个线程中数据的共享需要使用application对象。
在JSP中接收数据:
String userName = ( String )request.getAttribute( "user_name" );
//这个user_name就是前面的setAttribute中的标记。
session
访问范围
当前客户的所有组件
请参照配套登录实例
用同一个浏览器多次访问
用不同浏览其多次访问
HttpSession se = request.getSession();
Se.setAttribute();
application
访问范围
这是一个全局单例共享空间
服务器上所有组件
请参照配套登录实例
用同一个浏览器多次访问
用不同浏览其多次访问
在servlet中用:ServletContext application = this.getServletContext()
在jsp中用application
Web中文显示问题
解决页面显示中文问题
<%@ page language="java" import="java.util.*" pageEncoding=“UTF-8"%>
解决request传递中文问题
request.setCharacterEncoding( "UTF-8" );
在接受数据之前使用上述语句
并且页面表单使用form中的post方法,而不用get方法,使用get时其提交的信息会出现在IE中,需要进行特殊的处理才能正常显示中文。
JSP动态显示table方案
WebDemoServlet.java
import java.io.IOException;
import java.util.Hashtable;
import java.util.Map;
import javax.servlet.RequestDispatcher;
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 WebDemoServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// TODO Auto-generated method stub
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse resp)
throws ServletException, IOException {
// TODO Auto-generated method stub
//准备接受数据,为了实现中文传递,向先定义解码方式
request.setCharacterEncoding("UTF-8");
//如果是发送的话,那么也要设置其字符格式
resp.setCharacterEncoding("UTF-8");
//通过 request.getParameter()方法接受数据,
//下面方法中的"userName"对于表单中的文本框的名字
String userName = request.getParameter("userName");
String passWord = request.getParameter("passWord");
//以上就是从jsp中得到的各个数据,可以直接打印处理
System.out.println(userName + "-" + passWord);
//下面的部分实现将从Jsp读来的数据发送到另外一个Jsp页面中去
//第一步:将数据作为attribute存入request中
//下面的语句表示将userName保存在代号为USER_NAME的requset中
request.setAttribute("USER_NAME", userName);
request.setAttribute("PASSWORD", passWord);
//下面练习关于session的使用,使用范围是当前客户的所有组件,这是系统通过
//关于http报头和CGI变量来识别的
HttpSession hs = request.getSession();
//下面这句话和requset类似,就是把username保存到一个session里面,这个
//session的名字是"USER_NAME_SESSION",这样在其他的jsp里面就可以用到这个session的值了
//似乎这种数据的保存方式有点像Map
hs.setAttribute("USER_NAME_SESSION", userName);
//下面是关于全局变量application的使用
//因为用到的是全局变量,因此用到this,这里也不是直接说applicaton,而是context
ServletContext sc = this.getServletContext();
//这里的count用来计数,并且表面值为0
sc.setAttribute("COUNT", 0);
//下面演示动态table的形成,其实这表达了jsp编程的灵活性,
//对此的理解关键是要知道jsp的机制,其是被tomcat翻译成一个Servlet,
Map<String,Integer> list = new Hashtable<String,Integer>();
list.put("zheng", 25);
list.put("zhu", 25);
list.put("ma", 26);
//将这个数据用reques传递到jsp中去
request.setAttribute("LIST", list);
//采用request进行数据传递的时候一定要把他放到跳转的页面的前面。跳转到哪里,就到哪里去接受!
//第二步:跳转到指定页面并传递数据,制定转到当前路径的reslult.jsp文件中
//注意在使用相对路径的时候,这里的相对指得是Servlet与要转向的文件之间的相对性
RequestDispatcher rd = request.getRequestDispatcher("../Result.jsp");
rd.forward(request, resp);
}
}
index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<!-- 下面通过表单实现从Jsp向Servlet进行数据传递,主要是通过request -->
<!-- 当选择submit时,自动的将表单的各个数据向Servlet发送 -->
<h2 >用户登陆</h2>
<form action = "./Servlet/web" method = "post">
请输入用户名:
<input type = "text" name ="userName" ><br>
请输入密码:
<input type = "password" name ="passWord" ><br><br><br>
<input type = "submit" value = 确认>
<input type = "reset" value = 重写>
</form>
</body>
</html>
Result.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'Result.jsp' starting page</title>
</head>
<body>
<%!
String userName;
int count;
%>
<%
userName = (String)request.getAttribute("USER_NAME");
String passWord = (String)request.getAttribute("PASSWORD");
%>
用户名为:<%= userName %><br><!-- 这是jsp表达式 -->
密码为:<% out.print(passWord); %><!-- 这是jsp的执行部分 -->
采用session的方式得到用户名为:<br>
<%
userName = (String)session.getAttribute("USER_NAME_SESSION");
out.println(userName);
%>
<%
count =(Integer) application.getAttribute("COUNT");
count++;
out.println("您是第" +count +"人访问该网站");
application.setAttribute("COUNT",count);
%>
<br>
下面的部分接受Servlet传来的数据,并进行动态的表格打印
<table border = 1>
<tr>
<th>姓名</th>
<th>年龄</th>
</tr>
<%
Hashtable<String,Integer> list =(Hashtable<String,Integer>) request.getAttribute("LIST");
Set<String > nameSet = list.keySet();
for(String name:nameSet){
int age = list.get(name);
%>
<tr>
<td>
<%= name %>
</td>
<td>
<%= age %>
</td>
</tr>
<%
}
%>
</table>
</body>
</html>
SessionTest.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'SessionTest.jsp' starting page</title>
</head>
<body>
<%!
String userName;
int count;
%>
<%
userName = (String )session.getAttribute("USER_NAME_SESSION");
out.println("这是第二个浏览器访问的情况,但是可以用同一个session<br>");
out.println("用户名为:" + userName);
%>
<br>
<%
count =(Integer) application.getAttribute("COUNT");
count++;
out.println("您是第" +count +"人访问该网站");
application.setAttribute("COUNT",count);
%>
</body>
</html>
堆栈和队列容器的实现
容器 保存(堆栈,队列),最大长度,为空(等待再来拿,类似池的概念),多个堆栈,多个队列
类加载: 第一:如果要new一个子类,则JVM会先new一个父类(调用其默认构造器)。
第二:如果父类没有默认构造器(无参构造器)那么子类必须明确的用super来指明调用父类的那个构造器。
注意系统的结构良好性:可重用!,可读性好!(利用继承和多态减少代码的重复)
项目实施过程:功能(一期工程),安全(二期工程),性能(三期工程)
内核(关键的东西)+外壳(相当于一个工厂):这样可以降低模块之间的耦合度,提高模块的独立性,可以任意修改内核的东西,而不会影响外壳的东西。
Container.java
package container;
/**
* 这是一个容器类的父类,该容器主要是为了实现队列,堆栈等存储方式
* @author
*
*/
import java.util.List;
import java.util.Vector;
import util.DataManager;
public class Container{
//容器的最大容量
protected int containerSize;
//当存入数据时的最大尝试次数
protected int popRetryTime;
//当存入数据时的每次尝试等待时间
protected int popWaitTime;
//当读数据时的最大尝试次数
protected int pushRetryTime;
//当读数据时的每次尝试等待时间
protected int pushWaitTime;
private String curContainerType;
//这里用了Vector主要是考虑线程安全的问题
public List dataList = new Vector();
//构造函数,因为后面的队列和堆栈都要传递参数,因此写在父类的构造器里面
//以免代码重复
public Container(int containerSize,int popRetryTime,int popWaitTime,int pushRetryTime,int pushWaitTime,String containerType){
this.containerSize = containerSize;
this.popRetryTime = popRetryTime;
this.popWaitTime = popWaitTime;
this.pushRetryTime = pushRetryTime;
this.pushWaitTime = pushWaitTime;
this.curContainerType = containerType;
}
/**
* 读取数据的方法 ,并且根据不同的容器类型,采用不同的读方法
* @return
* @throws Exception
*/
public Object pop()throws Exception {
Object data =null ;
data = DataManager.waitForPop(this,0);
return data;
}
/**
* 插入数据方法
* @author
*/
public void push(Object data)throws Exception {
// TODO Auto-generated method stub
DataManager.waitForPush(this, 0, data);
}
public int getLength(){
return dataList.size();
}
/**
* 判断容器是否为空
* @return 如果为空则返回true,否则返回false
* @author
*/
public boolean isEmpty(){
int length = dataList.size();
if (length <= 0){
return true;
}
return false;
}
/**
* 判断容器是否为满,
* @return 如果为满则返回true,否则返回false
* @author
*/
public boolean isFull(){
if(this.containerSize ==-1){
return false;
}
if(this.containerSize <= this.dataList.size()){
return true;
}
return false;
}
public int getPopRetryTime() {
return popRetryTime;
}
public int getPopWaitTime() {
return popWaitTime;
}
public int getPushRetryTime() {
return pushRetryTime;
}
public int getPushWaitTime() {
return pushWaitTime;
}
public String getCurContainerType() {
return curContainerType;
}
}
DataManager.java
/**
*
* 这是一个工具类,主要实现了对容器中的数据插入和获取操作,
* 其关键点在于能够根据用户的需要进行等待或不等待
* @author
*
*/
import container.Container;
public class DataManager {
/**
* 等待获取数据方法,
* @param container 待获取的容器
* @param ct 要获取的容器的类型
* @param curRetryTime 当前尝试获取的次数
* @return 返回的获取数据
* @throws Exception 不能获取时抛出异常
* @author
*/
public static Object waitForPop (Container container,int curRetryTime) throws Exception {
Object data;
int indexData = 0;
//不为空的话直接取值
if(!container.isEmpty()){
if(container.getCurContainerType().equals("stack")){
indexData = container.getLength()-1;
}else if(container.getCurContainerType().equals("queue")){
indexData = 0;
}else if(container.getCurContainerType().equals("random")){
indexData = (int)(Math.random()*container.getLength());
}
data = container.dataList.get(indexData);
container.dataList.remove(indexData);
return data;
}
//为空的话,等待,再测试是否能够拿到,并且要判断是否需要无穷等待
if(container.getPopRetryTime()>-1){
if(curRetryTime >= container.getPopRetryTime()){
throw new Exception("容器为空,请稍候再试!");
}else{
curRetryTime++;
}
}
Thread.sleep(container.getPopWaitTime());
return waitForPop (container,curRetryTime);
}
/**
* 插入数据的方法
* @param container 待插入的容器
* @param curRetryTime 以尝试插入的次数
* @param data 待插入的数据
* @throws Exception 不能插入时抛出异常
* @author
*/
public static void waitForPush(Container container,int curRetryTime,Object data)throws Exception{
//判断容器是否已满,如果不满的话则直接添加进去
if(!container.isFull()){
container.dataList.add(data);
return ;
}
//如果容器满的话,等待,再测试是否能够插入,并且要判断是否需要无穷等待
if(container.getPushRetryTime()>-1){
if(curRetryTime >= container.getPushRetryTime()){
throw new Exception("容器已满,请稍候再试!");
}else{
curRetryTime++;
}
}
//等待片刻
Thread.sleep(container.getPushWaitTime());
waitForPush(container,curRetryTime,data);
}
}
XMLUtil.java
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
/**
* 本类主要实现对xml文件的解析
* @author hp
*
*/
public class XMLUtil {
/**
* 根据制定的配置文件xml构建一棵DOM数,并返回改树的根节点
* @param filePath
* @return
* @throws Exception
* @author
*/
public static Element getDOMTree(String filePath)throws Exception {
//取得DOM树
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(filePath);
Element root = doc.getDocumentElement();
return root;
}
/**
* 取得已知节点某属性的值
* @param Element
* @param String
* @return
* @author
*/
public static String getAttributeOfElement(Element e,String type){
return e.getAttribute(type);
}
/**
* 本方法只适用于每个标记中只有一个相同类型的子标记的情况,直接读取其文本值
* @param parent 父标记
* @param childType 子标记值
* @return
* @author
*/
public static String getTextValueOfElement(Element parent,String childType){
NodeList childList = parent.getElementsByTagName(childType);
Element curElement = (Element) childList.item(0);
String childValue ;
//这里主要进行处理,保证能够独到数据,如果读不到数据,则赋值为空
try{
childValue = curElement.getFirstChild().getNodeValue().toString();
}catch(NullPointerException n){
childValue = "";
}
return childValue;
}
}
TaoZhi.java
import java.util.Hashtable;
import java.util.Map;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import util.XMLUtil;
import container.Container;
public class TaoZhi {
Map<String,Container> containerList = new Hashtable<String,Container>();
/**
* 对配置文件的解析方法,并生成相应的容器实例
* @param configFilePath
* @param containerType
* @throws Exception
* @author
*/
public void parse(String configFilePath,String containerType) throws Exception{
//得到DOM树的根节点
Element root = XMLUtil.getDOMTree(configFilePath);
//得到子节点
NodeList containerTypeList = root.getElementsByTagName(containerType);
//遍历该节点列表,为不同ID的节点进行实例化操作
for(int i = 0 ; i< containerTypeList.getLength() ; i++ ){
Element curElement = (Element)containerTypeList.item( i );
//得到该节点的ID
String id = curElement.getAttribute("id");
//String id = XMLUtil.getAttributeOfElement(curElement, "id");
//取得该节点下各个子节点的值
int containerSize = Integer.valueOf( XMLUtil.getTextValueOfElement(curElement, "containerSize"));
int popRetryTime = Integer.valueOf( XMLUtil.getTextValueOfElement(curElement, "popRetryTime"));
int popWaitTime = Integer.valueOf( XMLUtil.getTextValueOfElement(curElement, "popWaitTime"));
int pushRetryTime = Integer.valueOf( XMLUtil.getTextValueOfElement(curElement, "pushRetryTime"));
int pushWaitTime = Integer.valueOf( XMLUtil.getTextValueOfElement(curElement, "pushWaitTime"));
Container curContainer = new Container(containerSize,popRetryTime,popWaitTime,pushRetryTime,pushWaitTime,containerType);
//下面的判断表示,如果存在重复的ID则不能使用
if(containerList.get(id) == null && curContainer !=null){
containerList.put(id, curContainer);
}else{
System.out.println("不能存在重复的ID或者配置文件设置有误,请修改配置文件");
}
}
}
/**
* 构造器,实现对配置文件的解析,将生成的容器加入到容器列表
* @param configFilePath
* @throws Exception
* @author
*/
public TaoZhi(String configFilePath) throws Exception{
//解析配置文件,并开始构造对象实例
this.parse(configFilePath,"stack");
this.parse(configFilePath,"queue");
this.parse(configFilePath,"random");
}
/**
* 获取数据
* @param ID 要获取数据的容器的id号
* @return 返回获取的数据
* @throws Exception 如果找不到数据,抛出异常
* @author
*/
public Object pop(String ID) throws Exception{
Object data;
Container curContainer = this.containerList.get(ID);
if( curContainer == null){
throw new Exception("您要取数据的容器不存在!请重新设定ID号!");
}else{
data = curContainer.pop();
}
return data;
}
/**
* 往容器插入数据
* @param ID 要插入的容器号
* @param data 要插入的数据
* @throws Exception
* @author
*/
public void push(String ID,Object data)throws Exception{
Container curContainer = this.containerList.get(ID);
if( curContainer == null){
throw new Exception("您要插入的容器不存在!请重新设定ID号!");
}else{
curContainer.push(data);
}
}
/**
* @param args
*/
public static void main(String[] args) throws Exception{
TaoZhi tz = new TaoZhi("./config.xml");
tz.push("1", 1);
tz.push("1", 2);
tz.push("1", 3);
System.out.println(tz.pop("1"));
System.out.println(tz.pop("5"));
System.out.println(tz.pop("1"));
}
}
上午 Servlet 中的Filter & Listener…
Servlet监听器
在web应用中响应特定对象的特定事件,这样就比较方便的控制application,session,request对象发生的特定事件,实现对特定事件的集中处理。
Servlet监听器用于监听一些重要事件的发生,监听器对象可以在事情发生前、发生后可以做一些必要的处理。
分类及介绍:(红色表示重要)
1、ServletContextListener:用于监听WEB 应用启动和销毁的事件,监听器类需要实现javax.servlet.ServletContextListener 接口。
这个其实就是对于application应用对象。
2. ServletContextAttributeListener:用于监听WEB应用属性改变的事件,包括:增加属性、删除属性、修改属性,监听器类需要实现javax.servlet.ServletContextAttributeListener接口。
3. HttpSessionListener:用于监听Session对象的创建和销毁,监听器类需要实现javax.servlet.http.HttpSessionListener接口或者javax.servlet.http.HttpSessionActivationListener接口,或者两个都实现。
配置文件如下:
<listener> <listener-class>类名</ listener-class ></ listener >
4. HttpSessionActivationListener:用于监听Session对象的钝化/活化事件,监听器类需要实现javax.servlet.http.HttpSessionListener接口或者javax.servlet.http.HttpSessionActivationListener接口,或者两个都实现。
5. HttpSessionAttributeListener:用于监听Session对象属性的改变事件,监听器类需要实现javax.servlet.http.HttpSessionAttributeListener接口。该接口要实现的方法,和对于的触发事件如下:
统计在线人数的时候应该用实现HttpSessionListener接口,也就是当一个用户来到是,实现创建一个session对象,从而计数一次。而上面的触发事件是不同的,表示一个Attribute增加一个就触发一次。
部署:
监听器的部署在web.xml文件中配置
过滤器
1.1 什么是过滤器
过滤器是一个程序,它先于与之相关的servlet或JSP页面运行在服务器上。过滤器可附加到一个或多个servlet或JSP页面上,并且可以检查进入这些资源的请求信息。在这之后,过滤器可以作如下的选择:
①以常规的方式调用资源(即,调用servlet或JSP页面)。
②利用修改过的请求信息调用资源。
③调用资源,但在发送响应到客户机前对其进行修改。
④阻止该资源调用,代之以转到其他的资源,返回一个特定的状态代码或生成替换输出。
1.2 Servlet过滤器的基本原理
在Servlet作为过滤器使用时,它可以对客户的请求进行处理。处理完成后,它会交给下一个过滤器处理,这样,客户的请求在过滤链里逐个处理,直到请求发送到目标为止。例如,某网站里有提交“修改的注册信息”的网页,当用户填写完修改信息并提交后,服务器在进行处理时需要做两项工作:判断客户端的会话是否有效;对提交的数据进行统一编码。这两项工作可以在由两个过滤器组成的过滤链里进行处理。当过滤器处理成功后,把提交的数据发送到最终目标;如果过滤器处理不成功,将把视图派发到指定的错误页面。
2.Servlet过滤器开发步骤
开发Servlet过滤器的步骤如下:
①编写实现Filter接口的Servlet类。
②在web.xml中配置Filter。
上面中的/*表示对所有的信息过滤。
开发一个过滤器需要实现Filter接口,Filter接口定义了以下方法:
①destory()由Web容器调用,初始化此Filter。
②init(FilterConfig filterConfig)由Web容器调用,初始化此Filter。
③doFilter(ServletRequest request,ServletResponse response,FilterChain chain)具体过滤处理代码。
FilterChain 的作用是:FilterChain是servlet容器提供给开发者的一个对象,用于资源请求调用的一个链表(可以参考CoR模式)! 过滤器使用FilterChain(过滤器链表)来调用链表里的下一个过滤器!调用完链表里最后一个过滤器以后,再继续调用其它的资源。 doFilter:(没有返回值) 如果过滤器链表里没有其它过滤器的话,这个过滤链的调用就会转到其它资源的调用。 FilterChain是由容器来管理的!
也是就是说多个过滤器会形成一个链结构,且就是通过这个FilterChain来实现转发嘚。
常用:权限管理,字符过滤等等
发表评论
-
Cookie跨域 cas
2011-10-27 17:30 1726正常的cookie只能在一个应用中共享,即一个cookie只能 ... -
JQuery中$.ajax()方法参数详解
2011-05-25 13:05 1661url: 要求为String类型的参数,(默认为当前页地址)发 ... -
jquery刷新页面
2011-04-27 23:51 961jquery刷新页面 局部刷新: 这个方法就多了去了,常见 ... -
spring MVC
2011-04-27 23:50 1519需要的JAR包有: spring2.jar cglib-nod ... -
Java hascode
2011-04-10 17:47 823java hascode Java中有两类集合(Colle ... -
spring原理
2011-04-10 00:03 8311、spring原理 s ... -
hibernate的缓存
2011-03-31 14:34 858缓存是介于应用程序和 ... -
Spring AOP之Hello World
2011-03-30 11:36 1012我们使用一个简单的例子来演示一下Spring中的AOP,这是一 ... -
数字推理题规律汇总
2011-03-29 16:48 1044□ 等差数列及其变式 【例题1】2,5,8,() A ... -
freemarker的模板标签获取
2011-03-28 13:23 1742In FreeMarker 2.2, Template has ... -
StringUtils函数全集
2011-01-13 16:45 1291StringUtils函数全集 Strin ... -
jquery+json+servlet
2011-01-11 13:54 5350jquery+json小例子 使用jquery发送请求到s ... -
java - 删除文件
2010-12-30 13:32 1116java删除文件 package IO.file; impo ... -
jquery 赋值函数
2010-12-28 11:14 886$("")是一个jquery对象,而不是一 ... -
jQuery的鼠标事件
2010-12-28 11:13 1946鼠标事件是在用户移动鼠标光标或者使用任意鼠标键点击时触发的。 ... -
获取鼠标在图片对象上的位置
2010-12-27 21:40 1198<!DOCTYPE HTML PUBLIC " ... -
window.opener 与 window.parent 的区别
2010-11-21 22:57 1029我们如果要用到iframe的值传到另一框架就要用到 windo ... -
几个常用代码在IE8和火狐下的对比
2010-11-19 14:44 9781、Input 有的浏览 ... -
window.open()运用
2010-11-18 17:24 1036window.open()支持环境: JavaScript1. ... -
java 环境变量
2010-05-06 10:34 2508电脑属性高级 > 环境变量 > 系统变量 > ...
相关推荐
当你遇到`java.lang.NoClassDefFoundError: javax/servlet/jsp/jstl/core/ConditionalTagSupport`这样的异常时,意味着在运行时系统找不到这个类,这通常是由于缺少JSTL相关的依赖或者配置不正确所导致的。...
在IT行业中,Servlet和JSP(JavaServer Pages)是用于构建动态Web应用程序的关键技术,尤其在企业级应用开发中占据重要地位。孙鑫是一位知名的Java技术专家,他的作品常常深入浅出地解析复杂的编程概念。这个名为...
在本文中,我们将深入探讨Servlet和JSP技术,以及如何基于Tomcat服务器进行Web应用程序的开发。Servlet和JSP是Java EE(企业版)平台中用于构建动态网页的关键技术,而Tomcat则是一个广泛使用的开源Java Servlet容器...
【Servlet与JSP技术】 Servlet和JSP是Java Web开发中的核心技术,用于构建动态网站和Web应用程序。Servlet是Java EE规范的一部分,它提供了一种服务器端处理HTTP请求的方法。Servlet是一个Java类,它扩展了服务器的...
Servlet和JSP是Java Web开发中的核心技术,它们用于构建动态Web应用程序。Servlet是Java编程语言中的一个接口,它允许服务器扩展其功能,处理HTTP请求并返回响应。JSP(Java Server Pages)则是一种视图技术,它将...
韩顺平servlet/jsp 知识详尽 重点突出 适合初学者学习 结合韩老师的视频会有非常好的效果
【基于Servlet/JSP的学生信息录入查询系统】 这个项目是一个典型的Web应用程序,主要目的是帮助初学者理解和实践Servlet和JSP在构建动态网站时的作用。Servlet是Java服务器端编程的基础,而JSP则是为了简化HTML和...
5. **Jothi Shankar Kumar**:“我认为自己在拿起《Head First》之前就已经了解了JSP/Servlets,但在阅读这本书之后,我才真正意识到我对它们的理解有多深。我非常欣赏《Head First》系列的写作风格。” 6. **...
Servlet和JSP(JavaServer Pages)是Java Web开发中的核心技术,用于构建动态Web应用程序。它们在Web服务器上运行,提供与客户端(通常是浏览器)交互的能力。JDBC(Java Database Connectivity)则是Java中用来连接...
Servlet/jsp网上书城是一个基于Java Web开发的项目,它运用了Servlet和JSP(JavaServer Pages)技术来构建一个基本的在线购物平台,用于展示、购买书籍并管理订单。这个项目的核心目标是提供一个用户友好的界面,让...
Servlet和JSP是Java Web开发中的核心技术,常用于构建动态网站和企业级应用程序。本项目“Servlet/jsp编写的网上书城”显然是一款基于这两项技术实现的在线图书销售平台。接下来,我们将深入探讨Servlet、JSP以及...
【Servlet和JSP入门教程】 本教程主要针对的是Servlet 2.4和JSP 2.0,这两个技术是构建Java Web应用的关键组件。Servlet是一种Java编程接口,用于扩展服务器的功能,而JSP(JavaServer Pages)则是一种动态网页技术...
java.lang.NoClassDefFoundError: javax/servlet/jsp/jstl/core/ConditionalTagSupport 问题-附件资源
该功能可以对所有人发言,也可以单独对某一个人发言。运用到的技术servlet/jsp.
javax/servlet/jsp/resources/web-jsptaglibrary_1_2.dtd javax/servlet/jsp/resources/web-jsptaglibrary_2_0.xsd javax/servlet/jsp/resources/jspxml.dtd javax/servlet/jsp/resources/jsp_2_0.xsd javax/servlet...
Servlet和JSP(JavaServer Pages)是Java Web开发中的核心技术,它们构成了Web应用程序的基础。在Java API中,Servlet和JSP API提供了处理HTTP请求、动态生成响应内容以及与数据库交互的能力。这篇详述将深入解析这...
**JSP(Java Server Pages)与Servlet是Java Web开发中的两个关键组件,它们共同构建了动态Web应用程序的基础。** **JSP技术:** JSP是一种服务器端的技术,它允许开发者在HTML页面中嵌入Java代码,以实现动态内容...
本教程通过"jsp-servlet-javaBean.zip"压缩包,旨在帮助开发者深入理解并熟练运用Servlet、JSP(JavaServer Pages)以及JavaBean,实现经典的MVC(Model-View-Controller)设计模式。以下将详细介绍这三个核心概念...
在`error.jsp`页面中,开发者可以获取`request`对象中包含的错误信息,如状态码(`javax.servlet.error.status_code`)、错误消息(`javax.servlet.error.message`)和异常类型(`javax.servlet.error.exception_...
### Servlet与JSP深入详解:基于Tomcat的Web开发 #### 一、Servlet技术概述 Servlet是一种用Java编写的服务器端应用程序接口(API),它扩展了Java Web开发的功能。Servlet可以响应HTTP请求,并且能够处理复杂的...