Using Session in Servlet/JSP

Categories: Java; Tagged with: ; @ July 3rd, 2012 0:03

Using session in Servlet:

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.getWriter().write("Servlet HelloWorld!");
		
		HttpSession session = request.getSession(false);
		if(session == null) {
			response.sendRedirect("ServletLogin");
			return;
		}else {
			System.out.println(session.getId());
			Integer totalAccess = (Integer) session.getAttribute("totalAccess"); // Get session attribute;
			if(totalAccess == null) {
				totalAccess = 0;
			}
			
			totalAccess += 1;
			session.setAttribute("totalAccess", totalAccess); // set attribute
			
			response.getWriter().write("TotalAccess: " + session.getAttribute("totalAccess"));
		}

 

Using session in JSP:

Jsp page directive:

<%@ page
          [ language=”java” ]
          [ extends=”package.class” ]
          [ import=”{package.class | package.*}, …” ]
          [ session=”true | false” ]
          [ buffer=”none | 8kb | sizekb” ]
          [ autoFlush=”true | false” ]
          [ isThreadSafe=”true | false” ]
          [ info=”text” ]
          [ errorPage=”relativeURL” ]
          [ contentType=”mimeType [ ;charset=characterSet ]”   |   “text/html ; charset=ISO-8859-1” ]
          [ isErrorPage=”true | false” ]
%>

“session = true” by default.  when access “session”, if session is not existing, will create one by default.
we can set:

<%-- Prevent the creation of a session –%>
<%@ page session="false">

to prevent the Creation of a Session in a JSP Page.

 

We didn’t mention about the thread safe of session, here is a post from IBM DW:
http://www.ibm.com/developerworks/library/j-jtp09238/index.html

The difference between Forward and Redirect in Servlet

Categories: Java; Tagged with: ; @ July 1st, 2012 15:16

Redirect:

response.sendRedirect(“ServletLogin”); // User not login, redirect to the login page.

“redirect sets the response status to 302, and the new url in a Location header, and sends the response to the browser. Then the browser, according to the http specification, makes another request to the new url”

And you can forward to any URL.

image

Forward:

request.getServletContext().getRequestDispatcher(“/s/HelloWorld”).forward(request, response);

forward happens entirely on the server. The servlet container just forwards the same request to the target url, without the browser knowing about that. Hence you can use the same request attributes and the same request parameters when handling the new url. And the browser won’t know the url has changed (because it has happened entirely on the server)

So we can get the parameters in the target method:

request.getParameter(“userName”) // HelloWorld…doPost()..

Ref: http://stackoverflow.com/questions/6068891/difference-between-jsp-forward-and-redirect


this picture is from: http://lukejin.iteye.com/blog/586091

Servlet实践 2-1

Categories: Java; Tagged with: ; @ February 13th, 2009 20:21

实践

2.1 需求及用例

创建一个简单的计算器, 当用户输入整数时, 输出其平方值. 但用户需要登录才能进行操作, 用户的登录信息放在web.xml中, 每次登录用户可以使用该计算器三次, 三次使用结束后, 提示用户推出后重新登录继续使用.

User Case 用例

登录系统

Brief description

登录系统

Scope/Level

AthenaES/User goal

Primary actor/role

Root

Minimal & Success Guarantees 保证

Minimal: The system logs how far it may get
Success:登录成功

Preconditions 前提

Triggers 引发条件

用户打开登录界面

Main Success Scenario 成功场景

1. 系统提示用户输入用户名及密码
2. 用户输入用户名及密码
3. 系统核对用户名及密码
4. 系统提示用户登录成功

Extension 扩展 #1

3a: 系统无法核实用户身份, 提示其用户名或密码错误, 并提示用户重新输入

Notes and Issues

User Case 用例

计算平方

Brief description

计算平方

Scope/Level

AthenaES/User goal

Primary actor/role

Root

Minimal & Success Guarantees 保证

Minimal: The system logs how far it may get
Success: 成功显示结果

Preconditions 前提

Actor is logged in

Triggers 引发条件

用户点击”计算”

Main Success Scenario 成功场景

1. 确认用户使用次数未达到上限
2. 用户输入整数
3. 用户点击”计算”
4. 系统确认输入合法
5. 系统计算平方值, 系统将用户使用次数加一, 系统显示结果, 提示用户使用次数.
用户重复步骤1~5 , 直到用户关闭程序或使用次数达到上限

Extension 扩展 #1

1a: 用户使用次数达到上限, 系统提示用户重新登陆后继续使用

Extension 扩展 #2

4a: 系统检测到用户输入不合法, 系统提示用户重新输入 用户重新进行2~4

Notes and Issues

2. 2 数据分析:


1. ServltContext
层次的数据: 由于用户名及最大限制次数等信息在整个Servlet进程中都会被使用, 因此使用Context的Listener来实现.

2. Session层次的数据: 用户本次登录已使用次数应记录在Seesion中, 在当前Session中使用

3. Request层次的数据: 用户输入的数值尽在当前Request中使用

2. 3 具体实现

</>

Calc主页面实现:

首先检查Session是否存在, 不存在则跳转到登录界面.
Session存在, 则通过session.getAttribute()获得该用户在当前Session中的使用次数, 如果为Null, 则设置为零, setAttribute.
如果不为Null, 则判断是否小于MAX_CALCULATION_TIMES_PER_SESSION, 如果大于三次则提示其退出登录重新登录继续使用.
小于MAX_CALCULATION_TIMES_PER_SESSION则呼叫proccessRequet()方法输出计算器. 该方法将会调用calculator()方法, 该方法将返回输入值的平方,同时将Session中的使用次数加一.
重要方法:
request.getSession(false);//获得Session, 如果不存在, 则返回null
session.getAttribute(ACCESS_COUNT);
session.setAttribute(ACCESS_COUNT, accessCount);
request.getSession().invalidate(); //
清空session

package com.insprise.servletStu;
//省略import
public class Calc extends HttpServlet {
	public static final String MAX_CALCULATIONAS_PER_SESSION = “maxNumber”; // 最大使用次数的Key
	public static int MAX_CALCULATION_TIMES_PER_SESSION; // 最大使用次数
	public static final String CURRENT_USER = “currentUser”; // 当前用户
	public static final String URL_MAIN = “./Calc”; // 主页面
	public static final String URL_LOGIN = “./Login”; // 登录页面
	public static final String URL_LOGOUT = “./Logout”; // 注销页面
	private static final String ACCESS_COUNT = “accessCount”; // 使用次数
	private static final String INPUT_INT = “inputInt”;
	private static Logger log = Logger.getLogger(Calc.class);
	private static final int MAX_INT = 46340; // Math.sqrt(Integer.MAX_VALUE)

	private HttpSession session;
	private Integer accessCount; // 使用次数

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
		session = request.getSession(false);
		if (validatUser(session)) { // 已登录
			accessCount = (Integer) session.getAttribute(ACCESS_COUNT);
			if (accessCount == null) { // 如果Session中不存在accessCount, 则表明其为新登录用户,
				// 赋值为0;
				accessCount = 0;
				session.setAttribute(ACCESS_COUNT, accessCount);
			}
			if (checkUseTimes(accessCount)) { // 已登录, 且使用次数在限制之内, 进行操作.
				proccessRequet(request, response);

			} else { // 已登录, 但使用次数操过限制,提示用户重新登陆.
				accessOverTime(request, response);
			}
		} else { // 未登录
			response.sendRedirect(URL_LOGIN);
		}
	}

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

	// 检查用户是否已登录
	private boolean validatUser(HttpSession s) {
		if (session != null) {
			return true;
		}
		return false;
	}

	// 检查用户使用次数是否超过限制
	private boolean checkUseTimes(Integer number) {
		//省略
	}

	// 使用次数超过限制之后 提示其登录;
	private void accessOverTime(HttpServletRequest request, HttpServletResponse response) throws IOException {
		request.getSession().invalidate();
		response.getWriter().println("本次登录已使用完毕, 请重新登录");
		return;
	}

	// 获得输入数值, 计算结果, 返回信息
	private void proccessRequet(HttpServletRequest request, HttpServletResponse response) throws IOException {
		Integer i;
		String title = "求整数平方";

		response.setContentType("text/html");
		response.setCharacterEncoding("utf-8");
		// 不使用缓存 在点击推出后 按后退按钮时 不会出现缓存中的内容.
		response.setHeader("Cache-Control", "no-store");
		response.setDateHeader("Expires", 0);
		response.setHeader("Pragma", "no-cache");

		PrintWriter out = response.getWriter();
		out.println(ServletUtilities.headwithTitle(title));
		out.println("

" + title + "


"); out.println("

当前用户: " + session.getAttribute(CURRENT_USER) + " [退出]

"); String numberString = request.getParameter(INPUT_INT); if (numberString != null) { try { out.println("

" + i + " 的平方是: " + calculator(i) + "

"); log.info("累计第[" + accessCount + "]次使用, 本次计算的参数为: " + i); } catch (Exception e) { out.println("您可能输入的不是整数 或您输入的整数绝对值过大

请输入: 一个绝对值小于" + MAX_INT + " 的整数

"); } } out.println("

您总共可以使用 " + MAX_CALCULATION_TIMES_PER_SESSION + "次, 您已累计使用:" + accessCount + "次
"); // 最后一次运行时, 停止输出Form; if (accessCount.equals(MAX_CALCULATION_TIMES_PER_SESSION)) { out.println("已达到最大使用次数限制, 请退出后重新登陆"); return; } printForm(out); out.println(""); } // 计算 private int calculator(int i) { accessCount = new Integer(accessCount.intValue() + 1); // 使用次数增加一次 session.setAttribute("accessCount", accessCount); return i * i; } // 打印一个Form private void printForm(PrintWriter out) { out.print("


"); out.println("请输入一个整数: "); out.println("
"); out.println(" "); } }

Servlet学习总结 – Servlet Reference

Categories: Java; Tagged with: ; @ February 13th, 2009 20:12

2009-2-13 14-56-18

很简单的几个概念, 其他还是OO.

A: Request常用方法

request中获取参数

方法

说明

getParameter(String name);

获得request中参数名name对应的值, 如果不存在该参数, 则返回Null – 注意: 名称大小写敏感

GetParameterNames

返回一个枚举对象, 包含了所在request中的所有参数名, 如果request没有参数, 该方法返回一个空的枚举

GetParameterValues(String name)

返回一个Sting[], 包含参数所对应的所有的值, 如果参数不存在,则返回Null.

getParameterMap

返回一个Map对象, 以参数名称为Key(String), 参数对应值为Value(类型String[])

getSession()

获得当前Session

Response中输出信息

方法

说明

setContentType(String type)

声明返回数据的MIME类型

setCharacterEncoding(String charset)

声明Response的编码

getWriter();

返回一个PrintWriter, 可通过该对象的print 或printlin方法向客户端发送字符串数据流

sendRedirect(String location)

设置转向 – 转到某地址

B: Session常用方法:

方法

说明

getServletContext()

获得Session所在的ServletContext对象

getAttribute(String name)

返回该Session中name对应的Attribute对象, 如果没有则返回null

getAttributeNames()

返回一个枚举, 包括Seesion中所有的Attribut 对应的name,

setAttribute(String name, Object value)

在Session中加入Attribute

invalidate()

销毁Session

C: ServeletContext常用方法

方法

说明

getInitParameter(String name)

返回一个String, 包含对应的初始化参数, 如果不存在则返回null, init参数可在web.xml中使用<context-param>设定

getInitParameterNames()

返回由所有的init参数名称组成的枚举, 如果不存在任何init参数, 则返回空的枚举

getAttribute(String name)

返回运行时设定相应的Attribute 对象, 如不存在则返回null

getAttributeNames()

返回一个枚举, 包含所有Attribute的name, 如果不存在任何Attribue, 则返回一个空的枚举

setAttribute(String name, Object object)

在运行时增加Attribute

removeAttribute(String name)

删除对应name的Attribute

D: Servlet框架理解

Servlet通过IoC(Inversion of Control意为控制反转)将代码交给框架来执行. 因此只需要在Servlet类中扩展HttpServlet, 覆盖doGet, doPost等方法, 就可成功创建并执行一个Servlet. 在有客户Request时, 将由Service方法分析Request, 并交由对应方法处理, 如Get交由doGet方法处理.

Listener: Servlet中的listener类似于AS中的Event kind, 在Listener支持的事件 – 如Servlet初始化完毕, Session初始化, Request Destory,等, 在这些事件发生后, 将自动运行相应的方法(IoC)

如果需要Listener或Filter, 则在编写好相应的类之后, 加入到web.xml描述文件中.

Servlet 的数据层次:
1. ServletContext: Application初始化时会呼叫Listener contextInitialized(), 可以在该方法中获得或设定ServletContext生命周期内的数据. 如可以通过getInitParameter来获取web.xml中定义好的初始化参数, 也可以通过setAttribute方法设定Attribute, 这些Attribute将在整个Servlet生命周期内有效.

2. HttpSession: 当获得Session之后, 可以进行setAttribute等方法设定Session’的Attribute – 在该Session中有效

3. HttpRequest: 在doGet, doPost等方法中, 可以通过request. get Parameter(String name)等方法来获得request中的数据, 这些数据仅对当前的这个Request有效

web.xml中<context-param>与<init-param>的差别及各自的读取方式

Categories: Java; Tagged with: ; @ February 13th, 2009 19:40

事由: 最近几天看了点Servlet, 打算写一个小程序, 需要在application启动时从web.xml中加载一个参数, 由于仅在Login这个Servlet中使用, 于是我是这样实现的:

  
    
    Login
    Login
    com.insprise.servletstu.Login
    
      maxNumber
      maxNumber
      3
    
  
  
    Login
    /Login
  
  

然后在Login中重写init()方法, 如下:

Calc.MAX_CALCULATION_TIMES_PER_SESSION = Integer.parseInt(this.getInitParameter(Calc.MAX_CALCULATIONAS_PER_SESSION));

功能以实现, 将最大值从web.xml中读取出来, 赋值给一个Global的变量.

===============================承上启下的分割线==============================================

但随着学习的深入, 发现容器并不一定会保持Servlet一直存活, 也许会在Request介绍后Destory掉Login Servlet, 然后如果再次Request Login, 则会重新init(), 于是重新读取web.xml, 重新赋值–明显第一次有效的, 后面的都是无用功.

从逻辑上分析, 该最大值应属于ServletContext级别的数据, 于是应使用Listener, 监听Application初始化, 在Application初始化时读取.

于是我没有改动web.xml, 设置了监听函数:

    public void contextInitialized(ServletContextEvent sce) {
        log.info("Context Started!" + sce.getServletContext());
        ServletContext context = sce.getServletContext();
        Calc.MAX_CALCULATION_TIMES_PER_SESSION = Integer.parseInt(context.getInitParameter(Calc.MAX_CALCULATIONAS_PER_SESSION));
    }

但不论如何都会有NullPoint的错误. 于是意识到该应在web.xml使用<context-param>设定参数, 而非某个<Servlet>下的<init-param>标签. 修改后的web.xml:

 
           maxNumber
           3

=====================================总结性的分割线============================================

总而言之:

使用ServletContext.getInitParameter()方法 可以获得web.xml中的<context-param>参数 – 使用范围很广, 能getServletContext就可以使用.

在Servlet的init()函数中使用this.getInitParameter()获得web.xml的<init-param>参数 – 较为局限的参数. 注意逻辑上的层次划分



// Proudly powered by Apache, PHP, MySQL, WordPress, Bootstrap, etc,.