Java web学习笔记

JavaWeb笔记

Servlet

一、Servlet接口

1、Servlet接口中的主要方法
1.1、init(Servlet config)

Servlet的初始化方法。在Servlet实例化后,容器调用该方法进行Servlet的初始化,ServletAPI规定任何Servlet实例init()方法只能被调用一次,如果此方法没有正常结束,就会抛出ServletException异常,一旦抛出异常,Servlet将不再执行。

1.2、service

(ServletRequest req, ServletResponse resp)😗*Servl的服务方法。当用户对Sevlet发出请求时容器会调用该方法处理用户请求;ServletRequest参数提供访问请求数据的方法和字段,ServletResponse参数提供Servlet构造相应的方法。

1.3、destroy():

Servlet的销毁方法。容器在终止Servlet服务前调用此方法,容器调用此方法前必须给service()线程足够时间来结束执行,因此接口规定当service()正在执行时,destroy()不被执行。

1.4、getServletConfig():

此方法可以让Servlet在任何时候后的ServletConfig对象。

1.5、getServletInfo():

此方法可以让Servlet在任何时候获得Servlet的信息,例如:开发者、创建日期、描述信息等。该方法也可用于容器。

2、GenericServlet类

GenericServlet类是一个抽象类,时Servlet接口的直接实现,提供了除service()方法之外其他有关Servlet生命周期的方法;

我们可以通过简单的拓展GenericServlet和实现service()方法编写一个基本的Servlet。

2.1、init(ServletConfig conf):

该方法来源于Servlet接口,若重写方法,必须调用super.init(config),这样GenericServlet类的其他方法才能正常工作。

2.2、init(ServletConfig config)

该方法重载了Servlet结合口的init(ServletConfig config)方法而无需调用super.init(config)而ServletConfig对象依然可以通过调用getServletConfig()方法获得。

2.3、service(ServletRequest req, ServletResponse resp):

这是一个抽象的方法,当为执行网络请求继承这个类时必须实现它。

2.4、destroy():

与Servlet接口中的destroy方法相同。

3、HttpServlet类

HttpServlet类继承于GenericServlet类,HttpServlet指能够处理Http请求的Servlet,他在原有的Servlet接口上添加了对Http协议的处理,它比Servlet接口的功能更加强大(PS:虽然通过拓展GenericServlet就可以编写一个基本的Servlet,但若要实现一个在Web中处理的Http请求的Servlet,则需要使用HttpServlet),HttpServlet作为Http请求的分发器,除了提供对Get和Post请求的处理方法doGet()和doPost()之外,对于其他请求类型(如:Head、Options、Delete、Put、Trance)也提供了相应的处理方法(如:doHead()、doOptions()、doDelete()、doPut()、doTrance())

3.1、service(HttpServletRequest req, HttpResponse resp):

HttpServlet在实现Servlet接口是,重写了service()方法。该方法会自动判断用户的请求方式;若为get请求,则调用HttpServlet的doGet()方法;若为post请求,则调用doPost()方法,而不要去重写service()方法。如果Servlet收到一个Http请求而没有重载相应的do方法 ,它就返回一个说明此方法对本资源不可用的标准Http错误。

3.2、doGet(HttpServletResquest req, HttpServletResponse resp):

此方法被本类的service()方法调用,用来处理一个HttpGet操作。

3.3、doPost(HttpServletResquest req, HttpServletResponse resp):

此方法被本类的service()方法调用,用来处理一个HttpPost操作

4、Servlet生命周期

Servlet的生命周期是指Servlet实例从创建到相应客户请求、直至销毁的过程。

5、Servlet的声明配置:@WebServlet&web.xml
5.1、String name&< servlet-name>

指定Servlet的名字,可以为任何字符串,一般与Servlet的类名相同,如果没有显式指定,则该Servlet的取值即为类的全限定名。

5.2、String[] urlPatterns&< url-pattern>

指定一组Servlet的URL匹配模式,可以是匹配地址映射(如:/SimpleServlet)、匹配目录映射(如:/servlet/*)和匹配扩展名映射(如: *.action)。

5.3、String[] value

该属等价于urlPatterns睡醒。两个属性不能同时使用。

5.4、WebInitParam[] initParams&< init-param>

指定一组初始化参数

5.5、int loadOnStartUp&< load-on-startup>

指定Servlet的加载顺序。当此项没有指定时,表示容器在该Servlet第一次被请求时才加载;当值为0或大于0时,表示容器在应用启动时就加载了这个Servlet。值越小,启动该Servlet的优先级越高。原则上不同的Servlet应该使用不同的启动顺序数字。

5.6、boolean asyncSupported&< async-supported>

声明Servlet是否支持异步操作模式,默认为false。

5.7、String description& < description >

指定该Servlet的描述信息。

5.8、String displayName&< displayname>

指定该Servlet的显示名,通常配合工具使用。

5.9、< servlet-class>

指Servlet类的全限定名,即:包名.类名。

5.10、< param-name>

指定初始参数名。

5.11、< param-value>

指定初始参数名对应的值。

5.12、< servlet-name>

用来指定要映射的Servlet名称,要与< servlet>声明中的< servlet-name>值一致。

二、数据处理

1、处理超链接请求数据(GET请求)

当用户通过超链接发送的请求到达Servlet容器时,包含数据的请求将被容器转换为HttpServletRequest对象。对请求数据的处理工作便由HttpServletRequest对象完成。

2、HttpServletRequest对象常用的数据处理方法
2.1、public String getParameterValues(String name)

返回由name指定的用户的请求参数的值

2.2、public String[] getParameterValues(String name)

返回由name指定的一组用户的请求参数的值

2.3、public Enumeration getParameterNames()

返回所有客户请求的参数名

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<a href="linkRequestServlet?pageNo=2&queryString=QST">下一页</a>
</body>
</html>
package com.learn.Demo01.servlet;

import java.io.IOException;
import javax.servlet.*;
@WebServlet("/linkRequestServlet")
public class linkRequestServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
    public linkRequestServlet() {
        super();
    }
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String pageNo = request.getParameter("pageNo");
		String queryString = request.getParameter("queryString");
		response.getWriter().println("pageNo:"+pageNo);
		response.getWriter().println("queryString:"+queryString);
		
	}

	
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	}

}

3、处理Form表单请求数据(POST请求)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="FormRequestServlet" method="POST">
	<p>用户名:<input name="username" type="text"></p>
	<p>&nbsp;码:<input name="password" type="password"></p>
	<p>信息来源:<input name="channel" type="checkbox" value="Web">网络
			  <input name="channel" type="checkbox" value="Newspaper">报纸
			  <input name="channel" type="checkbox" value="Friend">亲友</p>
			  <p>
			  <input name="submit" type="submit" value="提交">
			  <input name="reset" type="reset" value="重置">
			  </p>
</form>
</body>
</html>
package com.learn.Demo01.servlet;

import java.io.*;

import javax.servlet.*;

@WebServlet("/FormRequestServlet")
public class FormRequestServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    public FormRequestServlet() {
        super();
    }

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.getWriter().append("Served at: ").append(request.getContextPath());
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String username = request.getParameter("username");
		String password  = request.getParameter("password");
		String[] channel = request.getParameterValues("channel");
		PrintWriter out = response.getWriter();
		out.println("username:"+username);
		out.println("password:"+password);
		for(String s : channel)
		{
			out.println("channel:"+s);
		}
	}

}

4、重定向

重定向是指由原请求地址重新定位到某个新地址,原有的request请求失效,客户端看到的时新的request请求返回的响应结果,客户端浏览器地址栏变为新请求地址。

重定向方法(GET请求)

重定向通过HttpServletResponse对象sendRedirect()方法实现,该方法会通知客户端去重新访问新指定的URL地址

public void sendRedirect(String location)

其中location参数用以指定重定向的URL,可以是相对路径或绝对路径

PS:sendRedirect()方法不仅可以重定向到当前应用程序中的其他资源,还可以重定向到同一个站点上的其他应用程序中的资源,甚至是使用绝对URL重定向到其他站点的资源

package com.learn.Demo01.servlet;

import java.io.IOException;
import javax.servlet.*;

@WebServlet("/RedirectServlet")
public class RedirectServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    public RedirectServlet() {
        super();
    }

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("before redirect");
//		response.sendRedirect("/Demo01/ResultServlet");
		/**相对路径*/
		response.sendRedirect(request.getContextPath()+"/ResultServlet");
		System.out.println("end redirect");
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

}

package com.learn.Demo01.servlet;

import java.io.IOException;
import javax.servlet.*;

@WebServlet("/ResultServlet")
public class ResultServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    public ResultServlet() {
        super();
    }

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("redirect result");
		response.getWriter().println("redirect result page");
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

}

5、请求转发
  • 请求转发是指将请求再转发到其他地址,转发过程中使用的是同一个请求对象,妆发后浏览器地址栏内容不变。

  • 请求转发的过程是发生在服务器内部的,对客户端是透明的。服务器只能从当前应用内部查找相应的转发资源,而不能转发到其他应用资源。

  • 请求转发使用RequestDispatcher接口中的forward()方法来实现,该方法可以把请求转发给另外一个资源,并让该资源对此请求进行响应。

RequestDispatcher接口
  • forward()方法:将请求转发给其他资源
  • include()方法:将其他资源并入到当前请求中
package com.learn.Demo01.servlet;

import java.io.IOException;

import javax.servlet.*;

@WebServlet("/ForwardServlet")
public class ForwardServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    public ForwardServlet() {
        super();
    }

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("forward before");
		RequestDispatcher dispatcher = request .getRequestDispatcher("ResultServlet");
		dispatcher .forward(request, response);
		System.out.println("forward end");
	}
    
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

}

package com.learn.Demo01.servlet;

import java.io.IOException;
import javax.servlet.*;

@WebServlet("/ResultServlet")
public class ResultServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    public ResultServlet() {
        super();
    }

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("redirect result");
		response.getWriter().println("redirect result page");
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

}

三、Servlet核心接口

1、ServletConfig接口
1.1定义

容器在初始化一个Servlet时,将为该Servlet创建一个唯一的ServletConfig对象,并将这个ServletConfig对象通过init(ServletConfig config)方法传递并保存在此Servlet对象中。

1.2主要方法
  • getInitParameter(String param):根据给定的初始化参数名称,返回匹配的初始化参数值。
  • getInitParameterNames(String param):返回一个Enumeration对象,里面包含了所有的初始化参数。
  • getServletContext():返回一个ServletContext()对象。
  • getServletName();返回当前Servlet的名字,即@WebServlet的name属性值。如果没有配置这个属性,则返回Servlet类的全限定名。
<servlet>
  	<servlet-name>HelloServlet</servlet-name>
  	<servlet-class>com.learn.Demo02.servlet.HelloServlet</servlet-class>
  	<init-param>
  		<param-name>url</param-name>
  		<param-value>jdbc:oracle;thin:@localhost:1512:orcl</param-value>
  	</init-param>
  	<init-param>
  		<param-name>user</param-name>
  		<param-value>qst</param-value>
  	</init-param>
  	<init-param>
  		<param-name>password</param-name>
  		<param-value>qst123</param-value>
  	</init-param>
  </servlet>
package com.learn.Demo02.servlet;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

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

public class HelloServlet extends HttpServlet{

	
	public void init(ServletConfig config) throws ServletException{
		String url = config.getInitParameter("url");
		String user = config.getInitParameter("user");
		String password = config.getInitParameter("password");
		try {
			Connection connection = DriverManager.getConnection(url, user, password);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	

}

2、ServletContext接口
2.1定义
  • ServletContext也称为Servlet上下文,代表当前Servlet运行环境,是Servlet与Servlet容器之间的通信的接口。
  • Servlet容器在启动一个Web应用时,会为该应用创建一个唯一的ServletContext对象供该应用中的所有Servlet对象共享,Servlet对象可以通过ServletContext对象来访问容器中的各种资源。
2.2获取ServletContext对象的两种方式
  • 通过ServletConfig接口的getServletContext()方法获得ServletContext对象;
  • 通过GenericServlet抽象类的getServletContext()方法获得ServletContext对象,实质上该方法也是调用了ServletConfig的getServletContext()方法
2.3、ServletContext接口中提供的方法
2.3.1、获取应用初始化参数
  • 在Web应用开发中,可以通过web.xml配置应用范围的初始化参数,容器在应用程序加载时会读取这些配置参数,并存入ServletContext对象中

  • ServletContext接口提供的方法:

    getInitParameter(String name):返回应用范围内匹配的初始化参数值。在web.xml中< web-app>元素中< context-param>元素表示应用范围内的初始化参数。

    getInitParameterNames():返回一个包含初始化参数的Enumeration对象。

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
      <display-name>Demo02</display-name>
      <context-param>
      	<param-name>webSite</param-name>
      	<param-value>www.itshixun.com</param-value>
      </context-param>
      <context-param>
      	<param-name>email</param-name>
      	<param-value>admin@itshixun.com</param-value>
      </context-param>
      <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>
    </web-app>
    
    package com.learn.Demo02.servlet;
    
    import java.io.IOException;
    import java.util.Enumeration;
    import javax.servlet.*;
    
    @WebServlet("/ContextInitParamServlet")
    public class ContextInitParamServlet extends HttpServlet {
    	private static final long serialVersionUID = 1L;
           
        public ContextInitParamServlet() {
            super();
        }
    
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		ServletContext context = super.getServletContext();//获取Context对象
    		String webSite = context .getInitParameter("webSite");//获取初始化参数的值
    		String email = context .getInitParameter("email");//获取初始化参数的值
    		Enumeration<String> names  = context.getInitParameterNames();//获取所有应用初始化参数的名称,返回枚举类型
    		while(names.hasMoreElements()) {
    			String name = names.nextElement();
    			response.getWriter().println("name:"+name);
    		}
    		response.getWriter().println("webSite:"+webSite);
    		response.getWriter().println("email:"+email);
    	}
    
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		doGet(request, response);
    	}
    
    }
    
    
2.3.2、存取应用域属性
  • ServletContext对象可以理解为容器内的一个共享空间,可以存放具有应用级别作用域的数据,Web应用中的各个组件都可以共享这戏数据。这些共享数据以key/value的形式存放在ServletContext对象中,并以key作为其属性名被访问

  • 应用于存取方法

    setAttribute(String name, Object object):把一个对象和一个属性名绑定并存放到一个ServletContext中,参数name指定属性名,参数Object表示共享数据。

    getAttribute(String name):根据一个Enumeration对象,返回一个Object类型的对象。

    getAttributeNames():返回一个Enumeration对象,该u第项包含了所有存放在ServletContext中的属性名。

    removeAttribute(String name):根据参数指定的属性名,从ServletContext对象中删除匹配的属性。

  • 应用域具有两层含义:一是表示由Web应用的生命周期构成的时间段;而是表示在Web应用范围内的可访问性。

    package com.learn.Demo02.servlet;
    
    import java.io.IOException;
    
    import javax.servlet.*;
    
    @WebServlet("/ContextAttributeServlet")
    public class ContextAttributeServlet extends HttpServlet {
    	private static final long serialVersionUID = 1L;
           
        public ContextAttributeServlet() {
            super();
        }
    
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		ServletContext context = super.getServletContext();
    		Integer count = (Integer)context.getAttribute("count");
    		if(count==null) {
    			count = 1;
    		}else {
    			count=count+1;
    		}
    		context.setAttribute("count", count);
    		response.getWriter().println("count:   "+count);
    	}
    
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		doGet(request, response);
    	}
    
    }
    
    
2.3.3、获取应用信息
  • ServletContext对象包含有关Web应用的信息,例如:当前Web应用的根路径、应用名称、应用组件间的转发、以及容器下其他Web应用的ServletContext对象等

  • Web应用信息的获取方法

    getContextPath():返回当前Web应用的根路径。

    getServletContextName():返回Web应用的名字。即< web-app>元素中< display-name>元素的值。

    getRequestDispatcher(String path):返回一个用于其他Web组件转发请求的RequestDispatcher对象。

    getContext(String uripath)根据参数指定的URL返回当前Servlet容器中其他Web应用的ServletContext()对象,URL必须是以“/”开头的绝对路径。

    PS:服务器想要跨项目访问时需要将服务器配置文件中的contet.xml中的< context>改为< context crossContext=“true”>

    package com.learn.Demo02.servlet;
    
    import java.io.IOException;
    
    import javax.servlet.*;
    
    
    @WebServlet("/ContextAppInfoServlet")
    public class ContextAppInfoServlet extends HttpServlet {
    	private static final long serialVersionUID = 1L;
           
        
        public ContextAppInfoServlet() {
            super();
        }
    
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		request.setCharacterEncoding("utf-8");
    		response.setContentType("text/http;charset=utf-8");
    		ServletContext context = super.getServletContext();
    		//获取当前应用的上下文根路径
    		String path = context.getContextPath();
    		//获取当前应用名称
    		String contextNmae = context.getServletContextName();
    		//获取当前容器中路径为Demo01项目中的ServletContext对象
    		ServletContext context2 = context.getContext("/Demo01");
    		String context02Name = context2.getServletContextName();
    		
    		response.getWriter().println("Path:"+path);
    		response.getWriter().println("contextName:"+contextNmae);
    		response.getWriter().println("context02Name:"+context02Name);
    		
    		
    	}
    
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		doGet(request, response);
    	}
    
    }
    
    
2.3.4、获取容器信息
  • ServletContext接口提供了获取有关容器信息和向容器输出日志的方法

    getServerInfo():返回Web容器的名字和版本。

    getMajorVersion():返回Web容器支持的Servlet API的主版本号。

    getMinorVersion():返回Web容器支持的Servlet API的次版本号。

    log(String msg):用于记录一般的日志。

    log(String message, Throwable throw):用于记录异常的堆栈日志。

    package com.learn.Demo02.servlet;
    
    import java.io.IOException;
    
    import javax.servlet.*/
    
    
    @WebServlet("/ContextLogServlet")
    public class ContextLogServlet extends HttpServlet {
    	private static final long serialVersionUID = 1L;
           
      
        public ContextLogServlet() {
            super();
        }
    
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		// TODO Auto-generated method stub
    		request.setCharacterEncoding("utf-8");
    		response.setContentType("text/http;charset=utf-8");
    		ServletContext context = super.getServletContext();
    		//获取当前Web容器的名字和版本号
    		String serverInfo = context.getServerInfo();
    		//容器支持的Servlet API主版本号
    		int majorVersion = context.getMajorVersion();
    		//容器支持的Servlet API次版本号
    		int minorVersion = context.getMinorVersion();
    		//记录日志
    		context.log("自定义日志");
    		//记录异常的堆栈日志信息
    		context.log("自定义错误信息", new Exception("异常堆栈信息"));
    		
    		System.out.println("Web容器的名字和版本号:"+serverInfo);
    		System.out.println("容器支持的Servlet API主版本号:"+majorVersion);
    		System.out.println("容器支持的Servlet API次版本号:"+minorVersion);
    	}
    
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		doGet(request, response);
    	}
    
    }
    
2.3.5、获取服务器文件资源
  • ServletContext接口可以直接访问Web应用中的静态内容文件,例如HTML、GIF、Properties文件等,同时还可以获取文件资源的MIME类型以及其在服务器中的真实存放路径。

  • 具体方法

    getResourceAsStream(String path):返回一个读取参数指定的文件的输入流,参数路径必须以"/"开头。

    getResource(String path):返回由path指定的资源路径对应的一个URL对象,参数路径必须以"/"开头

    getRealPath(String path):根据参数指定的虚拟路径,返回文件系统中的一个真是的路径。

    getMineType(String file):返回参数指定的文件的IMINE类型。

    package com.learn.Demo02.servlet;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.URL;
    
    import javax.servlet.*;
    
    @WebServlet("/ContextFileResourceServlet")
    public class ContextFileResourceServlet extends HttpServlet {
    	private static final long serialVersionUID = 1L;
           
        public ContextFileResourceServlet() {
            super();
        }
    
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		request.setCharacterEncoding("utf-8");
    		response.setContentType("text/html;charset=utf-8");
    		ServletContext context = super.getServletContext();
    		//获取静态文件的输入流
    		InputStream iStream = context.getResourceAsStream("/image/题.PNG");
    		//获取静态文件的URL
    		URL url = context.getResource("/image/题.PNG");
    		//从URL对象中获取文件的输入流
    		InputStream isurl = url.openStream();
    		boolean flag = iStream.available()==isurl.available();
    		//获取指定的文件虚拟路径获取其真实路径
    		String fileRealPath = context.getRealPath("/image/题.PNG");
    		//获取文件的MIME类型
    		String mimeType = context.getMimeType("/image/题.PNG");
    		
    		response.getWriter().println("<p>flag:"+flag+"</p>");
    		response.getWriter().println("<p>fileRealPath:"+fileRealPath+"</p>");
    		response.getWriter().println("<p>MIME:"+mimeType+"</p>");
    		
    		
    	
    	}
    
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		doGet(request, response);
    	}
    
    }
    
3、HttpServletRequest接口
3.1、定义
  • 在Servlet API中,ServletRequest接口被定义为用于封装请求的信息。ServletRequest对象由Servlet容器在用户每次请求Servlet时创建并传入Servlet的service()方法中。
  • HttpServletRequest接口继承了ServletRequest接口,时专用于Http协议的子接口,用于封装Http请求信息。
  • 在HttpServlet类中的service()方法中,传入的ServletRequest对象被强制转换为HttpServletRequest对象来进行Http请求信息的处理。
3.2、Http请求行
  • Http协议请求报文的请求行由请求方法、请求URL和请求协议版本组成

  • HttpServletRequest接口对请求行各部分信息的获取方法

    getMethod():获取请求使用的Http方法,例如:GET、POST、PUT。

    getRequestURL():获取请求行中的资源名部分。

    getProtocol():获取使用的协议及版本号。例如:Http/1.1、Http/1.9。

    getQueryString():获取请求URL后面的查询字符串,只对GET有效。

    getServletPath():获取Servlet所映射的路径。

    getContextPath():获取请求资源所属于的Web应用路径。

    package com.learn.Demo02.servlet;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    import javax.servlet.*;
    
    
    @WebServlet("/RequestLineServlet")
    public class RequestLineServlet extends HttpServlet {
    	private static final long serialVersionUID = 1L;
           
        
        public RequestLineServlet() {
            super();
        }
    
    	
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		// 设置响应到客户端MIME类型和字符编码格式
    		request.setCharacterEncoding("utf-8");
    		response.setContentType("text/http;charset=utf-8");
    		//获取http请求方式
    		String method = request.getMethod();
    		//获取请求行中的资源名
    		String url = request.getRequestURI();
    		//获取使用的协议及版本号
    		String protocol = request.getProtocol();
    		//获取URL后面的查询字符串
    		String queryString = request.getQueryString();
    		//获取Servlet所映射的路径
    		String servletPath = request.getServletPath();
    		//获取请求资源所属于的Web应用的路径
    		String contextPath = request.getContextPath();
    		//获取输出流
    		PrintWriter outPrintWriter = response.getWriter();
    		outPrintWriter.println("<p>请求使用的http请求方式:"+method+"</p>");
    		outPrintWriter.println("<p>请求行中的资源名部分:"+url+"</p>");
    		outPrintWriter.println("<p>请求使用的协议及版本号:"+protocol+"</p>");
    		outPrintWriter.println("<p>请求URL后面的查询字符串:"+queryString+"</p>");
    		outPrintWriter.println("<p>Servlet所映射的路径:"+servletPath+"</p>");
    		outPrintWriter.println("<p>请求资源所属于的Web应用的路径"+contextPath+"</p>");
    		outPrintWriter.close();
    	}
    
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		doGet(request, response);
    	}
    
    }
    
    
3.3、Http请求头
3.3.1Http协议常见的请求头
  • Host:初始URL中的主机和端口,可以通过这个信息获得提出请求的主机名称和端口号。
  • Connection:表示是否需要持久连接。如果值为“Keep-Alive”或者该请求使用的是HTTP1.1(HTTP1.1默认进行持久连接),他就可以利用持久连接的优点,当页面包含多个元素时(例如:Applet、图片),可以显著的减少下载所需要的时间。
  • Content-Length:表示消息正文的长度。
  • Cache-Control:指定请求和响应准寻的缓存机制。常见值no-cache,指示请求和响应消息不能缓存。
  • Accept:浏览器可接受的MIME类型。
  • Origin:用来说明最初请求是从哪里发起,只用于FOST请求。
  • User-Agent:浏览器相关信息。
  • Accept-Charset:浏览器可接受的字符集。
  • Content-Type:表示后面的文档属于什么MIME类型。Servlet默认为test/plain,但通常需要显式地指定为text/html。由于经常要设置Content-Type,因此HttpServletRequest提供了一个专用的方法setContentType();
  • Referer:包含一个URL,表示从哪个地址出发访问到当前请求地址的
  • Accept-Encoding:浏览器能够进行解码的数据编码方式,比如gzip。Servlet能够向支持gzip的浏览器返回经gzip编码的HTML页面。许多情形下这可以减少5-10倍的下载时间。
  • Accept-Language:浏览器所希望的语言种类。当服务器能够提供一种以上的语言版本时要用到,开发人员可以通过这个信息确定可以向客户端显示何种语言的界面。
  • Cookie:表示客户端的Cookie信息。
3.3.2、获取请求头信息
  • 通过HttpServletRequest的getHeaderNames()方法获得所有请求头,此方法返回一个Enumeration(枚举)类型的值

    public abstract Enumeration getHeaderNames();

  • 通过HttpServletRequest的getHeader()方法根据指定的请求头名称读取当前对应的请求头信息,如果当前的请求中提供了对应的请求头信息,则返回对应的值,否则返回NULL

    public abstract String getHeader(String headerName);

  • HttpServletRequest提供了专门对请求头的访问方法

    getIntHeader(String name):获取整数类型参数名为name的http头部。

    getDateHeader(String name):获取long类型name的http头部。

    getContentLength():获取请求内容的长度,以字节为单位。

    getContentType():获取请求的文档类型定义。

    getLocale():获取用户浏览器设置的Locale信息。

    package com.learn.Demo02.servlet;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.util.Enumeration;
    
    import javax.servlet.*;
    @WebServlet("/RequestHeadInfoServlet")
    public class RequestHeadInfoServlet extends HttpServlet {
    	private static final long serialVersionUID = 1L;
           
        public RequestHeadInfoServlet() {
            super();
        }
    
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		request.setCharacterEncoding("utf-8");
    		response.setContentType("text/html;charset=utf-8");
    		StringBuffer sb = new StringBuffer();
    		sb.append("<html>");
    		sb.append("<head><title>请求头信息</title></head>");
    		sb.append("<table>");
    		sb.append("<body>");
    		sb.append("<h1>请求头信息</h1>");
    		sb.append("<p>获取请求头\"Host\"的信息:").append(request.getHeader("Host")).append("</p>");
    		sb.append("<p>获取请求头\"Content-Length\"的信息:").append(request.getIntHeader("Content-Length")).append("</p>");
    		sb.append("<p>获取请求头\"If-Modified-Since\"的信息:").append(request.getDateHeader("If-Modified-Since")).append("</p>");
    		sb.append("<p>获取请求内容的长度:").append(request.getContentLength()).append("</p>");
    		sb.append("<p>请求文档类型定义:").append(request.getContentType()).append("</p>");
    		sb.append("<p>用户浏览器的Locale信息:").append(response.getLocale()).append("</p>");
    		sb.append("<p>获取的Cookie[]数组对象:").append(request.getCookies()).append("</p>");
    		sb.append("<html>");
    		
    		//获取所有的请求头及名称
    		sb.append("<table border='1'>");
    		sb.append("<tr><th>请求头名称</th><th>请求头值</th></tr>");
    		Enumeration<String> headerNames = request.getHeaderNames();
    		while (headerNames.hasMoreElements()) {
    			String headerName = (String) headerNames.nextElement();
    			sb.append("<tr>");
    			sb.append("<td>").append(headerName).append("</td>");
    			sb.append("<td>").append(request.getHeader(headerName)).append("</td>");
    			sb.append("</tr>");
    		}
    		sb.append("</table>");
    		sb.append("</body>");
    		sb.append("</html>");
    		
    		PrintWriter out = response.getWriter();
    		out.println(sb.toString());
    		
    	}
    
    
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws Servletxception, IOException {
    		doGet(request, response);
    	}
    
    }
    
    
3.4、获取请求正文
3.4.1、获取请求正文(一)
  • Http协议请求正文内容为POST请求参数名称和值所组成的一个字符串;而对于GET请求,其请求参数附属在请求行中,没有请求正文。

  • Http协议的POST请求,主要通过Form表单向Web服务器端程序提交数据请求的方式实现。

  • < form>表单元素的enctype属性用于指定浏览器使用哪种编码方式将表单中的数据传给Web服务器,该属性由两种取值:

    application/x-www-form-urlencoded

    multipart/form-data

  • enctype属性默认的值为“application/x-www.form-urlencoded”

  • 使用"application/x-www-form-urlencoded"编码方式的请求正文,HttpServletRequest接口提供的获取方法如下:

    String getParameter(String name):返回由name指定的用户请求参数值。

    Enumeration getParameterNames():返回所有客户请求的参数名。

    String[] getParameterValues(String name):返回由name指定的用户请求参数的值

    Map getParameterMap():返回一个请求参数的Map,Map中的键为参数的名称,值为参数名对应的参数值。

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
    <form action="FormRequestServlet" method="POST">
    	<p>用户名:<input name="username" type="text"></p>
    	<p>密&nbsp;码:<input name="password" type="password"></p>
    	<p>信息来源:<input name="channel" type="checkbox" value="Web">网络
    			  <input name="channel" type="checkbox" value="Newspaper">报纸
    			  <input name="channel" type="checkbox" value="Friend">亲友</p>
    			  <p>
    			  <input name="submit" type="submit" value="提交">
    			  <input name="reset" type="reset" value="重置">
         </p>
    </form>
    </body>
    </html>
    
    package com.learn.Demo01.servlet;
    
    import java.io.*;
    
    import javax.servlet.*;
    
    @WebServlet("/FormRequestServlet")
    public class FormRequestServlet extends HttpServlet {
    	private static final long serialVersionUID = 1L;
           
        public FormRequestServlet() {
            super();
        }
    
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		response.getWriter().append("Served at: ").append(request.getContextPath());
    	}
    
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		String username = request.getParameter("username");
    		String password  = request.getParameter("password");
    		String[] channel = request.getParameterValues("channel");
    		PrintWriter out = response.getWriter();
    		out.println("username:"+username);
    		out.println("password:"+password);
    		for(String s : channel)
    		{
    			out.println("channel:"+s);
    		}
    	}
    
    }
    
    
3.4.2、获取请求正文(二)
  • enctype属性只有在< form>表单向服务器上传文件时才会设置值为“multipart/form-data”,并且此属性只适用于POST请求方式。

  • < form>表单的文件上传实现语法:

    <form action="服务器端程序地址" method="POST" enctype="multipart/form-data">
        <input name="文件域名称" type="file">
        <input type="submit" value="提交">
    </form>
    
  • 示例

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
    <form action="" method="post" enctype="multipart/form-data">
    	用户名:<input name="username" type="text">
    	上传文件:<input name="file" type="file">
    	<input type="submit">
    </form>
    </body>
    </html>
    
3.4.3、获取请求正文(三)
  • HttpServletRequest接口提供了获取请求正文的方法:

    ServletInputStream getInputStream():获取上传文件二进制输入流。

    BufferedReader getReader():获取上传文件字符缓冲输入流。

  • 使用@MultipartConfig注解方式获取上传文件

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
    <form action="FileUploadServlet" method="post" enctype="multipart/form-data">
    	用户名:<input name="username" type="text">
    	上传文件:<input name="file" type="file">
    	<input type="submit">
    </form>
    </body>
    </html>
    
    package com.learn.Demo02.servlet;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    import javax.servlet.*;
    @WebServlet("/FileUploadServlet")
    @MultipartConfig
    public class FileUploadServlet extends HttpServlet {
    	private static final long serialVersionUID = 1L;
    
        public FileUploadServlet() {
            super();
        }
    
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		response.getWriter().append("Served at: ").append(request.getContextPath());
    	}
    
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		request.setCharacterEncoding("utf-8");
    		response.setContentType("text/html;charset=utf-8");
    		Part part = request .getPart("file");
    		String filename = part.getSubmittedFileName();
    		part.write(getServletContext().getRealPath("/image/")+filename);
    		String username = request.getParameter("username");
    		PrintWriter out = response.getWriter();
    		out.print("username:"+username);
    	}
    
    }
    
    
3.5、获取网络连接信息
  • HttpServletRequest接口提供了如下获取客户端和服务端网络连接信息的方法

    getRemoteAddr():获取请求用户的IP地址。

    getRemoteHost():获取请求用户的主机名字。

    getRemotePort():获取请求用户的主机所使用的网络端口号。

    getLocalAddr():获取Web服务器的IP地址。

    getLocalName():获取Web服务器的主机名。

    getLocalPort():获取Web服务器所使用的网络端口号。

    getServerName():获取网站域名。

    getServerPort():获取URL请求的端口号。

    getScheme():获取请求使用的协议,例如:http或是https。

    getRequestURL():获取请求的URL地址。

    package com.learn.Demo02.servlet;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    /**
     * Servlet implementation class RequestWebInfoServlet
     */
    @WebServlet("/RequestWebInfoServlet")
    public class RequestWebInfoServlet extends HttpServlet {
    	private static final long serialVersionUID = 1L;
           
        /**
         * @see HttpServlet#HttpServlet()
         */
        public RequestWebInfoServlet() {
            super();
            // TODO Auto-generated constructor stub
        }
    
    	/**
    	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
    	 */
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		// TODO Auto-generated method stub
    		request.setCharacterEncoding("utf-8");
    		response.setContentType("text/http;charset=utf-8");
    		StringBuffer sb = new StringBuffer();
    		sb.append("<p>请求用户的IP地址:").append(request.getRemoteAddr()).append("</p>");
    		sb.append("<p>请求用户的主机名称:").append(request.getRemoteHost()).append("</p>");
    		sb.append("<p>请求用户的主机使用的网络端口:").append(request.getRemotePort()).append("</p>");
    		sb.append("<p>Web服务器的IP地址:").append(request.getLocalAddr()).append("</p>");
    		sb.append("<p>Web服务器的主机名:").append(request.getLocalName()).append("</p>");
    		sb.append("<p>Web服务器所使用的网络端口:").append(request.getLocalPort()).append("</p>");
    		sb.append("<p>网站的域名:").append(request.getServerName()).append("</p>");
    		sb.append("<p>URL请求的端口号:").append(request.getServerPort()).append("</p>");
    		sb.append("<p>请求使用的协议:").append(request.getScheme()).append("</p>");
    		sb.append("<p>请求的URL地址:").append(request.getRequestURL()).append("</p>");
    		
    		PrintWriter out = response.getWriter();
    		out.println(sb.toString());
    	}
    
    	/**
    	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
    	 */
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		// TODO Auto-generated method stub
    		doGet(request, response);
    	}
    
    }
    
    
3.6、存取请求域属性
  • 存储在HttpServletRequest对象中的对象称之为请求域属性,属于同一个请求的多个处理组件之间可以通过请求域属性来传递对象数据

  • HttpServletRequest接口提供了如下与请求域属性相关的方法

    void setAttribute(String name, Object value):存入一个请求域属性,name为属性名,value为属性值。

    Object getAttribute(String name):根据属性名称取出一个请求域属性值。

    void removeAttribute(String name):根据属性名称从请求范围内移除一个请求域属性。

    Enumeration getAttributeNames():获取所有请求范围内的请求域属性对象。

    package com.learn.Demo02.entity;
    
    public class People {
    	private String name;
    	private int age;
    	
    	public People() {
    		super();
    		// TODO Auto-generated constructor stub
    	}
    
    	public People(String name, int age) {
    		super();
    		this.name = name;
    		this.age = age;
    	}
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    
    	public int getAge() {
    		return age;
    	}
    
    	public void setAge(int age) {
    		this.age = age;
    	}
    
    	@Override
    	public String toString() {
    		return "People [name=" + name + ", age=" + age + "]";
    	}
    	
    	
    
    }
    
    
    package com.learn.Demo02.servlet;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.util.Enumeration;
    
    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 com.learn.Demo02.entity.People;
    
    /**
     * Servlet implementation class RequestScopeAttributeServlet
     */
    @WebServlet("/RequestScopeAttributeServlet")
    public class RequestScopeAttributeServlet extends HttpServlet {
    	private static final long serialVersionUID = 1L;
           
        /**
         * @see HttpServlet#HttpServlet()
         */
        public RequestScopeAttributeServlet() {
            super();
            // TODO Auto-generated constructor stub
        }
    
    	/**
    	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
    	 */
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		// TODO Auto-generated method stub
    		request.setCharacterEncoding("utf-8");
    		response.setContentType("text/html;charset=utf-8");
    		//设置名为People的People类型的请求域属性
    		request.setAttribute("people", new People("张三",30));
    		//设置名为msg的String类型的请求域属性
    		request.setAttribute("msg", "请求域中的String类型属性");
    		//获取名为people的请求域属性的值
    		People people = (People)request.getAttribute("people");
    		//获取名为msg的请求域属性的值
    		String msg = (String)request.getAttribute("msg");
    		//获取输出流
    		PrintWriter out = response.getWriter();
    		out.println("<p>request.getAttribute(\"people\")的值:"+people+"</p>");
    		out.println("<p>request.getAttribute(\"msg\")的值:"+msg+"</p>");
    		
    		Enumeration<String> names = request.getAttributeNames();
    		out.println("<p>请求域中的属性有:");
    		while (names.hasMoreElements()) {
    			out.println(names.nextElement()+"&nbsp;");
    			
    		}
    		
    		out.println("</p>");
    		request.removeAttribute("people");
    		out.println("<p>执行request.removeAttrinbute(\"people\")后的请求域属性有:");
    		names = request.getAttributeNames();
    		while (names.hasMoreElements()) {
    			out.println(names.nextElement()+"&nbsp;");			
    		}
    		out.close();
    	}
    
    	/**
    	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
    	 */
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		// TODO Auto-generated method stub
    		doGet(request, response);
    	}
    
    }
    
    
4、HttpServletResponse接口
4.1、定义
  • public interface HttpServletResponse extends ServletResponse
  • 在Servlet API中,ServletResponse接口被定义为用于创建相应消息。
  • ServletResponse对象由Servlet容器在用户每次请求Servlet时创建并传入Servlet的service()方法中。
  • HttpServletResponse接口继承自ServletResponse接口,是专用于Http协议的子接口,用于封装Http响应消息。
  • 在HttpServlet类的service()方法中,传入的ServletResponse对象被强制转换为HttpServletResponse对象来进行Http响应信息的处理。
4.2、Http状态码
4.2.1、状态码分类
  • 1**:表示信息,服务器收到请求,需要请求者继续执行操作
  • 2**:表示请求已成功被服务器接收、理解并接受
  • 3**:表示客户端采取进一步的操作才能完成请求。通常,这些状态码用来重定向,后续的请求地址(重定向目标)在本次响应的Location域中指明
  • 4**:表示客户端错误,请求包含语法错误或无法完成的请求
  • 5**:表示服务器在处理请求的过程中有错误或者异常状态发生,也有可能是服务器意识到以当前的软硬件资源无法完成对请求的处理
4.2.2、常见状态码
  • 200:表示请求成功
  • 302:表示资源(网页等)暂时转移到其他URL
  • 404:表示请求的资源(网页等)不存在
  • 500:表示服务器程序内部错误
4.3设置响应状态
  • setStatus(int sc):以指定的状态码将响应返回给客户端
  • setError(int sc):使用指定的状态码向客户端返回一个错误响应
  • sendError(int sc,String msg):使用指定的状态码和状态描述向客户端返回一个错误响应
  • sendRedirect(String location):请求的重定向,会响应Location报头以及改变状态码
package com.learn.Demo02.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;

/**
 * Servlet implementation class SetStatusServlet
 */
@WebServlet("/SetStatusServlet")
public class SetStatusServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public SetStatusServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/http;charset=utf-8");
		
		//response.sendRedirect("");
		response.setStatus(302);
		response.setHeader("location", "uploadFile.html");
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

4.4、构建响应消息头
  • 在Servlet中,可以通过HttpServletResponse的setHeader()方法来设置Http响应消息头,它接受两个参数用于指定响应消息头的名称和对应的值。

  • 设置值是String类型的响应消息头的语法格式

    public abstract void setHeader(String headName, String headerValue)

  • 对于含有整数和日期的消息头,设置方法语法格式:

    public abstract void setIntHeader(String headerName, int headerValue)

    public abstract void setDateHeader(String headerName, long millisecs)

4.4.1、常用响应消息头
  • Server:一种标明Web服务器软件及其版本号的头标
  • Content-Type:返回文档所采用的MIME类型
  • Transfer-Encoding:表示为了达到安全传输或者数据压缩等目的而对实体进行的编码。如chunked编码,该编码将实体分块传送并逐块标明长度,直到长度为0块表示传输结束,这在实体长度未知的时候特别有用(比如自由数据库动态产生的数据)
  • Date:发送Http消息的日期
  • Content-Encoding:用于说明页面在传输中已经采用的编码方式
  • Content-Length:响应内容的长度,以字节为单位
  • Expires:特定的一段时间,这段时间后应该将该文档人做事过期,不应该再继续缓存
  • Refresh:多少秒后浏览器应该重新载入页面
  • Cache-Control:用来指定响应遵循的缓存机制,若取值no-cache值表示阻止浏览器缓存页面
  • Last-Modified:文档最后被改动的时间。不要直接设置这个报头,而是应该提供getLastModified方法
  • Location:浏览器应该重新连接到URL。一般无需直接设置这个报头,而是使用sendRedirect()方法进行设定
  • Content-Disposition:通过这个报头,可以请求浏览器询问用户将响应存储到磁盘上给定的文件中
  • Set-Cookie:浏览器应该记下来的Cookie。不要直接设置这个报头,而是应该使用addCookie()方法
  • WWW-Authenticate:授权的类型和范围。需要在Authorization报头中给出
4.4.2、常用的消息头设置方法
  • setContentType(String mime):设定Content-Type消息头

  • setContentLength(int length):设定Content-Length消息头

  • addHeader(String name, String value):新增String类型的值到名为name的http头部

  • addIntHeader(String name, int vlaue):新增int类型的值到名为name的http头部

  • addDataHeader(String name, long value):新增long类型的值到名为name的http头部

  • addCookie(Cookie c):为Set-Cookie消息头增加一个值

    package com.learn.Demo02.servlet;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    /**
     * Servlet implementation class SetHeaderServlet
     */
    @WebServlet("/SetHeaderServlet")
    public class SetHeaderServlet extends HttpServlet {
    	private static final long serialVersionUID = 1L;
           
        /**
         * @see HttpServlet#HttpServlet()
         */
        public SetHeaderServlet() {
            super();
            // TODO Auto-generated constructor stub
        }
    
    	/**
    	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
    	 */
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		// TODO Auto-generated method stub
    		request.setCharacterEncoding("utf-8");
    		response.setContentType("text/http;charset=utf-8");
    		
    		response.setHeader("Refresh", "1");
    		
    		
    		PrintWriter out = response.getWriter();
    		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    		out.println("现在是:"+sdf.format(new Date()));
    	}
    
    	/**
    	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
    	 */
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		// TODO Auto-generated method stub
    		doGet(request, response);
    	}
    
    }
    
    
4.5、创建响应正文
  • 在Servlet中,向客户端输出的响应数据是通过输出流对象完成的,HttpServletResponse接口提供了两个获取不同类型输出流的方法

    getOutputStream():返回字节输出流对象ServletOutputStream

    getWriter():返回字符输出流对象PrintWriter

  • ServletOutputStream对象主要用于输出二进制字节数据的。例如:配合setContentType()方法响应输出一个图像、视频等

  • PrintWriter对象主要用于输出字符文本内容,但其内部实现仍是将字符串转换成某种字符集编码的字节数组后再进行输出

  • ServletOutputStream对象虽然也可以输出文本字符,但PrintWriter对象更易于完成文本到字节数组的转换

  • 当ServletOutputStream或PrintWrite对象中写入数据后,Servlet容器会将这些数据作为响应消息的正文,然后再与响应状态行和哥响应头组合成完整的响应报文输出到客户端

    package com.learn.Demo02.servlet;
    
    import java.io.IOException;
    import java.io.InputStream;
    
    import javax.servlet.ServletException;
    import javax.servlet.ServletOutputStream;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    /**
     * Servlet implementation class OutputStreamServlet
     */
    @WebServlet("/OutputStreamServlet")
    public class OutputStreamServlet extends HttpServlet {
    	private static final long serialVersionUID = 1L;
           
        /**
         * @see HttpServlet#HttpServlet()
         */
        public OutputStreamServlet() {
            super();
            // TODO Auto-generated constructor stub
        }
    
    	/**
    	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
    	 */
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		// TODO Auto-generated method stub
    		response.setContentType("image/PNG");
    		InputStream is = super.getServletContext().getResourceAsStream("/image/题.PNG");
    		ServletOutputStream os = response.getOutputStream();
    		int i = 0;
    		while((i=is.read())!=-1) {
    			os.write(i);
    		}
    		is.close();
    		os.close();
    	}
    
    	/**
    	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
    	 */
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		// TODO Auto-generated method stub
    		doGet(request, response);
    	}
    
    }
    
    

四、会话跟踪

1、无状态的Http协议
  • Http协议是一种无状态协议
  • Http协议采用的是"连接-请求-应答-关闭连接"模式
  • 对于交互式的Web应用,保持状态是非常重要的。一个有状态的协议可以用来帮助在多个请求和响应之间实现复杂的业务逻辑
2、会话跟踪技术
  • 会话跟踪技术是一种在客户端与服务器间保持Http状态的解决方案。从开发者角度考虑,是使上一次请求所传递的数据能够维持状态到下一次请求,并且辨认出是否相同的客户端发送来的。
2.1、Cookie技术
  • Cookie技术使一种在客户端保持会话跟踪的解决方案

  • Cookie是指某些网站为了辨别用户身份而存在用户终端上的文本信息(通常经过加密)

  • Cookie在用户第一次访问服务器时,由服务器通过响应头的方式发送给客户端浏览器;当用户再次向服务器发送请求时会附带上这些文本信息

  • Cookie对象通过javax.servlet.http.Cookie类的构造方法来创建

    Cookie unameCookie = new Cookie("username", "QST");
    

    其中,Cookie类的构造方法需要两个参数:第一个String类型用于指定Cookie的属性名;第二个String类型的参数用于指定属性值

  • HttpServletResponse对象通过addCookie()方法, 以增加"Set-Cookie"响应头的方式(不是替换原有的)将Cookie对象响应给客户端浏览器,存储在客户端机器上。

    response.addCookie(unameCookie);
    

    其中参数为一个Cookie对象

  • 通过HttpServletResponse对象的getCookie()方法获取客户端请求的Cookie。该方法所访问网站的所有Cookie的对象数组,便利该数组可以获得各个Cookie对象

  • 示例

    Cookie[] cookie = request.getCookie();
    if(cookie != null){
        for(Cookie c : cookie){
            out.println("属性名"+c.getName());
            out.println("属性值"+c.getValue());
        }
    }
    
  • Cookie的访问路径:在默认情况下,Cookie只能被创建它的应用获取。Cookie的setPath()方法可以重新指定其访问路径,例如:将其设置为在某个应用下的某个路径共享,或者在同一服务器内的所有应用共享。

  • Cookie的存活时间:Cookie有一定的存活时间,不会再客户端一直保存;默认情况下,Cookie保存在浏览器的内存中,在浏览器关闭时失效,这种Cookie也称为临时Cookie(或会话Cookie);若要使Cookie较长时间的保存在磁盘上,可以通过磁盘上的Cookie也称为持久Cookie

  • Cookie对象可以通过setMaxAge()方法设置其存活时间,时间以秒为单位:

    若时间为正整数,表示其存货秒数

    若时间为负数,表示其为临时Cookie

    若时间为0,表示通知浏览器删除相应的Cookie

    示例

    unameCookie,setMasAge(1*24*60*60);//参数以秒为基本单位
    
    package com.learn.Demo04.servlet;
    
    import java.io.IOException;
    
    import java.io.PrintWriter;
    import java.net.URLDecoder;
    import java.net.URLEncoder;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    /**
     * Servlet implementation class CookieExampleServlet
     */
    @WebServlet("/CookieExampleServlet")
    public class CookieExampleServlet extends HttpServlet {
    	private static final long serialVersionUID = 1L;
           
        /**
         * @see HttpServlet#HttpServlet()
         */
        public CookieExampleServlet() {
            super();
            // TODO Auto-generated constructor stub
        }
    
    	/**
    	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
    	 */
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		// TODO Auto-generated method stub
    		request.setCharacterEncoding("utf-8");
    		response.setContentType("text/html;charset=utf-8");
    		
    		PrintWriter out = response.getWriter();
    		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    		String nowTime = sdf.format(new Date());
    		
    		String lastVistTime = "";
    		int vistedCount = 0;
    		
    		//获取客户端所有浏览器保存的所有Cookie
    		Cookie[] cookies = request.getCookies();
    		
    		if(cookies != null) {
    			for(Cookie c : cookies) {
    				//判断是否为记录最近访问时间的Cookie
    				if("lastVistTime".equals(c.getName())) {
    					lastVistTime = c.getValue();
    				}
    				//判断是否为记录访问次数的Cookie
    				if("vistedCount".equals(c.getName())) {
    					vistedCount = Integer.valueOf(c.getValue());
    				}
    				
    			}
    		}
    		//若曾经访问过,输出上次访问时间
    		if(!"".equals(lastVistTime)) {
    			nowTime = URLEncoder.encode(lastVistTime, "utf-8");
    			out.println("上一次的访问时间为:"+lastVistTime);
    		}
    //		System.out.println(lastVistTime);
    		//输出访问次数
    		out.println("第"+(vistedCount+1)+"次访问");
    		//以本次访问时间重建同名新Cookie
    		nowTime = URLDecoder.decode(nowTime, "utf-8");
    		Cookie lastVistTimeC = new Cookie("lastVistTime", nowTime);
    		
    		
    		//设置最大存活时间:一年
    		lastVistTimeC.setMaxAge(365 * 24 * 60 * 60);
    		//以新访问次数重建同名新Cookie
    		Cookie vistCountC = new Cookie("vistedCount", String.valueOf(vistedCount+1));
    		//设置最大存活时间:一年
    		vistCountC.setMaxAge(360 * 24 * 60 * 60);
    		//将上述新建Cookie响应到客户端
    		response.addCookie(lastVistTimeC);
    		response.addCookie(vistCountC);
    	}
    
    	/**
    	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
    	 */
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		// TODO Auto-generated method stub
    		doGet(request, response);
    	}
    
    }
    
    
2.2、Session技术(一)
  • Session技术是指使用HttpSession对象实现会话跟踪技术,是一种在服务器端保持会话跟踪的解决方案。

  • HttpSession对象是javax.servlet.http.HttpSession接口的实例,也称为会话对象。该对象用来保存单个用户访问时的一些信息,是服务器在无状态的Http协议下用来识别和维护具体某个用户的主要方式。

  • HttpSession对象会在用户第一次访问服务器时由容器创建(注意:只有访问JSP、Servlet等程序时才会创建,只有访问HTML、IMAGE等静态资源并不会创建),当用户调用其失效方法(invalidate()方法)或超过其最大不活动时间时会失效。在此期间,用户与服务器之间的多次请求都属于同一个会话。

  • 服务器在创建会话对象时,会为其分配一个唯一的会话标识——SessionId,以“JSESSIONID”的属性名保存在客户端Cookie中,在用户随后的请求中,服务器通过读取Cookie中的JSESSIOSID属性值来识别不同的用户,从而实现对每个用户的会话跟踪。

  • HttpServletRequest接口提供了获取HttpSession对象的方法:

    • getSession():获取与客户端请求关联的当前的有效的Session,若没有Session关联则新建一个。

    • getSession(boolean create):获取与客户端请求关联的当前的有效的Session,若没有Session关联,当参数为真时,Session被新建,为假时,返回空值。

    • 【示例】获取HttpSession对象:

      HttpSession session = request.getSession();
      HttpSession session = request.getSession(true);
      
  • HttpSession接口提供了存取会话域属性和管理会话生命周期的方法:

    • void setAttribute(String key, Object value):以key/value的形式将对象保存在HttpSession对象中。

    • Object getAttribute(String key):通过key获取对象值。

    • void removeAttribute(String key):从HttpSession对象中删除指定名称key所对应的对象。

    • void invalidate():设置HttpSession对象失效。

    • int setMaxInactiveInterval(int interval):设定HttpSession对象的非活动时间(以秒为单位),若超过这个时间,HttpSession对象就会失效。

    • int getMaxInactiveInterval():获取HttpSession对象的有效非活动时间(以秒为单位)。

    • String getId():获取HttpSession对象标识sessionid。

    • long getCreationTime():获取HttpSession对象产生的时间,单位是毫秒。

    • long getLastAccessedTime():获取用户最后通过这个HttpSession对象送出的请求的时间。

    • 【示例】存取会话域属性:

      //存储会话域属性"username",值为"QST"
      session.setAttribute("username", "QST");
      //通过属性名"username"从会话域中获取属性值
      String uname = (String)session.getAttribute("username");
      //通过属性名将属性从会话域中移除
      session.removeAttribute("username");
      
    • 【示例】获取会话的最大不活动时间:

      int time = session.getMaxInactiveInterval(); //以秒为单位
      
    • 会话的最大不活动时间指会话超过次时间后不进行任何操作,会话自动失效的时间。

    • HttpSession对象的最大不活动时间与容器配置有关,对于Tomcat容器,默认事件为1800秒。

    • 通过web.xml设置会话的最大不活动时间:

      <session-config>
          	<!--单位为“分钟”-->
          <session-timeout>10</session-timeout>
      </session-config>
      
    • 通过会话对象的setMaxInactiveInterval()方法设置会话的最大不活动时间:

      session.setMaxInactiveInterval(600); //以秒为单位
      
    • 通过调用invalidate()方法让其立即失效。

      session.invalidate();
      
    • 服务器在执行会话失效代码后,会清除会话对象及其所有会话域属性,同时响应客户端浏览器清楚Cookie中的JSESSIONID。

    • 在实际应用中,此方法多用来实现系统中的“安全退出”,使客户端和服务器彻底结束次会话,清楚所有会话相关信息,防止会话劫持等黑客攻击。

      bookChoose.jsp

      <%@ page language="java" contentType="text/html; charset=UTF-8"
          pageEncoding="UTF-8"%>
      <!DOCTYPE html>
      <html>
      <head>
      <meta charset="UTF-8">
      <title>书籍选购</title>
      </head>
      <body>
      
      	<h2>请选择要买的书籍:</h2>
      	<form action="ShoppingCarServlet" method="post">
      		<p><input type="checkbox" name="book" value="Book-A">Book-A</p>
      		<p><input type="checkbox" name="book" value="Book-B">Book-B</p>
      		<p><input type="checkbox" name="book" value="Book-C">Book-C</p>
      		<p><input type="submit" value="submit"></p>
      	</form>	
      
      </body>
      </html>
      

      ShoppingCarServlet.java

      package com.learn.Demo04.servlet;
      
      import java.io.IOException;
      import java.util.HashMap;
      import java.util.Map;
      
      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;
      
      /**
       * Servlet implementation class ShoppingCarServlet
       */
      @WebServlet("/ShoppingCarServlet")
      public class ShoppingCarServlet extends HttpServlet {
      	private static final long serialVersionUID = 1L;
             
          /**
           * @see HttpServlet#HttpServlet()
           */
          public ShoppingCarServlet() {
              super();
              // TODO Auto-generated constructor stub
          }
      
      	/**
      	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
      	 */
      	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      		// TODO Auto-generated method stub
      		response.getWriter().append("Served at: ").append(request.getContextPath());
      	}
      
      	/**
      	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
      	 */
      	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      		// TODO Auto-generated method stub
      		response.setContentType("text/html;charset=utf-8");
      		request.setCharacterEncoding("UTF-8");
      		//获取Session对象
      		HttpSession session = request.getSession();
      		
      		//从会话域中获取ShoppingCar属性对象
      		//对象定义为Map类型,key为书名,value为购买数量
      		Map<String, Integer> car = (Map<String, Integer>)session.getAttribute("ShoppingCar");
      		//若会话域中无ShoppingCar属性对象,则实例化一个
      		if(car == null) {
      			car = new HashMap<String, Integer>();
      		}
      		//获取用户选择的书籍
      		String[] books = request.getParameterValues("book");
      		if(books != null && books.length > 0) {
      			for(String b : books) {
      				//判断是否在购物车中
      				if(car.get(b) != null) {
      					int num = car.get(b);
      					car.put(b, num+1);
      				}else {
      					car.put(b, 1);
      				}
      			}
      		}
      		//将更新后的购物车存储在会话域中
      		session.setAttribute("ShoppingCar", car);
      		response.sendRedirect("ShoppingListServlet");
      	}
      
      }
      
      

      ShoppingListServlet.java

      package com.learn.Demo04.servlet;
      
      import java.io.IOException;
      import java.io.PrintWriter;
      import java.util.Map;
      
      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;
      
      /**
       * Servlet implementation class ShoppingListServlet
       */
      @WebServlet("/ShoppingListServlet")
      public class ShoppingListServlet extends HttpServlet {
      	private static final long serialVersionUID = 1L;
             
          /**
           * @see HttpServlet#HttpServlet()
           */
          public ShoppingListServlet() {
              super();
              // TODO Auto-generated constructor stub
          }
      
      	/**
      	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
      	 */
      	@SuppressWarnings("unchecked")
      	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      		// TODO Auto-generated method stub
      		response.setContentType("text/html;charset=utf-8");
      		request.setCharacterEncoding("utf-8");
      		
      		PrintWriter out = response.getWriter();
      		
      		HttpSession session = request.getSession();
      		Map<String, Integer> car = (Map<String, Integer>) session.getAttribute("ShoppingCar");
      		
      		if(car != null && car.size() > 0) {
      			out.println("<p>你买了</p>");
      			//遍历显示购物车中的书籍名称和购买次数
      			for(String b : car.keySet()) {
      				out.println("<p>"+b+":"+car.get(b)+"本。</p>");
      			}
      		}else {
      			out.println("<p>你还没买呢!</p>");
      		}
      		out.println("<p><a href='bookChoose.jsp'>继续购买</a></p>");
      	}
      
      	/**
      	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
      	 */
      	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      		// TODO Auto-generated method stub
      		doGet(request, response);
      	}
      
      }
      
      
2.3、URL重写技术
  • URL重写是指服务器程序对接收的URL请求重新写成网站可以处理的另一个URL的过程。

  • URL重写技术是实现动态网站会话跟踪的重要保障。在实际应用中,当不能确定客户端浏览器是否支持Cookie的情况下,使用URL重写技术可以对请求的URL地址追加会话标识,从而实现用户的会话跟踪功能。

  • URL重写是通过HttpServletResponse的encodeURL()方法和encodeRedirectURL()方法实现

  • encodeURL()方法可以对任意请求的URL进行重写。

  • encodeRedirectURL()方法住哟啊对使用sendRedirect()方法的URL进行重写。URL重写方法根据请求信息中是否包含“Set-Cookie”请求头来决定是否进行重写,若包含该请求头,会将URL原样输出;若不包含,则会将会话标识重写到URL中。

  • 【示例】encodeURL()方法使用:

    out.println("<a href='"+response.encodeURL("RncodeURLServlet")+"'>链接请求</a>");
    
  • 【示例】encodeRedirectURL()方法使用:

    response.sendRedirect(response.encodeRedirectURL("EncodeURLServlet"));
    

    UrlRewritingServlet.java

    package com.learn.Demo04.servlet;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    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;
    
    /**
     * Servlet implementation class UrlRewritingServlet
     */
    @WebServlet("/UrlRewritingServlet")
    public class UrlRewritingServlet extends HttpServlet {
    	private static final long serialVersionUID = 1L;
           
        /**
         * @see HttpServlet#HttpServlet()
         */
        public UrlRewritingServlet() {
            super();
            // TODO Auto-generated constructor stub
        }
    
    	/**
    	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
    	 */
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		// TODO Auto-generated method stub
    		response.setContentType("text/html;charset=utf-8");
    		PrintWriter out = response.getWriter();
    		//获取会话对象
    		HttpSession session = request.getSession();
    		
    		//对CommomServlet和UseRedirectServlet两个请求地址进行URL重写
    		String link1 = response.encodeURL("CommonServlet");
    		String link2 = response.encodeURL("UseRedirectServlet");
    		//使用超链接形式对URL进行重写地址请求
    		out.println("<p><a href='"+link1+"'>对一个普通Servlet的请求</a></p>");
    		out.println("<a href='"+link2+"'>对一个含有重定向代码的Servlet的请求</a>");
    	}
    
    	/**
    	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
    	 */
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		// TODO Auto-generated method stub
    		doGet(request, response);
    	}
    
    }
    
    

    CommonServlet.java

    package com.learn.Demo04.servlet;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    /**
     * Servlet implementation class CommonServlet
     */
    @WebServlet("/CommonServlet")
    public class CommonServlet extends HttpServlet {
    	private static final long serialVersionUID = 1L;
           
        /**
         * @see HttpServlet#HttpServlet()
         */
        public CommonServlet() {
            super();
            // TODO Auto-generated constructor stub
        }
    
    	/**
    	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
    	 */
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		// TODO Auto-generated method stub
    		PrintWriter out = response.getWriter();
    		//获取URL重写传递来的会话标识值
    		String sessionId = request.getSession().getId();
    		out.println(sessionId);
    	}
    
    	/**
    	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
    	 */
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		// TODO Auto-generated method stub
    		doGet(request, response);
    	}
    
    }
    
    

    UseRedirectServlet.java

    package com.learn.Demo04.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;
    
    /**
     * Servlet implementation class UseRedirectServlet
     */
    @WebServlet("/UseRedirectServlet")
    public class UseRedirectServlet extends HttpServlet {
    	private static final long serialVersionUID = 1L;
           
        /**
         * @see HttpServlet#HttpServlet()
         */
        public UseRedirectServlet() {
            super();
            // TODO Auto-generated constructor stub
        }
    
    	/**
    	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
    	 */
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		// TODO Auto-generated method stub
    		//对重定向的URL进行重写
    		String encodeURL = response.encodeURL("CommonServlet");
    		//进行重定向
    		response.sendRedirect(encodeURL);
    	}
    
    	/**
    	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
    	 */
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		// TODO Auto-generated method stub
    		doGet(request, response);
    	}
    
    }
    
    
  • URL重写技术应用的注意事项

    • 如果应用需要使用URL重写,那么必须对应用的所有请求(包括所有的超链接、表单的action属性和重定向地址)都进行重写,从而将jsessionid维持下来。
    • 由于浏览器对URL地址长度的限制,特别是在对含有查询参数的GET请求进行URL重写时,需要注意其总长度。
    • 由于静态页面不能进行会话标识的传递,因此所有的URL地址都必须为动态请求地址。
2.4、隐藏表单域
  • 利用Form表单的隐藏表单域,可以在完全脱离浏览器对Cookie的使用限制,并且在用户无法从页面显示看到隐藏标识的情况下,将标识随请求一起传送给服务器处理,从而实现会话的跟踪。

  • 【示例】在Form表单中定义隐藏域

    <form action="xx" method="post">
        <input type="hidden" name="userID" value="10010">
        <input type="submit" value="submit">
    </form>
    
  • 在服务器端通过HttpServletRequest对象获取隐藏表单域的值

    String flag = request.getParameter("userID");
    

JSP

五、JSP语法

1、JSP概述
1.1 第一个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>
<h1>显示当前系统时间:</h1>
	<%
		java.util.Date date = new java.util.Date();
		out.print("当前时间是:"+date.toLocaleString());
	%>

</body>
</html>
1.2、JSP执行原理
  • 客户端请求JSP文件>>Web服务器将JSP文件翻译成.java文件>>再编译成.class文件>>再执行HTML响应>>响应客户端请求

  • 当同一个JSP页面再次被请求时,只要该JSP文件未被改动,容器将直接调用已装载的字节码文件,而不会再执行翻译和编译过程

    客户端请求JSP文件>>Web服务器将查找.class文件>>再执行HTML响应>>响应客户端请求 。

1.3、JSP基本结构
  • JSP页面就是带有JSP元素的常规Web页面,它有模板文本和JSP元素组成。
  • 在一个JSP页面中,所有非JSP元素的内容称为模板文本(template text)。模板文本可以是任何文本,如:HTML、XML,甚至可以是纯文本。
    • JSP并不依赖于HTML,它可以采用任何一种标记语言。模板文本通常被直接传递给浏览器。在处理一个JSP页面请求时,模板文本和JSP元素所生成的内容会合并,合并后的结果将作为响应内容发送给浏览器。
  • JSP有三种类型的元素:脚本元素、指令元素和动作元素
    • 脚本元素(Scripting element):
      • 脚本:<% %>
      • 表达式:<%= %>
      • 声明:<%! %>
      • 注释:<%-- --%>
    • 指令元素(Directive element):
      • <%@page
      • <%@include
      • <%@taglib
    • 动作元素(Action element):
      • < jsp:include>
      • < jsp:forward>
      • < jsp:param>
      • < jsp:useBean>
2、脚本元素
2.1、JSP脚本
  • 脚本元素允许用户将一小段的代码(一般是java代码)添加到JSP页面中,例如:可以加入一个if语句,以根据具体情况产生不同的HTML代码

  • 脚本元素在页面被请求执行

  • 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>
    	<%
    		String email = "fengjj@itshixun.com";
    		if(email.indexOf("@") == -1){
    	%>
    	您的邮箱地址没有@符号
    	<br>
    	<%
    		}else if(email.indexOf(" ") != -1){
    	%>
    	您的邮箱地址含有非法空格
    	<%
    		}else if(email.indexOf("@") != email.lastIndexOf("@")){
    	%>
    	您的邮箱地址含有多个@符号
    	<%
    		}else{
    	%>
    	您的邮箱地址书写正确
    	<%
    		}
    	%>
    </body>
    </html>
    
2.2、JSP表达式
  • JSP中的表达式可以被看作一种简单的输出形式,需要注意的是,表达式一定要有一个可以输出的值。

  • 【示例】使用JSP表达式输出九九乘法表

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>九九乘法表</title>
    </head>
    <body>
    <% for(int i=1;i<10;i++){%>
    <p>
    <%	for(int j=1;j<=i;j++){ %>
    <%= 	j+"*"+i+"="+(j*i)%>
    <%		} %>
    <%} %>
    </p>
    </body>
    </html>
    
2.3、JSP的声明
  • JSP中的声明用于声明一个或多个变和方法,并不输出任何的文本到输出流。在声明元素中声明的变量和方法将在JSP页面初始化时进行初始化。

    <%@page import="java.util.Date"%>
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>页面的访问次数</title>
    </head>
    <body>
    <%! int count = 0; %>
    <%! synchronized void setCount(){
    		count++;
    	}
    	%>
    <% String date = new Date().toLocaleString(); %>
    <%
    setCount();
    %>
    您是第<%=count %>个人访问本页面的人,访问时间是:<%=date %>
    </body>
    </html>
    
  • JSP声明变量与脚本变量的区别:

    • 声明变量将作为JSP翻译生成的Servlet的属性,所有对该JSP的请求将共享次变量。
    • 脚本变量将作为JSP翻译生成的Servlet的_JSPService()方法中的局部变量,每个对该JSP请求将被分配给一个同名的此变量。
2.4、JSP注释
  • 使用" < %-- --%>"对内容进行注释
3、指令元素
  • JSP指令用来向JSP容器提供编译信息

  • 指令并不向客户端产生任何输出,所有的指令都只在当前页面中有效

  • JSP指令元素包括

    • page指令
    • include指令
    • taglib指令
3.1、page指令
  • page指令描述了和页面相关的信息,如:导入所需类包、指明输出内容类型、控制Session等

  • page指令一般位于JSP页面的开头部分,在一个JSP页面中,page指令可以出现多次,但是在每个page指令中,每一种属性却只能出现一次,重复的属性设置将覆盖掉先前的设置

  • 【语法】

    <%@page 属性列表%>
    
  • 【示例】page指令

    <%@page language="java" contentType="text/html;charset=utf-8"%>
    
  • page指令的常见属性及其含义:

    • language:设定JSP页面使用的脚本语言,默认为Java,目前只可使用Java语言。
    • import:指定导入的Java软件包或类名列表,若有多个类,中间用逗号隔开。
    • isThreadSafe:指定JSP容器执行JSP程序的模式。有两种模式:一种为默认值为true,代表JSP容器会以多线程方式运行JSP页面;另一种模式设定值为false,JSP容器会以单线程方式运行JSP页面。建议采用isThreadSafe="true"模式。
    • contentType:指定MIME类型和JSP页面响应时的编码方式,默认为"text/html;charset=ISO8859-1"。通过设置contentType属性的MIME类型,可以改变JSP输出内容的处理方式,从而实现一些特殊的功能。例如:可以将输出内容指定为Word、Excel类型的文件、将二进制数据生成图像等。
    • pageEncoding:指定JSP文件本身的编码方式,例如pageEncoding=“UTF-8”。
    • session:指定JSP页面是否使用session对象,值为"true|false",默认为false。
    • errorPage:设定JSP页面发生异常时重新指向的页面URL,指向的页面文件要把isErrorPage设成true。
    • isErrotPage:指定此JSP页面是否作为处理异常错误的网页,值为"true|false",默认为false。
    • isELIgnored:指定JSP页面是否忽略EL表达式,值为"true|false",默认为false。
    • buffer:指定输出流是否需要缓冲,默认值是8kb,与autoFlush一起使用,确定是否自动刷新输出缓冲,如果设成true,则当输出缓冲区满的时候,刷新缓冲区而不是抛出一个异常。
    • autoFlush:如果页面缓冲区满时要自动刷新输出,则设置为true;否则,当页面缓冲区满时要抛出一个异常,则设置为false。
  • 【示例】使用import属性导入包和类:

    <%@page import="java.util.*"%>
    
  • 【示例】将HTML代码编写的表格转换成Microsoft Office Excel类型文件显示。

    <%@ page language="java" contentType="application/vnd.ms-excel; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
    <table border=1>
    <tr><td>客户编号</td><td>客户名称</td></tr>
    <tr><td>10001</td><td>张三</td></tr>
    <tr><td>10002</td><td>李四</td></tr>
    </table>
    </body>
    </html>
    
3.2、include指令
  • include指令的作用是在页面翻译期间引入另一个文件,被包含的文件可以是JSP、HTML或文本文件。

  • 【语法】

    <%@include file="文件"%>
    
  • 【示例】

    includeDeriective.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>
    <h1>以下包含头文件信息</h1>
    <%@include file="head.jsp" %>
    
    <h1>此处为页面正文信息</h1>
    
    <h1>以下包含底部文件信息</h1>
    <%@include file="tail.html" %>
    </body>
    </html>
    

    head.jsp

    <%@page import="java.util.Calendar"%>
    <%@ 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>
    
    	<%if(Calendar.getInstance().get(Calendar.AM_PM) == Calendar.AM){ %>
    	上午好!
    	<%}else{ %>
    	下午好!
    	<%} %>
    
    </body>
    </html>
    

    tail.html

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
    Copyright @2005-2015
    </body>
    </html>
    
3.3、taglib指令
  • taglib指令用于指定JSP页面所使用的标签库,通过该指令可以在JSP页面中使用标签库中的标签。

  • 【语法】

    <%@taglib uri="标签库URI" prefix="标签前缀" %>
    
  • 【示例】

    <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    
  • 对上述示例指定的标签库,可以使用如下代码进行标签引用:

    <c:out value="hello world"/>
    
    • 其中“c”为标签的前缀,在JSP中有些前缀已经保留,如果自定义标签,这些标签前缀不可使用。保留的前缀有:jsp、jspx、java、javax、servlet、sun和sunw。
4、动作元素
  • 在JSP中可以使用XML语法格式的一些特殊标记来控制行为,称为JSP标准动作(Standard Action)。
  • 利用JSP动作可以实现例如:动态地插入文件、调用JavaBean组件、重定向页面等功能。
4.1、include动作元素
  • < jsp:include>用于在页面运行时引入一个静态或动态地页面,也称为动态包含

  • 当容器把JSP页面翻译成Java文件时,并不会把JSP页面中由include动作指令指定的文件与原JSP页面合并成一个新页面,而是告诉Java解释器,这个文件在JSP运行时才被处理

  • < jsp:include>元素如果包含的文件是普通的文本文件,就将文件的内容发送到客户端,由客户端负责显示;如果包含的文件是JSP文件,JSP容器就执行这个文件,然后将执行结果发送到客户端,由客户端负责显示这些结果

  • < jsp:include>动作可以包含一个或多个< jsp:param>子动作,用于向要引入的页面传递数据

  • 【语法】

    <jsp:include page="urlSpec" flush="true"/>
    

    <jsp:include page="urlSpec" flush="true">
    	<jsp:param name="name" value="value"/>
    </jsp:include>
    

    其中:

    • page指定引入文件的地址
    • flush="true"表示设定是否自动刷新缓冲区,默认为false,可省略;在页面包含大量数据时,为缩短客户端延迟,可将一部分内容先行输出
    • name指定传入包含文件的变量名
    • value指定传入包含文件的变量名对应的值
  • 【示例】include动作

    <jsp:include page="show.jsp">
    	<jsp:param name="name" value="qst"/>
    	<jsp:param name="password" value="123"/>
    </jsp:include>
    
  • 计算梯形面积:

    viewLaderArea.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>
    <jsp:include page="countLaderArea.jsp">
    	<jsp:param value="10" name="upper"/>
    	<jsp:param value="30" name="base"/>
    	<jsp:param value="20" name="height"/>
    </jsp:include>
    </body>
    </html>
    

    countLaderArea.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>
    <%
    double  upper = Double.parseDouble(request.getParameter("upper"));
    double base = Double.parseDouble(request.getParameter("base"));
    double height = Double.parseDouble(request.getParameter("height"));
    double area = (upper + base) * height / 2;
    %>
    <%=area %>
    </body>
    </html>
    
4.2、forward动作元素
  • < jsp:forward>用于引导客户端的请求到另一个页面或者另一个Servlet

    < jsp:forward>动作可以包含一个或多个< jsp:param>子动作,用于向所转向的资源传递参数

  • 【语法】

    <jsp:forward page="relativeURLSpec"/> 
    

    <jsp:forward page="relativeURLSpec">
    	<jsp:param name="name" value="value"/>
    </jsp:forward>
    

    其中:

    • page指定转发请求的相对地址
    • < jsp:pram>中的name指定向转向页面传递的参数名称
    • < jsp:pram>中的name指定向转向页面传递的参数名称对应的值
  • 【示例】

    <jsp:forward page="second.jsp">
    	<jsp:param name="step" value="1"/>
    </jsp:forward>
    

    注意:< jsp:forword>的功能和Servlet的RequestDispatcher对象的forward方法类似,调用者和被调用者共享同一个request对象

4.3、useBean动作元素
  • < jsp:useBean>是JSP中一个非常重要的动作元素,使用这个动作元素,JSP可以动态使用JavaBean组件来扩充JSP的功能,由于JavaBean在开发上以及< jsp:useBena>在使用上简单明了,使得JSP与其他动态网页开发技术有了本质的区别。

  • 【语法】

    <jsp:useBean id="name" class="className" scope="page|request|session|application"/>
    

    <jsp:useBean id="name" type="typeName" scope="page|request|session|application"/>
    

    其中:

    • id指定该JavaBean实例的变量名,通过id可以访问这个实例
    • class指定JavaBean的类名。容器根据class指定的类调用其他构造方法来创建这个类的实例;
    • scope指定JavaBean的作用范围,可以使用page、request、session和application。默认值为page
    • type指定JavaBean对象的类型,通常在查找已存在的JavaBean时使用,这时使用type将不会产生新的对象
  • 【示例】在request对象中定义名为user的User的UserBean对象

    <jsp:useBean id="user" class="com.qst.ch03.modle.UserBean" scope="request"/>
    
4.4、setProperty和getProperty动作元素
4.4.1、setProperty
  • < jsp:setProperty>动作元素用于向一个JavaBean的属性赋值,需要和< jsp:useBean>动作一起使用

  • 【语法】

    <jsp:setProperty name="beanName" property="propertyName" value="propertyValue"/>
    

    <jsp:setProperty name="beanName" property="propertyName" param="paramName"/>
    

    其中:

    • name指定JavaBean对象名,与useBean动作中的id相对应
    • property指定JavaBean中需要赋值的属性名
    • value指定要为属性设置的值
    • param指定请求中的参数名(如:表单传值或URL传值),并将该参数的值赋给property所指定的属性。
  • 【示例】取出请求中名为loginName的参数值赋给user对象的userName属性

    <jsp:useBean id="user" class="com.qst.ch01.modle.UserBean" scope="request"/>
    <jsp:setProperty name="user" preperty-"userName" param="loginName"/>get
    
4.4.2、getProperty
  • < jsp:getProperty>动作用于从一个JavaBean中得到某个水星的值,不管原先这个属性是什么类型的,都见被转换成一个String类型的值

  • 【语法】

    <jsp:getProperty name="user" property="userName"/>
    

    其中:

    • name指定JavaBean对象名,与useBean动作中的id相对应
    • property指定JavaBean中需要访问的属性名
  • 【示例】从user对象中取出属性userName的值

    <jsp:getProperty name="user" property="userName"/>
    

六、内置对象

  • JSP内置对象是指在JSP页面中,不用声明就可以在脚本和表达式中直接使用的对象。

  • JSP内置对象也称为隐含对象,它提供了Web开发常用的功能,为了提高开发效率,JSP规范定义了内置对象

  • JSP内置对象有如下特点:

    • 内置对象由Web容器自动载入,不需要实例化。
    • 内置对象通过Web容器来实现和管理。
    • 在所有JSP页面中,直接调用内置对象都是合法的。
  • JSP规范定义了9种内置对象:

    对象名称类型功能说明
    requestjavax.servlet.http.HttpServletRequest请求对象,提供客户端Http请求数据的访问
    responsejavax.servlet.http.HttpServletResponse响应对象,用来向客户端输出响应
    outjavax.servlet.jsp.JspWriter输出对象,提供输出流访问
    sessionjavax.servlet.http.HttpSession会话对象,用来保存服务器与每个客户端会话过程中的信息
    applicationjavax.servlet.ServletContext应用程序对象,用来保存整个应用环境的信息
    pageContextjavax.servlet.jsp.PageContext页面上下文对象,用于存储当前JSP页面的相关信息
    configjavax.servlet.ServletConfig页面配置对象,JSP页面的配置信息对象
    pagejavax.servlet.jsp.HttpJspPage当前JSP页面对象,即this
    exceptionjavax.lang.Throwable异常对象,用于处理JSP页面中的错误
1、与Input/OutPut(输入/输出)有关的内置对象
  • 与Input/OutPut(输入/输出)有关的隐含对象包括:request对象、response对象和out对象,这类对象主要来作为客户端和服务器间的通信桥梁
    • request对象表示客户端对服务器端发送的请求。
    • response对象表示服务器对客户端的响应。
    • out对象负责把处理结果输出到客户端。
1.1、request内置对象
  • 主要用于接收客户端通过Http协议传送给服务器端的数据。

  • 该对象与Servlet中的请求对象为同一对象。

  • 该对象作用域为一次request请求。

  • 该对象拥有HttpServletRequest接口的所有方法,常用方法有:

    • void setCharacterEncoding(String charset):设置请求体参数的解码字符集。
    • String getParameter(String name):根据参数名获取单一参数值。
    • String[] getParameterValues(String name):根据参数名获取一组参数值。
    • void setAttribute(String name, Object value):以名/值的方式存储请求域属性。
    • Object getAttribute(String name):根据属性名获取存储的对象数据。
  • 【实例】

    • 获取信息

      login.jsp

      <%@ page language="java" contentType="text/html; charset=UTF-8"
          pageEncoding="UTF-8"%>
      <!DOCTYPE html>
      <html>
      <head>
      <meta charset="UTF-8">
      <title>登录</title>
      </head>
      <body>
      <form action="loginValidate.jsp" method="post">
      <p>用户名:<input name="username" type="text" ></p>
      <p>密&nbsp;&nbsp;码:<input name="password" type="password" ></p>
      <p><input name="submit" type="submit" value="提交"></p>
      </form>
      </body>
      </html>
      

      loginParameter.jsp

      <%@ page language="java" contentType="text/html; charset=UTF-8"
          pageEncoding="UTF-8"%>
      <!DOCTYPE html>
      <html>
      <head>
      <meta charset="UTF-8">
      <title>获取请求登录参数</title>
      </head>
      <body>
      <%
      //设置POST请求编码
      request.setCharacterEncoding("UTF-8");
      //获取请求参数
      String username = request.getParameter("username");
      String password = request.getParameter("password");
      
      out.println("参数username的值为:"+username+"<br>");
      out.println("参数password的值为:"+password+"<br>");
      
      %>
      </body>
      </html>
      
    • 验证信息

      login.jsp

      <%@ page language="java" contentType="text/html; charset=UTF-8"
          pageEncoding="UTF-8"%>
      <!DOCTYPE html>
      <html>
      <head>
      <meta charset="UTF-8">
      <title>登录</title>
      </head>
      <body>
      <%
      //从请求域属性errorMsg获取错误信息
      String error = (String)request.getAttribute("errorMsg");
      if(error != null){
      	out.print("<font color='red'>"+error+"</font>");
      }
      %>
      <form action="loginValidate.jsp" method="post">
      <p>用户名:<input name="username" type="text" ></p>
      <p>密&nbsp;&nbsp;码:<input name="password" type="password" ></p>
      <p><input name="submit" type="submit" value="提交"></p>
      </form>
      </body>
      </html>
      

      loginValidate.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>
      <%
      //设置POST请求编码
      request.setCharacterEncoding("UTF-8");
      //获取请求参数
      String username = request.getParameter("username");
      String password = request.getParameter("password");
      
      StringBuffer errorMsg = new StringBuffer();
      //参数信息验证
      if("".equals(username)){
      	errorMsg.append("用户名不能为空<br>");
      }
      if("".equals(password)){
      	errorMsg.append("密码不能为空<br>");
      }
      //将错误信息保存在请求域属性中
      request.setAttribute("errorMsg", errorMsg.toString());
      
      if(errorMsg.toString().equals("")){
      	out.print("信息验证成功<br>");
      }else{
      	%>
      	<jsp:forward page="login.jsp"></jsp:forward>
      	<%
      }
      %>
      </body>
      </html>
      
1.2、response内置对象
  • 主要用来将JSP处理后的结果传回到客户端。与Servlet中的响应对象为同一对象

  • response对象拥有HttpServletResponse接口的所有方法,常用方法有:

    • void setCharsetType(String name):设置响应内容和字符编码。
    • void sendRedirect(String url):重定向到指定的URL资源。
  • 【实例】

    login.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>登录</title>
    </head>
    <body>
    <%
    //从请求域属性errorMsg获取错误信息
    String error = (String)request.getAttribute("errorMsg");
    if(error != null){
    	out.print("<font color='red'>"+error+"</font>");
    }
    %>
    <form action="loginValidate.jsp" method="post">
    <p>用户名:<input name="username" type="text" ></p>
    <p>密&nbsp;&nbsp;码:<input name="password" type="password" ></p>
    <p><input name="submit" type="submit" value="提交"></p>
    </form>
    </body>
    </html>
    

    loginValidate.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>
    <%
    //设置POST请求编码
    request.setCharacterEncoding("UTF-8");
    //获取请求参数
    String username = request.getParameter("username");
    String password = request.getParameter("password");
    
    StringBuffer errorMsg = new StringBuffer();
    //参数信息验证
    if("".equals(username)){
    	errorMsg.append("用户名不能为空<br>");
    }
    if("".equals(password)){
    	errorMsg.append("密码不能为空<br>");
    }
    //将错误信息保存在请求域属性中
    request.setAttribute("errorMsg", errorMsg.toString());
    
    if(errorMsg.toString().equals("")){
    	response.sendRedirect("main.jsp?username="+username);
    }else{
    	%>
    	<jsp:forward page="login.jsp"></jsp:forward>
    	<%
    }
    %>
    </body>
    </html>
    

    main.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>主界面</title>
    </head>
    <body>
    <p>欢迎!<%=request.getParameter("username") %></p>
    </body>
    </html>
    
1.3、out内置对象
  • out对象主要用来控制管理输出的缓冲区(buffer)和输出流(output stream)向客户端页面输出数据。
  • out对象的方法可以分为两类:
    • 数据的输出
    • 缓冲区的处理
2、与Context有关的内置对象
  • session对象表示浏览器与服务器的会话上下文对象。
  • application对象表示应用程序上下文环境。
  • pageContext对象表示当前JSP页面上下文环境。
2.1、session对象
  • 表示浏览器与服务器之间的一次会话。

  • 一次会话的含义是:从客户端浏览器连接服务器开始,在关闭浏览器或主动退出后,会话结束。这个过程可以包含浏览器与服务器之间的多次请求与响应。

  • session对象具有HttpSession接口的所有方法,常用方法如下:

    • void setAttribute(String name, Object value):以名/值对的方式存储session属性。
    • Object getAttribute(String name):根据属性名获取属性值。
    • void invalidate():使session对象失效,释放所有的属性空间。
  • 【实例】安全登出

    login.jsp

    loginValidate.jsp

    main.jsp

    logout.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>
    <%
    session.invalidate();
    %>
    </body>
    </html>
    
2.2、application对象
  • 表示当前应用程序运行环境,用来获取应用程序上下文环境中的信息。

  • 该对象在容器启动时实例化,在容器关闭时销毁。作用域为整个Web容器的生命周期。

  • 该对象具有ServletContext接口的所有功能,常用方法如下:

    • void setAttribute(String name, Object value):以名/值对的方式存储application 域属性。
    • Object getAttribute(String name):根据属性名获取属性值。
    • void removeAttribute(String name):更根据属性名从application域中移除属性。
  • 【实例】留言板

    <%@page import="java.util.Vector"%>
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>用户留言板</title>
    <script type="text/javascript">
    	function validate() {
    		var uname = document.getElementById("username");
    		var massage = document.getElementById("message");
    		if(uname.value==""){
    			alert("请输入名字!");
    			uname.focus();
    			return false;
    		}else if(message.value == ""){
    			alert("请输入留言!");
    			message.focus();
    			return false;
    		}
    		return true;
    	}
    </script>
    </head>
    <body>
    	<p>请留言</p>
    	<form action="guestBook.jsp" method="post" οnsubmit="return validate();" >
    		<p>请输入名字:<input type="text" name="username" id="username"></p>
    		<p>请输入留言:<textarea name="message" id="message" cols="50" rows="3"></textarea></p>
    		<p><input type="submit" value="提交"></p>
    	</form>
    	<hr>
    	<p>留言内容</p>
    	<%
    	//设置解码字符集
    	request.setCharacterEncoding("UTF-8");
    	//获取留言信息
    	String username = request.getParameter("username");
    	String message = request.getParameter("message");
    	//从application域属性messageBook中获取留言本
    	Vector<String> book = (Vector<String>)application.getAttribute("messageBook");
    	if(book == null){
    		book = new Vector<String>();
    	}
    	if(username != null && message != null){
    		String info = username+"#"+message;
    		book.add(info);
    		application.setAttribute("messageBook", book);
    	}
    	//遍历显示所有的用户留言
    	if(book.size() > 0){
    		for(String b : book){
    			String[] arr = b.split("#");
    			out.print("<p>姓名:"+arr[0]+"<br>留言:"+arr[1]+"</p>");
    		}
    	}else{
    		out.print("没有留言!");
    	}
    	%>
    </body>
    </html>
    
2.3、pageContext对象
  • pageContext用以获取当前JSP页面的相关信息。

  • pageContext对象作用范围为当前JSP页面。

  • pageContext对象可以访问当前JSP页面所有的内置对象,访问方法如下:

    • ServletRequest getRequest():获取当前JSP页面的请求对象。
    • ServletResponse getResponse():获取当前JSP页面的响应对象。
    • HttpSession getSession():获取和当前JSP页面有联系的会话对象。
    • ServletConfig getSevletConfig():获取当前页面的ServletConfig对象。
    • ServletContext getServletContext():获取当前页面的运行环境对象。
    • Object getPage():获取当前JSP页面的Servlet实体
    • Exception getException():获取当前JSP页面的异常对象,不过此页面的page指令的isErrorPage属性要设为true。
    • JspWriter getOut():获取当前JSP页面的输出流
  • pageContext对象存取域属性的方法:

    • Object getAttribute(String name, int scope):获取范围为scope,名为name的属性对象。

    • void setAttribute(String name, Object value, int scope):以名、值对的方式存储scope范围域属性。

    • void removeAttribute(String name, int scope):从scope范围移除名为name的属性。

    • Enumeration getAttributeNameInScope(int scope):从scope范围中获取所有属性的名称。

      • 存取域属性的方法setAttribute()中scope参数被定义为四个常量,分别代表四种作用域范围:

        PAGE_SCOPE = 1代表paga范围
        REQUEST_SCOPE = 2代表request范围
        SESSION_SCOPE = 3代表session范围
        APPLICATION_SCOPE = 4代表application范围
  • 【实例】pageContext对象存取域属性

    <%@ 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>
    <%
    	pageContext.getSession().setAttribute("sessionKey", "Fastlink");
    	Object o = pageContext.getAttribute("sessionKey", pageContext.SESSION_SCOPE);
    %>
    <%=o %>
    </body>
    </html>
    
3、与Servlet有关的内置对象
  • page对象和config对象,page对象表示JSP翻译后的Servlet对象;config对象表示JSP翻译后的Servlet的ServletConfig对象。
3.1、page内置对象
  • page对象即this,代表JSP本身,更准确地说它代表JSP被翻译后地Servlet,因此它可以调用Servlet类所定义的方法。page对象很少在JSP中使用。

  • 演示page对象获取页面page指令的info属性指定地页面说明信息

    <%@page import="org.eclipse.jdt.internal.compiler.ast.ThisReference"%>
    <%@ page language="java" contentType="text/html; charset=UTF-8" info = "page内置对象的使用"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
    <p>使用"this"获取的页面说明信息:<%=this.getServletInfo() %></p>
    <p>使用"page"获取的页面说明信息:<%=((HttpJspPage)page).getServletInfo() %></p>
    </body>
    </html>
    
3.2、config内置对象
  • config内置对象即页面配置对象,表示当前Jsp页面翻译后的Servlet的ServletConfig对象,存放着一些初始的数据结构。

  • config对象和page对象一样很少被用到。

  • 演示JSP通过config对象获取初始化参数:

    <%@ 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>
    <%
    String initParam = config.getInitParameter("init");
    out.println(initParam);
    %>
    </body>
    </html>
    
4、与Error有关的内置对象
4.1、exception内置对象
  • 当JSP网页有错误时会产生异常,exception对象就用来对这个异常做处理。

  • 该对象为异常对象,表示页面中产生的异常

  • 如果一个JSP页面要应用此对象,必须将此页面中额page指令的isErrorPage属性值设为True,否则无法编译。

  • exception对象是java.lang.throwable的对象

  • 演示exception对象对页面异常的处理

    calculate.jsp

     <%@ page language="java" contentType="text/html; charset=UTF-8" errorPage="error.jsp" isELIgnored="false"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>计算</title>
    </head>
    <body>
    <%
    	int a, b;
    	a = 10;
    	b = 0;
    	int c = a / b; 
    %>
    </body>
    </html>
    

    error.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8" isELIgnored="true"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html>
    <html>
    <head>
    <meta http-equiv="Context-Type" content="text/html charset=UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
    <%
    	exception.printStackTrace(response.getWriter());
    %>
    <hr>
    <%=exception.getMessage() %>
    </body>
    </html>
    
5、JSP的四种作用域
  • 对象的生命周期和可访问性称之为作用域(scope),在JSP中有四种作用域:页面域、请求域、会话域和应用域。

    • 页面域(page scope):页面域的生命周期是指页面执行期间。存储在页面域的对象只对于它所在的页面是可访问的。
    • 请求域(request scope):请求域的生命周期是指一次请求过程,包括被请求转发(forward)或被包含(include)的情况。存储在请求域中的对象只有在此请求过程中才可以被访问。
    • 会话域(session scope):会话域的生命周期是指某个客户端与服务器所连接的时间;客户端在第一次访问服务器时创建会话,在关闭浏览器或主动退出后,会话结束。存储在会话域中的对象在整个会话期间(可能包含对此请求)都可以被访问到。
    • 应用域(application scope):应用域的生命周期是指从服务器开始执行服务到服务器关闭为止,是四个作用域中时间最长的。存储在应用域中的对象在整个应用程序运行期间可以被所有JSP和Servlet共享访问,在使用时要特别注意存储数据的大小和安全性,否则可能造成服务器负载过重和线程安全。
  • JSP的四种作用域分别对应pageContext、request、session和application四个内置对象

  • 四个内置对象都通过setAttribute(String name, Object value)方法来存储属性,通过getAttribute(String nama)来获取属性,从而实现属性对象在不同作用域的数据分享。

    visitCount.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>访问统计</title>
    </head>
    <body>
    <%
    	int pageCount = 1;
    	int sessionCount = 1;
    	int applicationCount = 1;
    	
    	//页面域计数
    	if(pageContext.getAttribute("pageCount") != null){
    		pageCount = Integer.parseInt(pageContext.getAttribute("pageCount").toString());
    		pageCount++;
    	}
    	pageContext.setAttribute("pageCount", pageCount);
    	//会话域计数
    	if(session.getAttribute("sessionCount") != null){
    		sessionCount = Integer.parseInt(session.getAttribute("sessionCount").toString());
    		sessionCount++;
    	}
    	session.setAttribute("sessionCount", sessionCount);
    	//应用域计数
    	if(application.getAttribute("applicationCount") != null){
    		applicationCount = Integer.parseInt(application.getAttribute("applicationCount").toString());
    		applicationCount++;
    	}
    	application.setAttribute("applicationCount", applicationCount);
    %>
    <p>页面域计数:<%=pageCount %></p>
    <p>会话域计数:<%=sessionCount %></p>
    <p>应用域计数:<%=applicationCount %></p>
    </body>
    </html>
    

七、JSP与JavaBean

1、JavaBean规范
  • 一个标准的JavaBean需要遵循一下规范:

    • JavaBean是一个公开的(public)类,以便被外部程序访问。
    • 具有一个午餐的构造方法(即一般类中默认的构造方法),以便被外部程序实例化时调用。
    • 提供setter方法和getter方法,以便让外部程序设置和获取其属性。
  • 凡是符合上述规范的Java类都可以称为JavaBean。

  • 【示例】封装商品价格计算的JavaBean

    package com.Demo06.bean;
    
    public class ProductBean {
    	private String name;
    	private int num;
    	private double price;
    	
    	
    	
    	public ProductBean() {
    		super();
    		// TODO Auto-generated constructor stub
    	}
    	
    	
    	public ProductBean(String name, int num, double price) {
    		super();
    		this.name = name;
    		this.num = num;
    		this.price = price;
    	}
    	
    	public String getName() {
    		return name;
    	}
    	public void setName(String name) {
    		this.name = name;
    	}
    	public int getNum() {
    		return num;
    	}
    	public void setNum(int num) {
    		this.num = num;
    	}
    	public double getPrice() {
    		return price;
    	}
    	public void setPrice(double price) {
    		this.price = price;
    	}
    	
    	public double getTotalPrice() {
    		return this.num * this.price;
    	}
    
    }
    
    
2、JSP中使用JavaBean
  • JSP提供三个动作元素:

    • < jsp:useBean>:创建或查找JavaBean实例对象。
    • < jsp:setProperty>:设置JavaBean对象的属性
    • < jsp:getProperty>:获取JavaBean对象的属性值
  • 【示例】使用Java脚本访问JavaBean

    <%@page import="com.Demo06.bean.ProductBean"%>
    <%@ 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>
    <%
    	Object obj = pageContext.getAttribute("product");
    	ProductBean product = null;
    	if(obj == null){
    		product = new ProductBean();
    	}
    	product.setName("可比克");
    	product.setNum(21);
    	product.setPrice(21.2);
    %>
    <%=product.getTotalPrice() %>
    </body>
    </html>
    
2.1、< jsp:useBean>元素
  • < jsp:useBean>元素yon关于在某个指定的作用域范围内查找一个指定名称的JavaBean对象,如果存在则直接返回该JavaBean对象的引用,如果不存在则实例化一个新的JavaBean对象,并将它按照指定的名称存储在指定的作用域范围内。

  • < jsp:useBean>元素的语法格式:

    <jsp:useBean id="beanInstanceName" class="package.class" scope="page|request|session|application"/>
    

    其中:

    • id属性用于指定JavaBean对象的引用名称和其存储域属性名。
    • class属性用于指定JavaBean对象的完整类名。
    • scope属性用于指定JavaBean对象的存储域范围,其取值只能是page、request、session和application其中的一个,默认为page。
  • 演示< jsp:useBean>元素的使用

    procuct.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>
    <jsp:useBean id="product" class="com.Demo06.bean.ProductBean" scope="page"></jsp:useBean>
    </body>
    </html>
    

##### 2.2、< jsp:setProperty>元素

  • < jsp:setProperty>元素用于设置JavaBean对象的属性,相当于调用JavaBean对象的setter方法。

  • < jsp:setProperty>元素的语法:

    <jsp:setProperty name="beanInstanceName" property="propertyName" value="propertyValue"/>
    //或
    <jsp:setProperty name="beanInstanceName" property="propertyName" param="parameterName"/>
    //或
    <jsp:setProperty name="beanInstanceName" property="propertyName"/>
    //或
    <jsp:setProperty name="beanInstanceName" property="*"/>
    

    其中:

    • name属性用于指定JavaBean对象的名称,其值应与< jsp:useBean>标签中的id属性相同。
    • property属性用于指定JavaBean对象的属性名
    • value属性用于指定JavaBean对象的某一个属性的值,可以是一个字符串,也可以是一个表达式,它将自动转换为所要设置的JavaBean属性额类型,该属性可选。
    • param属性用于将一个请求参数的值赋给JavaBean对象的某个属性,它可以将请求字符串类型的返回值转换为JavaBean属性所对应的类型,该属性可选。value和param属性不能同时使用。
2.3、< jsp:getProperty>元素
  • < jsp:getProperty>元素用于读取JavaBean对象的属性,等同于调用JavaBean对象的getter方法,然后将读取到的属性值转换成字符串后输出到响应正文中。

  • < jsp:getProperty>元素的语法:

    <jsp:getProperty name="beanInstanceName" property="propertyName"/>
    

    其中:

    • 那么属性用于指定JavaBean对象的名称,其值应与< jsp:useBean>标签的id属性值相同。
    • property属性用于指定JavaBean对象的属性名。
3、JavaBean的应用
  • registerStep1.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>注册第一步</title>
    </head>
    <body>
    <h2 align="center">用户注册第一步</h2>
    <form action="registerStep2.jsp" method="post">
    <table border="1" width="50%" align="center" >
    <tr><td>用户名:</td><td><input type="text" name="username"></td></tr>
    <tr><td>密  码:</td><td><input type="password" name="password"></td></tr>
    <tr><td colspan="2" align="center"><input type="submit" value="下一步"></td><td><input type="text" name="username"></td></tr>
    </table>
    </form>
    </body>
    </html>
    
  • registerStep2.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>注册第二步</title>
    </head>
    <body>
    <%
    	//设置请求编码格式
    	request.setCharacterEncoding("UTF-8");
    %>
    <%--实例化JavaBean,使用请求参数为对象的属性值 --%>
    <jsp:useBean id="user" class="com.Demo06.bean.UserBean" scope="session">
    	<jsp:setProperty property="username" name="user"/>
    	<jsp:setProperty property="password" name="user"/>
    </jsp:useBean>
    
    <h2 align="center">用户注册第二步</h2>
    <form action="registerConfirm.jsp" method="post">
    	<table border="1" width="50%" algin="ceter">
    		<tr>
    			<td>性别:</td>
    			<td>
    				<input type="radio" name="sex" checked="checked" value="男">男
    				<input type="radio" name="sex" value="女">女
    			</td>
    		</tr>
    		<tr>
    			<td>年龄:</td>
    			<td>
    				<input type="text" name="age">
    			</td>
    		</tr>
    		<tr>
    			<td>提示信息:</td>
    			<td>
    				<select name="tooltip">
    					<option value="你妈的名字">你妈的名字</option>
    					<option value="你爸的名字">你爸的名字</option>
    				</select>
    			</td>
    		</tr>
    		<tr>
    			<td>提示答案:</td>
    			<td>
    				<input type="text" name="answer">
    			</td>
    		</tr>
    		<tr>
    			<td>邮箱:</td>
    			<td>
    				<input type="text" name="email">
    			</td>
    		</tr>
    		<tr>
    			<td>愿意接收的信息:</td>
    			<td>
    				<input type="checkbox" name="message" value="新闻">新闻
    				<input type="checkbox" name="message" value="产品广告">产品广告
    				<input type="checkbox" name="message" value="招聘">招聘
    			</td>
    		</tr>
    		<tr>
    			<td colspan="2" align="center"><input type="submit" value="完成"></td>
    		</tr>
    	</table>
    </form>
    </body>
    </html>
    
  • registerConfirm.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>注册第一步</title>
    </head>
    <body>
    <%
    	//设置请求编码方式
    	request.setCharacterEncoding("UTF-8");
    %>
    <%--查找JavaBean对象,使用请求参数为对象赋值 --%>
    <jsp:useBean id="user" class="com.Demo06.bean.UserBean" scope="session">
    	<jsp:setProperty property="*" name="user"/>
    	
    	<h2 align="center">用户注册信息确认</h2>
    	<form action="registerSeccess,jsp" method="post">
    		<table border="1" width="50%" align="center">
    			<tr>
    				<td>用户名:</td>
    				<td><jsp:getProperty property="username" name="user"/></td>
    			</tr>
    			<tr>
    				<td>密码:</td>
    				<td><jsp:getProperty property="password" name="user"/></td>
    			</tr>
    			<tr>
    				<td>性别:</td>
    				<td><jsp:getProperty property="sex" name="user"/></td>
    			</tr>
    			<tr>
    				<td>年龄:</td>
    				<td><jsp:getProperty property="age" name="user"/></td>
    			</tr>
    			<tr>
    				<td>提示信息:</td>
    				<td><jsp:getProperty property="tooltip" name="user"/></td>
    			</tr>
    			<tr>
    				<td>提示答案:</td>
    				<td><jsp:getProperty property="answer" name="user"/></td>
    			</tr>
    			<tr>
    				<td>邮箱:</td>
    				<td><jsp:getProperty property="email" name="user"/></td>
    			</tr>
    			<tr>
    				<td colspan="2" align="center"><input type="submit" value="确认提交"></td>
    			</tr>
    		</table>
    	</form>
    </jsp:useBean>
    </body>
    </html>
    
  • UserBean.jsva

    package com.Demo06.bean;
    
    public class UserBean {
    	private String username;
    	private String password;
    	private char sex;
    	private int age;
    	private String tooltip;
    	private String answer;
    	private String email;
    	private String[] message;
    	public UserBean() {
    		super();
    		// TODO Auto-generated constructor stub
    	}
    	
    	
    	
    	public UserBean(String username, String password, char sex, int age, String tooltip, String answer, String email,
    			String[] message) {
    		super();
    		this.username = username;
    		this.password = password;
    		this.sex = sex;
    		this.age = age;
    		this.tooltip = tooltip;
    		this.answer = answer;
    		this.email = email;
    		this.message = message;
    	}
    
    
    
    	public String getUsername() {
    		return username;
    	}
    
    
    
    	public void setUsername(String username) {
    		this.username = username;
    	}
    
    
    
    	public String getPassword() {
    		return password;
    	}
    
    
    
    	public void setPassword(String password) {
    		this.password = password;
    	}
    
    
    
    	public char getSex() {
    		return sex;
    	}
    
    
    
    	public void setSex(char sex) {
    		this.sex = sex;
    	}
    
    
    
    	public int getAge() {
    		return age;
    	}
    
    
    
    	public void setAge(int age) {
    		this.age = age;
    	}
    
    
    
    	public String getTooltip() {
    		return tooltip;
    	}
    
    
    
    	public void setTooltip(String tooltip) {
    		this.tooltip = tooltip;
    	}
    
    
    
    	public String getAnswer() {
    		return answer;
    	}
    
    
    
    	public void setAnswer(String answer) {
    		this.answer = answer;
    	}
    
    
    
    	public String getEmail() {
    		return email;
    	}
    
    
    
    	public void setEmail(String email) {
    		this.email = email;
    	}
    
    
    
    	public String[] getMessage() {
    		return message;
    	}
    
    
    
    	public void setMessage(String[] message) {
    		this.message = message;
    	}
    
    
    
    	public String getMessageChoose() {
    		String messageChoose = "";
    		if(message != null) {
    			for(int i=0;i<messageChoose.length();i++) {
    				messageChoose += message[i];
    				if(i != message.length-1) {
    					messageChoose +=",";
    				}
    			}
    		}
    		return messageChoose;
    	}
    	
    	
    }
    

八、EL表达式

  • EL(Expression Language, 表达式语言)是一种简单的表达式语言,可以方便的访问和处理程序数据,而无需使用JSP元素(Scriptlet)或JSP表达式。

  • EL在容器默认配置下处于启用状态,每个JSP页面也可以通过page指令的isELIgnored属性单独设置其状态。

  • 语法

    <%@page isELIgnored = "true|false"%>
    

    其中:

    • 如果isELIgnored属性值取true,则EL表达式会被当成字符串直接输出。
    • 默认情况下isELIgnored属性值取值为false,由JSP引擎调用EL引擎来解释执行其中的表达式。
  • EL表达式的特点:

    • 可以访问JSP的内置对象(pageContext、 request、session、application等)。
    • 简化了对JavaBean、集合的访问方式。
    • 可以对数据进行自动类型转换。
    • 可以通过各种运算符进行计算。
    • 可以使用自定义函数实现更加复杂的功能。
1、EL语法
1.1语法
${表达式}

其中表达式可以实常量,可以是变量,表达式中可以使用EL隐含对象、EL运算符和EL函数。

  • 【示例】

    ${"hello"}//输出字符串常量
    ${23.5}//输出浮点型常量
    ${23+5}//输出算术运算结果
    ${23>5}//输出关系运算结果
    ${23||5}//输出逻辑运算结果
    ${23>5?23:5}//输出条件运算结果
    ${empty username}//输出empty运算结果
    ${username}//查找输出变量值
    ${sossionScope.user.sex}//输出隐含对象中的属性值
    ${qst:fun(arg)}//输出自定义函数的返回值
    
1.2、EL中的常量
  • 包括布尔常量、整型常量、浮点数常量、字符串常量和NULL常量。
1.3、EL的变量
  • EL表达式中的变量不同于JSP表达式从当前页面中定义的变量进行查找,而是由EL引擎调用PagaContext.findAttribute(String)方法从JSP的四大作用域范围中查找。

  • 例如:${user},表达式将按照page、request、session、application范围的顺序依次查找名为username的属性;假如中途找到,就直接回传,不再继续找下去;假如全部的范围都没有找到,就回传null。

  • EL变量的命名除了要遵循Java变量的命名范围外,还需要注意不能使用EL中的保留字。

    EL中预留的保留字:

andornotemptydiv
modinstance ofeqneit
gtlegetruefalse
null
1.4、EL中的操作符
  • 对于常见的对象属性、集合数据的访问,EL提供了两种操作符

    • "."操作符:访问对象的某个属性

      • 例如:访问JavaBean对象中的属性:

        ${productBean.category.name}
        

        其中productBean为一个JavaBean对象; category为productBean中的一个属性对象; name为category对象的一个属性。

    • "[]"操作符:也可用于访问对象属性,属性需要使用双引号括起来

      • 例如:

        ${productBean["category"]["name"]}
        
  • "[]"操作符功能:

    • 当属性包含了特殊字符,如:".“或”-“等并非字母或数字的符号,就一定要用”[]"操作符,例如:${header[“user-agent”]}。
    • "[]"操作符可以访问有序集合或数组中的指定索引位置的某个元素,例如:${array[0]}。
    • "[]"操作符可以访问Map对象的key关键字的值,例如:${map[“key”]}。
    • "[]“操作符和”."操作符可以结合使用,例如:${users[0].usernames}。
1.5、EL的错误处理机制
  • EL作为表现层的JSP页面的错误处理,往往对用户会有直观的体现,为此EL提供了比较友好的处理方式:不提供警告,只提供默认值和错误,默认值是空字符串,错误是抛出一个异常。
  • EL对一下几种常见错误的处理方式:
    • 在EL表达式中访问一个不存在的变量,则表达式输出空字符串,而不会抛出NullPointerException
    • 在EL中访问一个不存在的对象属性,则表达式输出空字符串,而不会抛出NullPointerException异常。
    • 在EL表达式中访问一个存在对象的不存在属性,则表达式抛出PropertyNotFoundException异常。
2、EL隐含对象
2.1、与范围有关的隐含对象
  • 在JSP中有四种作用域,EL表达式针对这四种作用域提供了相应的隐含对象用于获取各作用域范围中的属性

    隐含对象说明
    pageScope用于获得页面作用范围中的属性值,相当于pageContext.getAttribute()
    requestScope用于获得请求作用范围中的属性值,相当于request.getAttribute()
    sessionScope用于获得会话作用范围中的属性值,相当于session,getAttribute()
    applicationScope用于获得应用程序作用范围中的属性值,相当于application.getAttribute()
  • 【示例】使用EL访问Session作用域中的表达对象

    ${sessionScope.sex}
    

    【示例】使用脚本代码访问Session作用域中的属性

    <% 
    User user = (User)session.getAttibute("user");
    String sex = user.getSex();
    out.print(sex);
    %>
    

    由上述JSP脚本代码与EL的对比可以看出,EL自动完成了类型转换和数据传输功能,并大大简化了代码量。

  • 【演示】使用隐含对象获取存储在不同范围中JavaBean属性值的用法

    Student.java

    package com.Demo07.bean;
    
    public class Student {
    	private String  name;
    	private int age;
    	public Student() {
    		super();
    		// TODO Auto-generated constructor stub
    	}
    	public Student(String name, int age) {
    		super();
    		this.name = name;
    		this.age = age;
    	}
    	public String getName() {
    		return name;
    	}
    	public void setName(String name) {
    		this.name = name;
    	}
    	public int getAge() {
    		return age;
    	}
    	public void setAge(int age) {
    		this.age = age;
    	}
    	
    	
    }
    
    

    scopeImplicit.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8" import="com.Demo07.bean.Student"%>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
    <%pageContext.setAttribute("studentInPage", new Student("张三", 21)); %>
    <jsp:useBean id="studentInSession" class="com.Demo07.bean.Student" scope="session">
    	<jsp:setProperty name="studentInSession" property="name" value="李四"/>
    	<jsp:setProperty name="studentInSession" property="age" value="22"/>
    </jsp:useBean>
    <p>pageContext对象中获取属性值:${pageScope.studentInPage.name} ${pageScope.studentInPage.age}</p>
    <p>Session对象中获取属性值:${sessionScope.studentInSession.name} ${sessionScope.studentInSession.age} ${sessionScope.sage}</p>
    
    </body>
    </html>
     
    
2.2、与请求参数有关的隐含对象
  • 请求参数也是JSP开发中常见的操作,EL表达式对此也提供了相应的隐含对象:

    隐含对象说明
    param用于获得请求参数的单个值,相当于request.getParameter()
    paramValues用于获得请求参数的一组值,相当于request.getParameterValues()
  • 【演示】获取一个请求地址中的参数值

    paramImplicitObj.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>与请求参数有关的隐含对象</title>
    </head>
    <body>
    <%--http://localhost:8080/Demo07/paramImplicitObj.jsp --%>
    <p>请求参数param1的值:${param.param1 }</p>
    <p>请求参数param2的值:${paramValues.param2[0] }</p>
    
    </body>
    </html>
    
2.3、与其他隐含对象
  • EL表达式语言提供的其他隐含对象

    隐含对象说明
    pageContext相当于JSP页面中的pageContext对象,用于获取ServletContext、request、response、session等其他JSP内置对象
    header用于获得HTTP请求头中的单个值,相当于request.getHeader(String name)
    headerValues用于获得HTTP请求头中的一组值,相当于request.getHeaders(String name)
    cookie用于获得指定的Cookie
    initParam用于获得上下文初始参数,相当于application.getInitParameter(String name)
  • 【演示】各个隐含对象的用法

    web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
      <display-name>Demo07</display-name>
      <context-param>
      	<param-name>website</param-name>
      	<param-value>http://www.baidu.com</param-value>
      </context-param>
      <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>
    </web-app>
    

    otherImplicitObj.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>
    <h3>其他隐含对象的用法</h3>
    <p>获取服务器信息:${pageContext.servletContext.serverInfo}</p>
    <p>获取Servlet注册名:${pageContext.servletConfig.servletName}</p>
    <p>获取请求地址:${pageContext.request.requestURL}</p>
    <p>获取session创建时间:${pageContext.session.creationTime}</p>
    <p>获取响应的文档类型:${pageContext.response.contentType}</p>
    
    <h3>header隐含对象的用法</h3>
    <p>获取请求头Host的值:${header.host }</p>
    <p>获取请求头user-agent的值:${headerValues["user-agetn"][0] }</p>
    
    <h3>cookie隐含对象的用法</h3>
    <p>获取名为JSESSIONID的Cookie对象:${cookie.JSESSIONID }</p>
    <p>获取名为JSESSIONID的Cookie对象的名称和值:${cookie.JSESSIONID.name } ${cookie.JSESSIONID.value }</p>
    
    <h3>initParam隐含对象的用法</h3>
    <p>${initParam.website }</p>
    </body>
    </html>
    
3、EL运算符
  • EL表达式中的算术运算符

    算术运算符说明示例结果
    +${23+5}28
    -${23-5}18
    *${23*5}115
    /或div 23 / 5 或 {23/5}或 23/5{23div5}4.6
    %或mod取余KaTeX parse error: Expected '}', got 'EOF' at end of input: {23%5}或{23mod5}3
    • 需要注意的是,在除法运算中,操作数将被强制转换为Double然后进行相除运算。
  • EL表达式中的关系运算符

    关系运算符说明示例结果
    ==或eq等于 23 = = 5 或 {23==5}或 23==5{23 eq 5}false
    !=或ne不等于 23 ! = 5 或 {23!=5}或 23!=5{23 ne 5}true
    <或lt小于 23 < 5 或 {23<5}或 23<5{23 lt 5}false
    >或gt大于 23 > 5 或 {23>5}或 23>5{23 gt 5}true
    <=或le小于等于 23 < = 5 或 {23<=5}或 23<=5{23 le 5}false
    >=或ge大于等于 23 > = 5 或 {23>=5}或 23>=5{23 ge 5}true
  • EL表达式中的逻辑运算符

    逻辑运算符说明示例结果
    &&或andKaTeX parse error: Expected '}', got '&' at position 7: {true &̲& true}或{true and true}true
    || 或 or t r u e ∥ ∥ f a l s e 或 {true \|\| false}或 truefalse{true or false}true
    ! 或 not ! t r u e 或 {!true}或 !true{not true}false
  • EL表达式中的条件运算符:格式为A?B:C,表示根据表达式A的结果选择B或C,如果A为true,执行B,否则执行C

    • 【示例】

      ${sessionScope.username==null?"游客":sessionScope.username}
      
  • empty运算符是一个前缀操作符,用于检测一个值是否为null或"空",运算符有一个操作数,可以是变量或表达式。

    ${empty sessionScopeusername}
    

    上述示例由=有两层含义:

    • 一是表示session对象中是否存在username属性,等同于

      ${sessionScope.username==null}
      
    • 二是表示session对象中username的值是否为空,等同于

      ${sessionScope.username==""}
      

      九、JSTL

      < c:forEach> 标签
  • 【语法】

    <c:forEach [var="varName"] item="collection" [varStatus="varStatusName"] [begin="begin"] [end="end"] [step="step"]>
    	//标签体内容
    </c:forEach>
    

    其中:

    • var用于指定将当前迭代的元素保存到page域中的属性名称。
    • items指定将当前被迭代的集合对象。
    • varStatus表示当前被迭代到的对象的状态信息,包括四个属性:index(表示当前迭代成员的索引值)、count(表示当前已迭代成员的数量)、first(表示当前迭代到的成员是否为第一个)、last(表示当前迭代到的成员是否为最后一个)。
    • begin表示遍历的起始索引,值为整数。
    • end表示遍历结束的结束索引,值为整数。
    • step表示迭代的步长,值为整数。
  • 【示例】迭代数组对象

    <%
    	String arrays[] = new String[5];
    	arrays[0] = "Hello";
    	arrays[1] = ",";
    	arrays[2] = "everyone";
    	arrays[3] = "!";
    %>
    <c:forEach item="${arrays}" var="item">
    	${item}
    </c:forEach>
    
  • 【示例】迭代集合对象

    <%
    	List<book> list = new ArrayList<book>();
    	list.add(new book("book1"));
    	list.add(new book("book2"));
    	list.add(new book("book3"));
    %>
    <c:forEach item="${sessionScope.bookList}" var="book" varStatus="vst";>
    	<p>
            序号:${vst.index+1}, 书名:${book.bookName}
        </p>
    </c:forEach>
    
  • 【示例】迭代Map对象

    <%
    	Map<String,book> map = new HashMap<String, book>();
    	map.put("book1", new book("book1"));
    	map.put("book2", new book("book2"));
    	map.put("book3", new book("book3"));
    	request.setAttribute
    %>
    <c:forEach items="${requestScope.bookMap}" var="mapitem">
    	<p>
            ${mapitem.key}:${mapitem.value,book.Name}
        </p>
    </c:forEach>
    
  • 【示例】迭代指定次数

    <c:forEach begin="1" end="100" step="1" var="num">
    	<c:set var="sum" value="${sum+num}"></c:set>
    </c:forEach>
    ${sum}
    
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值