jsp进阶教程和Servlet

在看此教程之前请先去jsp基础部分看基础教程

目录
1、JavaBean
2、jsp自定义标签
3、jstl
4、Servlet
5、过滤器
6、监听器
7、jsp+servlet连接数据库
8、jsp+servlet分页
9、jsp+servlet文件上传

1、JavaBean

1.1什么是JavaBean

JavaBean是一种用Java语言写的可重用组件,可以被Applet、Servlet、JSP进行调用,也可以被可视化开发工具调用,包含属性、方法、事件。

	创建JavaBean的要求
		①属性必须私有化
		②提供无参构造函数
		③私有化的属性的方法修饰符要为public给其他程序方便访问,方法命名遵循规范

1.2、第一个JavaBean

JavaBean的属性可以是任意并且多个类型、 需要对JavaBean提供get(取值)set(设置)方法方便外界访问。


public class UserBean {
     
	
	//属性
	private Integer id;
	private String name;
	private String pwd;
	
	//构造方法
	public UserBean(Integer id, String name, String pwd) {
     
		super();
		this.id = id;
		this.name = name;
		this.pwd = pwd;
	}


	public UserBean() {
     
		super();
		// TODO Auto-generated constructor stub
	}

	//get、set方法
	
	public Integer getId() {
     
		return id;
	}

	public void setId(Integer id) {
     
		this.id = id;
	}

	public String getName() {
     
		return name;
	}

	public void setName(String name) {
     
		this.name = name;
	}

	public String getPwd() {
     
		return pwd;
	}

	public void setPwd(String pwd) {
     
		this.pwd = pwd;
	}
	
}

1.3、在jsp页面使用JavaBean

JSP提供三个关于JavaBean的组件的动作元素,分别是:
:查找、或者实例化一个Bean。
语法
id表示JavaBean的名称,class指的是类的全限定名,scope指的是改Bean的作用域范围默认为page,可以设置为request、session、application。

:设置JavaBean的属性。
语法
name 表示JavaBean的名称 property表示JavaBean实例对象的属性名称,value表示属性的值,param表示将JavaBean的某个属性值设置为请求参数值,会自动转换成要设置的JavaBean属性的类型。
:获得Bean的属性。

实例

<%@page import="java.util.Enumeration"  %>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"  errorPage="enoor.jsp"  %>
<!DOCTYPE html> 
<html>
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>	
		<!--  id表示JavaBean的名称 class:JavaBean的路径 scope:JavanBean的作用范围 -->
		<jsp:useBean id="User" class="com.zhou.UserBean" scope="request" />
		
		<!-- 设置值 -->
		<!-- peoperty:JavaBean对象的属性名 name:JavaBean的id名称 value:JavaBean对象属性的值  -->
		<jsp:setProperty property="id" name="User" value="1001"/>
		<jsp:setProperty property="name" name="User" value="张三"/>
		<jsp:setProperty property="pwd" name="User" value="666666"/>
		<!-- 使用请求参数设置值 接收参数名为names的值 再将值赋值给name  如果 property="*" 代表赋值给所有属性名字-->
		<jsp:setProperty property="name" name="User" param="names"/>
		<form action="">
			<input type="text" name="names" />
			<input type="submit" value="确定"/>
		</form>
		<!-- 取值  property="JavaBean对象的属性名" name="JavaBean对象的id"-->
		<table border="1">
			<tr>
				<th>id</th>
				<th>姓名</th>
				<th>密码</th>
			</tr>
			<tr>
				<td><jsp:getProperty property="id" name="User"/></td>
				<td><jsp:getProperty property="name" name="User"/></td>
				<td><jsp:getProperty property="pwd" name="User"/></td>
			</tr>
		</table>
		
</body>

</html>

运行结果
jsp进阶教程和Servlet_第1张图片

2、jsp自定义标签

jsp自定义标签就是用户自己去定义标签,当jsp页面包含标签会被转换为servlet,然后servlet执行时web容器会去调用相对应标签的操作。

2.1、怎么定义jsp自定义标签

①继承SimpleTagSupport类。

②重写的doTag()方法。

package com.zhou;

import java.io.IOException;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.SimpleTagSupport;

//继承SimpleTag
public class hello extends SimpleTagSupport{
     
	//重写doTag方法
	 public void doTag() throws JspException, IOException {
     
		 	//获得JspContext对象
		 //将out.println("这是一个自定义标签!"); 传递给JspWrite
		    JspWriter out = getJspContext().getOut();
		    out.println("这是一个自定义标签!");
	 }
	 
	 

	

	
}

③在WEB-INF下面创建标签库描述文件


<!-- 创建以.tld结尾的标签库文件 -->

<!-- 定义标签库 -->
<taglib>
	<!-- 标签库的版本 -->
  <tlib-version>1.0</tlib-version>
  	<!-- 依赖的JSP版本 -->
  <jsp-version>2.0</jsp-version>
  	<!-- 当在JSP中使用标签时,此标签库首选或者建议的前缀 -->
  <short-name>Example TLD</short-name>
  <!-- 定义标签 -->
  <tag>
  	<!-- 标签的名字 -->
    <name>hello</name>
    <!-- Java标签处理器类的名称 -->
    <tag-class>com.zhou.hello</tag-class>
    <!-- 标签主体部分的内容 -->
    <body-content>empty</body-content>
  </tag>
</taglib>

④在jsp页面使用标签

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"  errorPage="enoor.jsp"  %>
 <!-- 使用自定义的标签 prefix:标签的前缀 uri:标签的路径 -->
<%@ taglib prefix="dd" uri="/WEB-INF/custom.tld" %>
<!DOCTYPE html> 
<html>
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>	
		<!-- 创建了一个标签名为hello的标签并且前缀为dd -->
		<dd:hello/>
</body>

</html>

运行结果
jsp进阶教程和Servlet_第2张图片

2.2、自定义标签自定义内容

package com.zhou;

import java.io.IOException;
import java.io.StringWriter;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.SimpleTagSupport;

//继承SimpleTag
public class hello extends SimpleTagSupport{
     
	//定义一个StringWriter对象
	 StringWriter sw = new StringWriter();
	//重写doTag方法
	 public void doTag() throws JspException, IOException {
     
		 	//想要输出的信息作为标签体的内容输出	
		    getJspBody().invoke(sw);
		    //调用JspWriter将标签体的内容输出到浏览器
		    getJspContext().getOut().println(sw.toString());
	 }
	 
	 

	

	
}


<!-- 创建以.tld结尾的标签库文件 -->

<!-- 定义标签库 -->
<taglib>
	<!-- 标签库的版本 -->
  <tlib-version>1.0</tlib-version>
  	<!-- 依赖的JSP版本 -->
  <jsp-version>2.0</jsp-version>
  	<!-- 当在JSP中使用标签时,此标签库首选或者建议的前缀 -->
  <short-name>Example TLD</short-name>
  <!-- 定义标签 -->
  <tag>
  	<!-- 标签的名字 -->
    <name>hello</name>
    <!-- Java标签处理器类的名称 -->
    <tag-class>com.zhou.hello</tag-class>
    <!-- 标签主体部分的内容 -->
  <!--   	可以接受文本,EL表达式,和JSP的动作。 -->
    <body-content>scriptless</body-content>
  </tag>
</taglib>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"  errorPage="enoor.jsp"  %>
 <!-- 使用自定义的标签 prefix:标签的前缀 uri:标签的路径 -->
<%@ taglib prefix="dd" uri="/WEB-INF/custom.tld" %>
<!DOCTYPE html> 
<html>
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>	
		<!-- 创建了一个标签名为hello的标签并且前缀为dd -->
		<dd:hello>2132131</dd:hello>
</body>

</html>

结果:2312131

2.3、创建带属性的自定义标签

package com.zhou;

import java.io.IOException;
import java.io.StringWriter;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.SimpleTagSupport;

//继承SimpleTag
public class hello extends SimpleTagSupport{
     
	//定义一个变量
	private String msg;
	//set方法
	public void setMsg(String msg) {
     
		this.msg = msg;
	}
	
	//定义一个StringWriter对象
	 StringWriter sw = new StringWriter();
	//重写doTag方法
	 public void doTag() throws JspException, IOException {
     
		 //如果属性不为空调用JspWriter将标签体的内容输出到浏览器	
		 if(msg!=null) {
     
			  JspWriter out = getJspContext().getOut();
	          out.println( msg );
		 	}else {
     
		 		//想要输出的信息作为标签体的内容输出	
			    getJspBody().invoke(sw);
			    //调用JspWriter将标签体的内容输出到浏览器	
			    getJspContext().getOut().println(sw.toString());
		 	}
		 	
		   
	 }
	 
	 

	

	
}


<!-- 创建以.tld结尾的标签库文件 -->

<!-- 定义标签库 -->
<taglib>
	<!-- 标签库的版本 -->
  <tlib-version>1.0</tlib-version>
  	<!-- 依赖的JSP版本 -->
  <jsp-version>2.0</jsp-version>
  	<!-- 当在JSP中使用标签时,此标签库首选或者建议的前缀 -->
  <short-name>Example TLD</short-name>
  <!-- 定义标签 -->
  <tag>
  	<!-- 标签的名字 -->
    <name>hello</name>
    <!-- Java标签处理器类的名称 -->
    <tag-class>com.zhou.hello</tag-class>
    <!-- 标签主体部分的内容 -->
  <!--   	可以接受文本,EL表达式,和JSP的动作。 -->
    <body-content>scriptless</body-content>
    		<!-- 义多个,定义Tag的属性 -->
    <attribute>
    	<!-- 属性的名字 -->
    	<name>msg</name>
    </attribute>
  </tag>
</taglib>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"  errorPage="enoor.jsp"  %>
 <!-- 使用自定义的标签 prefix:标签的前缀 uri:标签的路径 -->
<%@ taglib prefix="dd" uri="/WEB-INF/custom.tld" %>
<!DOCTYPE html> 
<html>
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>	
		<!-- 创建了一个标签名为hello的标签并且前缀为dd -->
		<dd:hello msg="你好啊"/>
</body>

</html>

运行结果:你好啊!

# 3、jstl ## 3.1、jstl简介 JSTL(JavaServer Pages Standard Tag Library)意思时标准标签库,jstl标签基于jsp页面,可以插入在JSP代码中,jstl标签封装了很多功能,大大减少开发的代码量,主要包含核心标签,格式化标签,SQL标签,XML标签,jstl函数。

我这里只讲解一下c标签一些用法
详情参照:https://www.runoob.com/jsp/jsp-jstl.html

3.2、jstl优点

JSTL的优点如下:
1、简化了JSP和Web应用程序的开发。
2、在应用程序服务器之间提供了一致的接口,最大限度地提高了·Web应用在各应用服务器之间的移植。
3、允许JSP设计工具与Web应用程序开发的进一步集成。
4、以一种统一的方式减少了JSP中的Scriptlets代码数量,可以达到程序中没有任何Scriptlest代码。
⑤JSTL封装了JSP开发中的常用功能,提高开发的效率

3.3、使用方法

①要在JSP页面中使用JSTL标签,需使用taglib指令引用标签库
②点击这里下载需要的jar包

3.4、常用的核心标签

3.4.1、c:if标签

标签判断表达式的值,如果表达式的值为 true 则执行其主体内容。

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!-- 引用标签库 -->
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<!-- 设置一个变量 跟其对应的作用域 以及值 -->
	<c:set var="i" scope="request" value="20"></c:set>
	<!-- 进行判断 -->
	<c:if test="${i>19}">
		true
	</c:if>
</body>
</html>

结果为:true

3.4.2、c:forEach标签

c:forEach标签的一些属性
items :要被循环的信息。
begin :开始的元素。
end :最后一个元素。
step :每一次迭代的步长 。
var :代表当前条目的变量名称 。
varStatus :代表循环状态的变量名称。

<%@page import="java.util.ArrayList"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!-- 引用标签库 -->
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>	
		<!-- var="变量名" begin="开始" end="结束" step="迭代增量" -->
		<c:forEach var="i" begin="1" end="5" step="2">
			<c:out value="${i}" />
		</c:forEach>
</body>
</html>

运行结果:1 3 5

3.4.3、, , 标签

标签与Java switch语句的功能一样,标签中对应有代表首位switch的case,switch语句中有default,而标签中有

<%@page import="java.util.ArrayList"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!-- 引用标签库 -->
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>	
		<c:set var="money" value="2999"></c:set>
		
		<c:choose>
			<c:when test="${money>=3000}">钱够了</c:when>
			<c:otherwise>钱少了</c:otherwise>
		</c:choose>
</body>
</html>

运行结果:钱少了

4、Servlet

4.1、Servlet简介

Servlet(Server Applet)是Java Servlet的简称,是用Java编写的服务器端程序,主要功能在于交互式地浏览和生成数据,生成动态Web内容。

4.2、Servlet工作原理

1.浏览器向服务器发出GET请求
2.服务器上的Tomcat接收到该url,根据该url判断为Servlet请求,此时Tomcat将产生两个对象:请求对象(HttpServletRequest)和响应对象(HttpServletResponce)
3.Tomcat根据url找到目标Servlet,且创建一个线程
4.Tomcat将刚才创建的请求对象和响应对象传递给该线程
5.Tomcat调用Servlet的service()方法
6.service()方法根据请求类型(本示例为GET请求)调用doGet()(本示例调用doGet())或doPost()方法
7.doGet()执行完后,将结果返回给Tomcat
8.线程被销毁或被放在线程池中
jsp进阶教程和Servlet_第3张图片

4.3、Servlet生命周期

关于Servlet的生命周期主要有三个方法
①init初始化方法:当客户端发送的时候会调用init方法创建servlet,通过ServletConfig进行初始化,只创建一次下次请求不创建。
②service处理客户端请求方法:当servlet创建完成的时候,将客户端的请求交给service处理,并返回给客户端。
每当收到客户端的请求,服务器会产生一个新的线程进行服务,根据请求的类型,调用其对应处理的方法。
③destroy销毁方法:当web应用被终止,或者Servlet容器终止运行,或者Servlet重新装载Servlet新实例时,Servlet容器会调用Servlet的destroy()方法。

下面来模拟一下servlet的生命周期
首先创建一个类继承HttpServlet并重写inti()、service()、destroy()方法。

package Servlet;

import java.io.IOException;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;

public class MyServlet extends HttpServlet{
     
	
	public MyServlet() {
     
		System.out.println("开始创建Servlet....");
	}
	
	
	@Override
	public void init(ServletConfig arg0) throws ServletException {
     
	System.out.println("Servlet开始初始化....");
	}
	
	@Override
	public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException {
     
		System.out.println("Servlet开始工作....");
	}

	@Override
	public void destroy() {
     
		System.out.println("Servlet开始销毁....");
	}
}

servlet2.5版本需要手动在webxml配置servlet

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
  <display-name>JSP</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
  	
  	<!-- 配置servlet -->
 	<servlet>
 	<!-- servlet的名字 -->
 	<servlet-name>servlet</servlet-name>
 	<!-- servlet的类全限定名 -->
 	<servlet-class>Servlet.MyServlet</servlet-class>
 	</servlet>
 	
 	<!-- 配置servlet的映射 -->
 	<servlet-mapping>
 		<!-- servlet的内部名称要和上面的名称一样 -->
 		<servlet-name>servlet</servlet-name>
 		<!-- servlet的请求路径 -->
 		<!-- 使用http://localhost:8888/JSP/index.jsp/myservlet即可访问servlet -->
 		<url-pattern>/myservlet</url-pattern>
 	</servlet-mapping>
 	
 	
</web-app>

servlet3.0版本可以直接在类上使用@WebServlet("/")注解
@WebServlet("/myservlet")

jsp进阶教程和Servlet_第4张图片
jsp进阶教程和Servlet_第5张图片
当停止tomcat服务器servlet开始进行销毁
jsp进阶教程和Servlet_第6张图片

4.4、表单提交到Servlet

<%@page import="java.util.ArrayList"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!-- 引用标签库 -->
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>	
		<!--action="servlet url"   -->
		<form action="myservlet">
			姓名:<input type="text" name="username"/>
			<br/>
			密码:<input type="text" name="password"/>
			<br/>
			<input type="submit" value="提交"/>
		</form>
</body>
</html>
package Servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/myservlet")
public class MyServlet extends HttpServlet{
     
	//form表单默认提交方式是get所以重写doget方法
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     
		//根据表单input的name值获取数据
		String username = request.getParameter("username");
		String password = request.getParameter("password");
		System.out.println("姓名:"+username);
		System.out.println("密码:"+password);
	}
}

jsp进阶教程和Servlet_第7张图片
输出结果

get请求参数会明文显示,隐私数据建议使用post方式提交较为安全
在这里插入图片描述

姓名:张三
密码:666

4.5、解决页面乱码问题

使用post方式请求

request.setCharacterEncoding("UTF-8");

使用get方式请求

parameter=new String(parameter.getbytes("iso8859-1"),"utf-8");

打印数据在web页面

response.setContentType("text/html;charset=utf-8");

4.6、请求转发和重定向

请求转发
request.getRequestDispatcher(URL地址).forward(request, response);
客户端请求servlet,servlet处理后调用forward方法将数据转发到另外一个页面。

重定向

response.sendRedirect(URL地址);

客户端请求servlet,servlet处理后使用response调用sendRedirect方法把要访问的目标资源作为response响应头信息发给客户端浏览器,不携带数据的情况下使用重定向比较好。

实例

<%@page import="java.util.ArrayList"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!-- 引用标签库 -->
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>	
		<form action="myservlet" method="post">
			姓名:<input type="text" name="username"/>
			<br/>
			密码:<input type="text" name="password"/>
			<br/>
			<input type="submit" value="提交"/>
		</form>
</body>
</html>
package Servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/myservlet")
public class MyServlet extends HttpServlet{
     
	//form表单默认提交方式是get所以重写doget方法
	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     
		//处理乱码问题
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");
		
		//根据表单input的name值获取数据
		String username = request.getParameter("username");
		String password = request.getParameter("password");
		//如果账号密码正确转发到success.jsp界面
		if(username.equals("zs")&&password.equals("123")) {
     
			//包username保存到request域
			request.setAttribute("name", username);
			request.getRequestDispatcher("success.jsp").forward(request, response);
		}else {
     
			//否则跳转到index.jsp界面
			response.sendRedirect("index.jsp");
		}
		
	}
}


<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	欢迎您:${
     name}
</body>
</html>

jsp进阶教程和Servlet_第8张图片运行结果
jsp进阶教程和Servlet_第9张图片

5、过滤器(Filter)

5.1、什么是过滤器

过滤器(Filter)是Servlet常用的一种技术,可以对web资源进行拦截:(例如Jsp, Servlet, 静态图片文件或静态 html 文件),对拦截的资源进行一个权限控制。

Servlet API提供了一个接口Fileter 所有实现接口的类称之为过滤器。

5.2、过滤器原理

Filter接口提供了三个方法:inti()初始化过滤器、doFilter(执行过滤),destory(销毁过滤器)。

①客户端(浏览器)发送请求。
②服务端调用init方法创建请求(request)、响应对象(response)。
③每一个过滤器都有请求响应对象。
④调用doFilter()方法执行过滤,只有当过滤器放行后才能访问Servlet。
⑤最后返回给客户端。
jsp进阶教程和Servlet_第10张图片
用法:
①创建类Filter接口。
②实现Filter接口的方法。
③xml配置过滤器也可以通过在类上面加注解。

实例

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>My JSP 'index.jsp' starting page</title>
  </head>
  <body>
    	<a href="success.jsp">访问</a>
  </body>
</html>

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>jsp</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
  
  	<!-- 配置过滤器 -->
  	<filter>
  		<!-- 过滤器名字 -->
  		<filter-name>myfilter</filter-name>
  		<!-- 过滤器的实现类 -->
  		<filter-class>Filter.MyFilter</filter-class>
  	</filter>
  	
  	<!-- 配置过滤器映射(规则) -->
  	<filter-mapping>
  		<!-- 这里的filter-name要上面的一致 -->
  		<filter-name>myfilter</filter-name>
  		<!-- 过滤所有的资源 -->
  		<url-pattern>/success.jsp</url-pattern>
  	</filter-mapping>
</web-app>
package Filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class MyFilter implements Filter{
     
	
	public MyFilter() {
     
		System.out.println("创建过滤器....");
	}
	
	
	public void init(FilterConfig filterConfig) throws ServletException {
     
	System.out.println("过滤器初始化....");
	}
	
	
	
	public void destroy() {
     
		System.out.println("过滤器开始销毁...");
	}


	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
     
		System.out.println("过滤器开始执行....");
	}


	
	
}

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'success.jsp' starting page</title>

</head>
<body>
欢迎你!!!
</body>
</html>

以上代码实现了资源拦截,当index.jsp页面想访问success.jsp页面的时候,被过滤器拦截了。

jsp进阶教程和Servlet_第11张图片在这里插入图片描述

jsp进阶教程和Servlet_第12张图片

没有打印"欢迎你"说明拦截成功!

当停止tomcat服务器的时候过滤器会进行销毁。
jsp进阶教程和Servlet_第13张图片

5.3、过滤器实现登录拦截

登录界面

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
   
    <title>登录</title>
	
  </head>
  
  <body>
    	<form action="loginServlet" method="post">
    		用户名:<input type="text" name="username"/>
    		<br/>
    		密码:<input type="password" name="password"/>
    		<br/>
    		<input type="submit" value="确定"/>
    		<a href="MyJsp.jsp">跳转</a>
    	</form>
  </body>
</html>

登录成功界面

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'success.jsp' starting page</title>

</head>
<body>
欢迎您:${
     name}
</body>
</html>

登录的servlet

package Login;

import java.io.IOException;

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 javax.servlet.http.HttpSession;

public class MyLogin extends HttpServlet{
     
	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     
		//解决乱码问题
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");
		//获取请求参数
		String name = request.getParameter("username");
		String pwd = request.getParameter("password");
		HttpSession session = request.getSession();
		//如果登录成功就设置一个session
		if(name.equals("zs") && pwd.equals("123")) {
     
			session.setAttribute("name", name);
			request.getRequestDispatcher("success.jsp").forward(request, response);
		}else {
     
			//登录失败就重定向到登录界面
			response.sendRedirect("login.jsp");
		}

	}
}

登录过滤器

package Filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class MyFilter implements Filter{
     

	public void destroy() {
     
		// TODO Auto-generated method stub

	}

	public void doFilter(ServletRequest request, ServletResponse response, FilterChain fChain)
			throws IOException, ServletException {
     

		HttpServletRequest req =(HttpServletRequest) request;
		HttpServletResponse rep = (HttpServletResponse)response;


		//获得请求路径
		String uri = req.getRequestURI();
		boolean flag =true;
		//如果请求路径不是从login.jsp并且session名字为name的值为null就不放行
		if(uri.indexOf("login")==-1 &&req.getSession().getAttribute("name")==null) {
     
			flag=false;
		}
		if(flag) {
     
			fChain.doFilter(request, response);
		}else {
     
			rep.sendRedirect("login.jsp");
		}
	}


	public void init(FilterConfig arg0) throws ServletException {
     

	}






}

注解注册过滤器

//拦截所有资源
@WebFilter(urlPatterns= {
     "/*"})

web.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
 	<!-- 欢迎页 -->
      <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
      <!--登录Servlet-->
    <servlet>
        <servlet-name>LoginServlet</servlet-name>
        <servlet-class>Login.MyLogin</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>LoginServlet</servlet-name>
        <url-pattern>/loginServlet</url-pattern>
    </servlet-mapping>
  	<!-- 配置过滤器 -->
  	<filter>
  		<!-- 过滤器名字 -->
  		<filter-name>myfilter</filter-name>
  		<!-- 过滤器对应类全限定名 -->
  		<filter-class>Filter.MyFilter</filter-class>
  	</filter>
  	
  	<!-- 配置过滤器映射 -->
  	<filter-mapping>
  		<!-- 这里的filter-name要上面的一致 -->
  		<filter-name>myfilter</filter-name>
  		<!-- 过滤所有的资源 -->
  		<url-pattern>/*
  	

jsp进阶教程和Servlet_第14张图片

5.4、编码过滤器

当进行提交或者打印内容到页面上的时候会出现中文乱码现象,按照以往的方式我们会写:

①解决页面乱码

response.setHeader("content-type", "text/html;charset=UTF-8");

②解决post请求乱码

response.setCharacterEncoding("UTF-8");

③get请求乱码

String username=request.getParameter("username");
username=new String(username.getBytes("iso8859-1"),"UTF-8");

以上三种解决乱码的方式每当我们创建一个Servlet的时候就要写一遍,不实用,通过下面的编码过滤器将编码统一设置为utf-8无论创建多少个servlet都能解决中文乱码问题。

实例

index.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 'index.jsp' starting page</title>


  </head>
  
  <body>
    <form action="#" method="post">
    	姓名<input type="text" name="name">
    	<br>
    	<input type="submit" value="提交">
    </form>
    
    
    <%
    	String name = request.getParameter("name");
    	response.getWriter().print(name);
    %>
  </body>
</html>

编码过滤器类

package Filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class EncodingFilter implements Filter{
     

	public void destroy() {
     
		// TODO Auto-generated method stub
		
	}
	
    private String encoding = null;
	private FilterConfig config;
	
	public void init(FilterConfig filterConfig) throws ServletException {
     
		this.config=filterConfig;
	}


	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
     
		HttpServletRequest req = (HttpServletRequest)request;
		HttpServletResponse res = (HttpServletResponse)response;
		//如果encoding为null,则采用FilterConfig的config对象读取编码,encoding编码在配置文件web.xml中定义
		if(encoding==null) {
     
			encoding=config.getInitParameter("encoding");
		}
		//如果不为null通过request对象将编码设置为encoding的值
		//并且通过response对象设置页面的类型和字符编码
		if(encoding!=null) {
     
			request.setCharacterEncoding(encoding);
			response.setContentType("text/html;charset="+encoding);
		}
		//放行
		chain.doFilter(request, response);
		
	}

	
}

注解配置注册编码过滤器

@WebFilter(urlPatterns= {
     "/*"},initParams= {
     @WebInitParam(name="encoding",value="UTF-8")})

web.xml配置编码过滤器

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
 	<!-- 欢迎页 -->
      <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
    	<!-- 配置编码过滤器 -->
    	<filter>
    		<filter-name>EncodingFilter</filter-name>
    		<filter-class>Filter.EncodingFilter</filter-class>
    		<!-- 初始化参数 -->
    		<init-param>
    			<!-- 参数名 -->
    			<param-name>encoding</param-name>
    			<!-- 参数值 -->
    			<param-value>UTF-8</param-value>
    		</init-param>
    	</filter>
    	<!-- 配置编码过滤器映射 -->
    	<filter-mapping>
    		<filter-name>EncodingFilter</filter-name>
    		<url-pattern>/*
    	

6、监听器(Listener)

6.1、监听器概念

监听器是主要用于监听ServletContext、HttpSession和ServletRequest等域对象的创建和销毁事件,它还可以监听域对象的属性发生修改的事件,可以在事件发生前或者发生后做一些必要的处理。

6.2、监听器工作原理

简单解释就是当被监听者的某一个条件被触发了,通知监听者该要干嘛。
在java中可以理解为接口回调:

6.3、监听器的分类

jsp中的监听器分为三类:ServletContext事件监听器、HttpSession事件监听器、ServletRequest事件监听器。

6.4、监听ServletContext事件

6.4.1、监听ServletContextListener创建与销毁

常用方法

方法名 触发条件
public void contextInitialized(ServletContextEvent sce) 创建Servletcontext(即创建应用程序)时
public void contextDestroyed(ServletContextEvent sce) 销毁Servletcontext(停止应用程序)

web.xml注册上下文监听器

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	id="WebApp_ID" version="2.5">
	<!-- 欢迎页 -->
	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>
	<!-- 配置监听器 -->
	<listener>
		<listener-class>Listene.ListeneDemo1</listener-class>
	</listener>
	<!-- 配置上下文初始化参数名和值 -->
	<context-param>
		<param-name>name</param-name>
		<param-value>imooc</param-value>
	</context-param>
</web-app>

上下文监听器类

package Listene;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;


//监听请求对象、响应对象的创建和销毁

public class ListeneDemo1 implements ServletContextListener{
     

	public void contextInitialized(ServletContextEvent sce) {
     
		//获得上下文初始化参数
		String name = sce.getServletContext().getInitParameter("name");
		System.out.println("Servler上下文:"+name+"创建了......");
	}
	public void contextDestroyed(ServletContextEvent sce) {
     
		System.out.println("Servlet上下文销毁了........");
	}
}

运行结果

当启动web容器
jsp进阶教程和Servlet_第15张图片停止web容器
jsp进阶教程和Servlet_第16张图片

6.4.2、监听ServletContextAttributeListener属性的增、删改

public void attributeAdded(ServletContextAttributeEvent arg); 增加属性
public void attributeRemoved(ServletContextAttributeEvent scab); 属性删除
public voidattributeRepalced(ServletContextAttributeEvent arg); 属性替换(第二次设置同一属性)

实例
创建监听器实现ServletContextAttributeListener接口的三个方法
这里使用的是注解方式注册监听器

package Listene;


import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
import javax.servlet.annotation.WebListener;



//监听请求对象、响应对象的创建和销毁
@WebListener("/ls")
public class ListeneDemo1 implements ServletContextAttributeListener{
     

	public void attributeAdded(ServletContextAttributeEvent scab) {
     
		System.out.println("添加了名为:"+scab.getName()+"值为:"+scab.getValue()+"的属性" );
	}

	public void attributeRemoved(ServletContextAttributeEvent scab) {
     
		System.out.println("删除了名为:"+scab.getName()+"值为:"+scab.getValue()+"的属性....");
	}

	public void attributeReplaced(ServletContextAttributeEvent scab) {
     
		System.out.println("替换了名为:"+scab.getName()+"值为:"+scab.getValue()+"的属性");
	}
}

创建servlet

package Listene;

import java.io.IOException;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/jsp/ss")
public class sss extends HttpServlet {
     
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
		//创建全局对象
		ServletContext servletContext = getServletContext();
		//添加
		servletContext.setAttribute("name","张三");
		//覆盖
		servletContext.setAttribute("name", "李四");
		//删除
		servletContext.removeAttribute("name");
	}
}

index.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 'index.jsp' starting page</title>
  </head>
 
  <body>
    	
    	<a href="jsp/ss">访问</a>

  </body>
</html>

当点击超链接访问Servlet的时候控制台打印如下信息

添加了名为:org.apache.jasper.runtime.JspApplicationContextImpl值为:org.apache.jasper.runtime.JspApplicationContextImpl@11551222的属性
添加了名为:org.apache.jasper.compiler.ELInterpreter值为:org.apache.jasper.compiler.ELInterpreterFactory$DefaultELInterpreter@615885d1的属性
添加了名为:name值为:张三的属性
替换了名为:name值为:张三的属性
删除了名为:name值为:李四的属性....

说明监听成功

6.5、监听ServletRequest事件

6.5.1、ServletRequestListener

ServletRequestListener常用方法

方法名 触发条件
public void requestInitialized(ServletRequestEvent sre) 创建request时
public void requestDestroyed(ServletRequestEvent sre) 销毁request时
package Listene;


import java.io.BufferedReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Enumeration;
import java.util.Locale;
import java.util.Map;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;



//监听请求对象创建和销毁
@WebListener("/ls")
public class ListeneDemo implements ServletRequestListener{
     

	public void requestDestroyed(ServletRequestEvent sre) {
     
		System.out.println("request对象销毁了.....");
		
	}

	public void requestInitialized(ServletRequestEvent sre) {
     
		System.out.println("request对象创建了.....");
	}

	
	
}

当客户端通过http协议访问服务器的时候ServletRequest开始进行创建并销毁(因为ServletRequest只在第一次请求有效)。

运行结果

request对象创建了.....
request对象销毁了.....

6.5.2、监听ServletRequestAttributeListener属性增删改

ServletRequestAttributeListener常用方法

方法名 触发条件
public void attributeAdded(ServletRequestAttributeEvent srae) 添加属性时
public void attributeReplaced(ServletRequestAttributeEvent srae) 替换属性时
public void attributeRemoved(ServletRequestAttributeEvent srae) 移除属性时
public String getName(); 得到属性名称
public Object getValue(); 取得属性的值

实例

package Listene;

import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;

import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpServletRequest;



//监听请求对象创建和销毁
@WebListener("/ls")
public class ServletRquestListeners implements  ServletRequestAttributeListener  
{
     

	public void attributeAdded(ServletRequestAttributeEvent arg0) {
     
		System.out.println("增加了" + arg0.getName() + " " +
				arg0.getValue() );       
	}

	public void attributeReplaced(ServletRequestAttributeEvent arg0) {
     
		System.out.println("修改了" + arg0.getName() + " " +
				arg0.getValue() );
	}
	public void attributeRemoved(ServletRequestAttributeEvent arg0) {
     
		System.out.println("去除了" + arg0.getName() + " " +
				arg0.getValue() );
	}
} 



package Listene;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/jsp/dd")
public class ddd extends HttpServlet{
     
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
		req.setAttribute("name", "张三");
		req.setAttribute("name", "李四");
		req.removeAttribute("name");
	}
}

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'index.jsp' starting page</title>
</head>

<body>
	<a href="jsp/dd">访问</a>
</body>
</html>

结果

修改了org.apache.catalina.ASYNC_SUPPORTED true
增加了name 张三
修改了name 张三
去除了name 李四

6.6、监听会话(HttpSession)事件

6.6.1、监听HttpSessionListener

常用方法

方法名 触发条件
public void sessionCreated(HttpSessionEvent se) 创建session时
public void sessionDestroyed(HttpSessionEvent se) 销毁session时

实例

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>
   		<%
   			request.getSession().setAttribute("name", "zs");
   		 %>
   		 
   			<a href="qc.jsp">清除session</a>
  </body>
</html>

监听器页面

package com.zhou;

import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

public class Listener implements HttpSessionListener{
     
	
	public void sessionCreated(HttpSessionEvent se) {
     
		System.out.println("创建了sessison........");
	}

	public void sessionDestroyed(HttpSessionEvent se) {
     
		System.out.println("销毁了session..........");
	}

}

web.xml配置界面

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>jsp</display-name>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  
  	<listener>
  		<listener-class>com.zhou.Listener</listener-class>
  	</listener>
</web-app>

以上代码我们在index.jsp页面创建了一个session控制台打印如下信息:

创建了sessison........

当点击链接清除session的时候控制台打印如下信息说明session被清除成功

销毁了session..........

6.6.2、监听HttpSessionAttributeListener

常用方法

方法名 触发条件
public void attributeAdded(HttpSessionBindingEvent event) 添加属性时
public void attributeReplaced(HttpSessionBindingEvent event) 替换属性时
public void attributeRemoved(HttpSessionBindingEvent event) 移除属性时

实例
index.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 'index.jsp' starting page</title>
  </head>  
  <body>
   		<%
   			//增加
   			request.getSession().setAttribute("name", "zs");
   			//替换
   			request.getSession().setAttribute("name", "ls");
   		 %>
   		 	<!--清除  -->
   			<a href="qc.jsp">清除session</a>
  </body>
</html>

监听器界面采用的是注解注册

package com.zhou;

import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;

@WebListener
public class Listener implements HttpSessionAttributeListener{
     

	public void attributeAdded(HttpSessionBindingEvent se) {
     
		System.out.println("添加了"+se.getName()+"属性");
	}

	public void attributeRemoved(HttpSessionBindingEvent se) {
     
		System.out.println("删除了"+se.getName()+"属性");
	}

	public void attributeReplaced(HttpSessionBindingEvent se) {
     
		System.out.println("替换了"+se.getName()+"属性");
	}
	
	

}

清除session界面

<%@ 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>
   
  </head>
  
  <body>
    <%request.getSession().invalidate(); %>
  </body>
</html>

以上代码当我们打开浏览器的时候访问服务器会显示

添加了name属性
替换了name属性

当点击了清除session链接所有session失效从而也达到删除session的目的,当然也可以通过“request.removeAttribute(“session名字”);”删除指定seession 或者等待session名字到期即可

7、jsp+servlet连接数据库

7.1、使用mysql驱动包连接数据库

准备好连接mysql的jar包,我这里使用的是:mysql-connector-java-5.1.49.jar
创建servlet

package com.zhou;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Connection;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


@WebServlet("/findAll")
public class Servlets extends HttpServlet{
     
	private final static String DRIVER="com.mysql.jdbc.Driver";
	private final static String URI="jdbc:mysql:///sys?useSSL=false";
	private final static String USERNAME="root";
	private final static String PASSWORD="19990704";
	private static PreparedStatement ps;
	private static Connection conn;
	private static ResultSet rs;
	//加载驱动
	static {
     
		try {
     
			Class.forName(DRIVER);
			System.out.println("加载驱动成功....");
		} catch (ClassNotFoundException e) {
     
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
		 try {
     
			 resp.setContentType("text/html;charset=utf-8");
			//建立连接
			 conn = DriverManager.getConnection(URI,USERNAME,PASSWORD);
			 //定义查询sql语句
			 String sql = "select * from user";
			 //执行sql语句
			  ps = conn.prepareStatement(sql);
			  //执行查询
			  rs =ps.executeQuery();
			  //遍历结果集
			  PrintWriter out = resp.getWriter();
			  while (rs.next()) {
     
				//将结果打印到页面
				 //""里面的内容要跟数据库里面的字段对应
				  out.print(rs.getInt("id"));
				  out.print(" ");
				  out.print(rs.getString("name"));
				  out.print(" ");
				  out.print(rs.getString("password"));
				  out.println("
"
); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally { //释放资源 try { if (rs!=null) { rs.close(); } if (ps!=null) { ps.close(); } if (conn!=null) { conn.close(); } } catch (Exception e2) { // TODO: handle exception } } } }

创建jsp页面用来请求servlet

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>My JSP 'index.jsp' starting page</title>
  </head>  
  <body>
   	
   			<a href="findAll">查询</a>
  </body>
</html>

运行结果
jsp进阶教程和Servlet_第17张图片

7.2、使用c3p0连接数据库

C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展,支持自动回收。目前使用它的开源项目有Hibernate、Spring等。

使用方法
①下载mysql驱动包和c3p0jiar包:mysql-connector-java-5.1.49.jar、c3p0-0.9.1.2.jar。
②在src下编写c3p-config配置文件

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
	<!-- 我们希望在配置文件中,出现链接的参数信息 -->
	<!-- 1、配置默认数据源 -->
	<default-config>
		<!-- name 属性定义 链接参数的key 标签的内容 代表值 -->
		<property name="driverClass">com.mysql.jdbc.Driver</property>
		<!-- 采用了简写形式,三个/ -->
		<property name="jdbcUrl">jdbc:mysql:///sys?useSSL=false
		<property name="user">root</property>
		<property name="password">19990704</property>
		<!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数 -->
		<property name="acquireIncrement">5</property>
		<!--初始化时获取十个连接,取值应在minPoolSize与maxPoolSize之间 -->
		<property name="initialPoolSize">10</property>
		<!--连接池中保留的最小连接数 -->
		<property name="minPoolSize">10</property>
		<!--连接池中保留的最大连接数 -->
		<property name="maxPoolSize">50</property>
	</default-config>
</c3p0-config>

编写jdbc工具类

package com.zhou;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import java.sql.PreparedStatement;

public class JdbcUtil {
     
	 //创建c3p0的实例,读取src下面的配置文件中default-config里面的默认数据源
    private static ComboPooledDataSource ds = new ComboPooledDataSource();

    //创建c3p0的实例,读取src下面的配置文件中named-config里面的初始数据源
//    private static ComboPooledDataSource ds1 = new ComboPooledDataSource("petshop");
    //从连接池里面获取连接
    public static Connection getConnection() throws SQLException {
     
        return ds.getConnection();
    }

    //关闭两个参数,释放资源
    public static void close(Connection conn, PreparedStatement ps) {
     
        try {
     
            ps.close();
        } catch (SQLException e) {
     
            e.printStackTrace();
        }
        try {
     
            //使用连接池后,此时的close()并不是关闭链接,而是把链接放回到了连接池中
            conn.close();
        } catch (SQLException e) {
     
            e.printStackTrace();
        }
    }

    //关闭三个参数,释放资源
    public static void close(Connection conn, PreparedStatement ps, ResultSet rs) {
     
    	try {
     
			if (rs!=null) {
     
				rs.close();
			}
			if (ps!=null) {
     
				ps.close();
			}
			if (conn!=null) {
     
				conn.close();
			}
		} catch (Exception e2) {
     
			// TODO: handle exception
		}
    }
}

编写servlet

package com.zhou;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Connection;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


@WebServlet("/findAll")
public class Servlets extends HttpServlet{
     
	
	
	
	
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
		 	Connection conn = null;
	        PreparedStatement ps = null;
	        ResultSet rs = null;
		try {
     
			 resp.setContentType("text/html;charset=utf-8");
			//建立连接
			 conn = JdbcUtil.getConnection();
			 //定义查询sql语句
			 String sql = "select * from user";
			 //执行sql语句
			  ps = conn.prepareStatement(sql);
			  //执行查询
			  rs =ps.executeQuery();
			  //遍历结果集
			  PrintWriter out = resp.getWriter();
			  while (rs.next()) {
     
				//将结果打印到页面
				 //""里面的内容要跟数据库里面的字段对应
				  out.print(rs.getInt("id"));
				  out.print(" ");
				  out.print(rs.getString("name"));
				  out.print(" ");
				  out.print(rs.getString("password"));
				  out.println("
"
); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally { //释放资源 JdbcUtil.close(conn, ps, rs); } } }

index.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 'index.jsp' starting page</title>
  </head>  
  <body>
   	
   			<a href="findAll">查询</a>
  </body>
</html>

运行结果
jsp进阶教程和Servlet_第18张图片

8、jsp+servlet分页

8.1、什么是分页

当我们打开百度随便搜索一个东西会出现如下红框框里面的内容有页码,还可以上一页下一页,简而言之就是把从数据库里面查询出来的数据,控制他的每页数据显示条数。
jsp进阶教程和Servlet_第19张图片

8.2、分页思路

①在servlet定义当前页,从那条记录开始分页,以及每页显示的条数。
②判断前端传来的当前页是否为null,不为null就转整数。
③判断前端传来的每页需要显示的条数是否为null,不为null就转整数。
④计算开始页信息:(开始页+每页显示条数)*(当前页-1);
四获取数据的总条数。
⑤根据总条数计算分页总数:
如果(总条数/每页显示条数!=0)
就向上取整Math.ceil(总条数/pageS每页显示条数)+1
否则向上取整Math.ceil(总条数/pageS每页显示条数)。
⑥把总条数、分页总数和当前页以及集合保存到request域,然后转发到前台jsp页面。

8.3、使用mysql关键字limit实现分页

语法:select * from 表名 limit 参数1,参数2
参数1代表从第几页开始,参数2表示显示的条数。

实例:select * from user limit 1,2
下面我们去代码里面实现分页效果

index.jsp界面
需要引入c标签遍历后台集合数据到页面上(需要jstl jar包)

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!-- 引入c 标签 -->
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'index.jsp' starting page</title>
</head>
<body>
	<a href="findAll">查询</a>
	<center>
		<table border="1" cellpadding="0" cellspacing="0">
			<tr>
				<th>编号</th>
				<th>姓名</th>
				<th>密码</th>
			</tr>
			<c:forEach items="${user}" var="u">
				<tr>
					<td>${
     u.id}</td>
					<td>${
     u.name}</td>
					<td>${
     u.password}</td>
				</tr>
			</c:forEach>
		</table>
		当前页${
     pageNum}/总页数${
     page}&nbsp;
		<!-- 当前页不等于1 代表可以进跳转到首页 -->
		<c:if test="${pageNum!=1}">
			<a href="findAll?pageNum=1">首页</a>
		</c:if>
		<!-- 当前页不等于1 分页总数代表可以进行上一页 -->
		<c:if test="${pageNum!=1}">
			<a href="findAll?pageNum=${pageNum-1}">上一页</a>
		</c:if>
		<!-- 当前页等于1 分页总数代表不可以进行上一页 -->
		<c:if test="${pageNum==1}">
			上一页
		</c:if>
		<!-- 当前页不等于分页总数代表可以进行下一页 -->
		<c:if test="${pageNum!=page}">
			<a href="findAll?pageNum=${pageNum+1}">下一页</a>
		</c:if>

		<c:if test="${pageNum==page}">
   			下一页
   		</c:if>
		<!-- 当前页不等于1 代表可以进跳转到首页 -->
		<c:if test="${pageNum!=page}">
			<a href="findAll?pageNum=${page}">尾页</a>
		</c:if>
		跳转到<input type="text" value="" id="count" style="width: 30px"><button onclick="tz()">跳转</button>
		每页显示 <input type="text" value="" id="row" style="width: 30px"><button onclick="xs()">显示</button>

	</center>
</body>
<script type="text/javascript">
		//跳转到指定页函数方法
		function tz () {
     
		//获取输入框的值
		var count=document.getElementById("count").value;
		//判断输入的数是否是整数
		var i =parseInt(count);
		if(i!=count||count>${
     page}){
     
		//输入的数大于总分页数提示错误信息
			alert("输入的数有误请重新输入!")
			count=document.getElementById("count").value="";
		}else{
     
			window.location.href="findAll?pageNum="+count;
		}
		}
		//控制显示条数的函数方法
		function xs () {
     
		//获取输入框的值
			var row=document.getElementById("row").value;
			//转整数
			var i =parseInt(row);
			//判断输入的数是否是整数
			if(i!=row){
     
				alert("输入的数有误请重新输入!")
				row=document.getElementById("row").value="";
			}else if(row>${
     page}){
     
				//输入的数大于总条数提示错误信息
				alert("输入的数不能大于总数居条数!")
				row=document.getElementById("row").value="";
			}else{
     
				//输入的数是整数把显示的条数传到后台取
				window.location.href="findAll?pagesize="+row;
			}
			
		}
	</script>
</html>

c3p0-config.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
	<!-- 我们希望在配置文件中,出现链接的参数信息 -->
	<!-- 1、配置默认数据源 -->
	<default-config>
		<!-- name 属性定义 链接参数的key 标签的内容 代表值 -->
		<property name="driverClass">com.mysql.jdbc.Driver</property>
		<!-- 采用了简写形式,三个/ -->
		<property name="jdbcUrl">jdbc:mysql:///sys?useSSL=false
		<property name="user">root</property>
		<property name="password">19990704</property>
		<!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数 -->
		<property name="acquireIncrement">5</property>
		<!--初始化时获取十个连接,取值应在minPoolSize与maxPoolSize之间 -->
		<property name="initialPoolSize">10</property>
		<!--连接池中保留的最小连接数 -->
		<property name="minPoolSize">10</property>
		<!--连接池中保留的最大连接数 -->
		<property name="maxPoolSize">50</property>
	</default-config>
</c3p0-config>

jdbcUtil连接数据库工具类

package com.zhou;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import java.sql.PreparedStatement;

public class JdbcUtil {
     
	 //创建c3p0的实例,读取src下面的配置文件中default-config里面的默认数据源
    private static ComboPooledDataSource ds = new ComboPooledDataSource();

    //创建c3p0的实例,读取src下面的配置文件中named-config里面的初始数据源
//    private static ComboPooledDataSource ds1 = new ComboPooledDataSource("petshop");
    //从连接池里面获取连接
    public static Connection getConnection() throws SQLException {
     
        return ds.getConnection();
    }

    //关闭两个参数,释放资源
    public static void close(Connection conn, PreparedStatement ps) {
     
        try {
     
            ps.close();
        } catch (SQLException e) {
     
            e.printStackTrace();
        }
        try {
     
            //使用连接池后,此时的close()并不是关闭链接,而是把链接放回到了连接池中
            conn.close();
        } catch (SQLException e) {
     
            e.printStackTrace();
        }
    }

    //关闭三个参数,释放资源
    public static void close(Connection conn, PreparedStatement ps, ResultSet rs) {
     
    	try {
     
			if (rs!=null) {
     
				rs.close();
			}
			if (ps!=null) {
     
				ps.close();
			}
			if (conn!=null) {
     
				conn.close();
			}
		} catch (Exception e2) {
     
			// TODO: handle exception
		}
    }
}

servlet

package com.zhou;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.sql.Connection;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


@WebServlet("/findAll")
public class Servlets extends HttpServlet{
     
	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     
			//解决页面显示内容乱码问题
			response.setContentType("text/html;charset=utf-8");
			//从第几条数据开始分页 
			int pageStart = 0;
			//每页显示数据的条数
			int pageSize = 2;
			//设置当前页
			int pageNum = 1;
			//获取从前端传来的页码
			String pageNums=request.getParameter("pageNum");
			//如果当前页码不为空把页码转换为整数赋值给当前页码
			if(pageNums!=null) {
     
				pageNum=Integer.parseInt(pageNums);
			}
			
			//获取从前端传来的页码
			String pageSizes=request.getParameter("pagesize");
			//如果当前页码不为空把页码转换为整数赋值给当前页码
			if(pageSizes!=null) {
     
				pageSize=Integer.parseInt(pageSizes);
			}
			
			//计算开始页
			pageStart = (pageStart+pageSize)*(pageNum-1);
			
			List<User> list = UserDao.findAll(pageStart,pageSize);
			
			//获取分页的总页数
			int size = UserDao.Selectsize();
			request.setAttribute("size", size);
			//计算分页总数
			int page;
			//如果分页总数除以显示条数不等于0
			if(size/pageSize!=0) {
     
				//就向上取整分页的总页数+1
				page=(int)Math.ceil(size/pageSize)+1;
			}else {
     
				//不等于0就向上取整分页的总页数
				page=(int) Math.ceil(size/pageSize);
			}
			
			//分页总页数
			request.setAttribute("page", page);
			
			//把当前页码存到request域
			request.setAttribute("pageNum", pageNum);
			
			//把集合添加到request作用域
			request.setAttribute("user", list);
			//转发到index.jsp界面
			request.getRequestDispatcher("index.jsp").forward(request, response);
	}
}

分页方法和条数总数方法

package com.zhou;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class UserDao {
     
	//分页查询方法
	public static List<User> findAll(int i, int j) {
     
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		//获得连接
		try {
     
			conn = JdbcUtil.getConnection();
			String sql = "select * from user limit ?,?";
			//预编译sql语句
			ps= conn.prepareStatement(sql);
			//为?赋值
			//第一个?
			ps.setInt(1, i);
			//第二个?
			ps.setInt(2, j);
			//执行sql语句
			rs = ps.executeQuery();
			//定义集合保存user对象
			ArrayList<User> list = new ArrayList<User>();
			//遍历结果集
			while (rs.next()) {
     
				//通过构造函数遍历结果集
				User user = new User(
						rs.getInt("id"),
						rs.getString("name"),
						rs.getString("password")
						);
				//添加user对象集合
				list.add(user);
			}
			return list;
		} catch (SQLException e) {
     
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
     
			JdbcUtil.close(conn, ps,rs);
		}
		return null;
	}
	//获得总条数方法
	public static int Selectsize() {
     
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		//获得连接
		try {
     
			conn = JdbcUtil.getConnection();
			String sql = "select count(*) from user ";
			//预编译sql语句
			ps= conn.prepareStatement(sql);
			//执行sql语句
			rs = ps.executeQuery();
			int i=0;
			//遍历结果集
			while (rs.next()) {
     
				i=rs.getInt(1);
			}
			return i;
		} catch (SQLException e) {
     
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
     
			JdbcUtil.close(conn, ps,rs);
		}
		return 0;
	}

}

User类

	package com.zhou;

public class User {
     
	private Integer id;
	private String name;
	private String password;
	public User(Integer id, String name, String password) {
     
		super();
		this.id = id;
		this.name = name;
		this.password = password;
	}
	public User() {
     
		super();
		// TODO Auto-generated constructor stub
	}
	
	
	
	public Integer getId() {
     
		return id;
	}
	public void setId(Integer id) {
     
		this.id = id;
	}
	public String getName() {
     
		return name;
	}
	public void setName(String name) {
     
		this.name = name;
	}
	public String getPassword() {
     
		return password;
	}
	public void setPassword(String password) {
     
		this.password = password;
	}
	@Override
	public String toString() {
     
		return "User [id=" + id + ", name=" + name + ", password=" + password + "]";
	}
	
	
}

运行结果
jsp进阶教程和Servlet_第20张图片

9、jsp+servlet文件上传

9.1、文件上传

①引入如下jar包
在这里插入图片描述
②表单需要设置enctype="multipart/form-data"以二进制方式上传。
③编写处理上传文件的servlet和jsp页面

jsp界面
<%@ page language=“java” import=“java.util.*” pageEncoding=“UTF-8”%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"/"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

My JSP 'file.jsp' starting page
package com.zhou;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.List;

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 org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

@WebServlet("/fileUpload")
public class FileUpload extends HttpServlet{
     
	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     
		//解决乱码问题
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");
		//创建文件上传保存的目录
		String path="E:/upload"; 
		File file = new File(path); 
		//判断文件是否存在不存在就创建
		if (!file.exists() ) {
      
		//创建目录 
		file.createNewFile(); 
		} 
		try{
      
		//使用Apache文件上传组件处理文件上传步骤: 
		//1、创建一个DiskFileItemFactory工厂 
		DiskFileItemFactory factory = new DiskFileItemFactory(); 
		//2、创建一个文件上传解析器 
		ServletFileUpload upload = new ServletFileUpload(factory); 
		//解决上传文件名的中文乱码 
		upload.setHeaderEncoding("UTF-8"); 
		//3、判断提交上来的数据是否是上传表单的数据 
		if(!ServletFileUpload.isMultipartContent(request)){
      
		//按照传统方式获取数据 
		return; 
		} 
		//4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List集合,每一个FileItem对应一个Form表单的输入项 
		List<FileItem> list = upload.parseRequest(request); 
		for(FileItem item : list){
      
		//如果fileitem中封装的是普通输入项的数据 
		if(item.isFormField()){
      
		String name = item.getFieldName(); 
		//解决input输入的数据中文乱码问题 
		String value = item.getString("UTF-8"); 
		//value = new String(value.getBytes("iso8859-1"),"UTF-8"); 
		System.out.println(name + "=" + value); 
		}else{
     
		//如果fileitem中封装的是上传文件 
		//得到上传的文件名称, 
		String filename = item.getName(); 
		System.out.println(filename); 
		if(filename==null || filename.trim().equals("")){
      
		continue; 
		} 
		//不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,而有些只是单纯的文件名
		//处理获取到的上传文件的文件名的路径部分,只保留文件名部分 
		filename = filename.substring(filename.lastIndexOf("\\")+1); 
		//获取item中的上传文件的输入流 
		InputStream in = item.getInputStream(); 
		//创建一个文件输出流 
		FileOutputStream out = new FileOutputStream(path + "\\" + filename); 
		//创建一个缓冲区 
		byte buffer[] = new byte[1024]; 
		//判断输入流中的数据是否已经读完的标识 
		int len = 0; 
		//循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据 
		while((len=in.read(buffer))>0){
      
		//使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath + "\\" + filename)当中 
		out.write(buffer, 0, len); 
		} 
		//关闭输入流 
		in.close(); 
		//关闭输出流 
		out.close(); 
		//删除处理文件上传时生成的临时文件 
		item.delete(); 
		response.getWriter().print("");
		} 
		} 
		}catch (Exception e) {
      
			response.getWriter().print("");
		e.printStackTrace(); 
		} 
	}
}

运行结果
jsp进阶教程和Servlet_第21张图片
jsp进阶教程和Servlet_第22张图片

你可能感兴趣的:(jsp进阶,javabean,过滤器,java,jsp)