一、session是什么?有什么作用?在servlet中怎么管理session?
Http是无状态的协议,客户端只需要简单地向服务器请求,但客户端或者服务器都没有纪录彼此过去的行为,每一次请求之间都是独立的。由此在Java Servlet API中引入Session机制来跟踪客户的状态。Session指的是在一段时间内,单个客户与Web服务器的一连串相关的交互过程。在一个Session中,客户可能会多次请求访问同一个网页,也有可能请求访问各种不同的服务器资源共享源。
例如在电子邮件应用中,从一个客户登录到电子邮件系统开始,经过收信,写信和发信等一系列操作,直至最后退出邮件系统,整个过程为一个Session。
对于Session来说,Session是一个容器,可以存放会话过程中的任何对象。同时,Session是(request对象)产生的,同一个会话中多个request共享了一Session对象,可以直接从请求中获取到Session对象。
Servlet的会话管理机制:
HTTP是一种无状态的协议。它意味着Web应用并不了解有关同一用户以前请求的信息。维持会话状态信息的方法之一是使用Servlet或者JSP容器提供的会话跟踪功能。Servlet API规范定义了一个简单的HttpSession接口,通过它我们可以方便地实现会话跟踪。HttpSession接口提供了存储和返回标准会话属性的方法。标准会话属性如会话标识符、应用数据等,都以“名字-值”对的形式保存。简而言之,HttpSession接口提供了一种把对象保存到内存、在同一用户的后继请求中提取这些对象的标准办法。在会话中保存数据的方法是setAttribute(String s, Object o),从会话提取原来所保存对象的方法是getAttribute(String s)。每当新用户请求一个使用了HttpSession对象的JSP页面,JSP容器除了发回应答页面之外,它还要向浏览器发送一个特殊的数字。这个特殊的数字称为“会话标识符”,它是一个唯一的用户标识符。此后,HttpSession对象就驻留在内存之中,等待同一用户返回时再次调用它的方法。在客户端,浏览器保存会话标识符,并在每一个后继请求中把这个会话标识符发送给服务器。会话标识符告诉JSP容器当前请求不是用户发出的第一个请求,服务器以前已经为该用户创建了HttpSession对象。此时,JSP容器不再为用户创建新的HttpSession对象,而是寻找具有相同会话标识符的HttpSession对象,然后建立该HttpSession对象和当前请求的关联。会话标识符以Cookie的形式在服务器和浏览器之间传送。如果客户端不支持cookie,运用url改写机制来保证会话标识符传回服务器。
二、分析书上P132的程序清单
1、long before = System.currentTimeMillis(); .......... long after = System.currentTimeMillis(); 这两个语句的作用?
此语句的作用是规定了Filter负责拦截所有的用户请求的过滤范围。
2. HttpServletRequest hrequest = (HttpServletRequest) request ; 这个语句的含义?
将请求强制转换为HttpServletRequest型再赋给HttpServletRequest 请求对象hrequest
3. System.out.println("Filter 已经拦截到用户的请求的地址: " + hrequest.getServletPath()); 这句话的含义?
通过getServletPath()函数打印Filter 已经拦截到用户的请求的地址
三、写一个用Filter进行用户授权的例子即过滤request?
LoginFilter.java
private String permitUrls[] = null;
private String gotoUrl = null;
public void destroy() {
// TODO Auto-generated method stub
permitUrls = null;
gotoUrl = null;
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// TODO Auto-generated method stub
HttpServletRequest res=(HttpServletRequest) request;
HttpServletResponse resp=(HttpServletResponse)response;
if(!isPermitUrl(request)){
if(filterCurrUrl(request)){
System.out.println("--->请登录");
resp.sendRedirect(res.getContextPath()+gotoUrl);
return;
}
}
System.out.println("--->允许访问");
chain.doFilter(request, response);
}
public boolean filterCurrUrl(ServletRequest request){
boolean filter=false;
HttpServletRequest res=(HttpServletRequest) request;
User user =(User) res.getSession().getAttribute("user");
if(null==user)
filter=true;
return filter;
}
public boolean isPermitUrl(ServletRequest request) {
boolean isPermit = false;
String currentUrl = currentUrl(request);
if (permitUrls != null && permitUrls.length > 0) {
for (int i = 0; i < permitUrls.length; i++) {
if (permitUrls[i].equals(currentUrl)) {
isPermit = true;
break;
}
}
}
return isPermit;
}
//请求地址
public String currentUrl(ServletRequest request) {
HttpServletRequest res = (HttpServletRequest) request;
String task = request.getParameter("task");
String path = res.getContextPath();
String uri = res.getRequestURI();
if (task != null) {// uri格式 xx/ser
uri = uri.substring(path.length(), uri.length()) + "?" + "task="
+ task;
} else {
uri = uri.substring(path.length(), uri.length());
}
System.out.println("当前请求地址:" + uri);
return uri;
}
public void init(FilterConfig filterConfig) throws ServletException {
// TODO Auto-generated method stub
String permitUrls = filterConfig.getInitParameter("permitUrls");
String gotoUrl = filterConfig.getInitParameter("gotoUrl");
this.gotoUrl = gotoUrl;
if (permitUrls != null && permitUrls.length() > 0) {
this.permitUrls = permitUrls.split(",");
}
}
}
Web.xml
<filter-name>loginFilter</filter-name>
<filter-class>filter.LoginFilter</filter-class>
<init-param>
<param-name>ignore</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>permitUrls</param-name>
<param-value>/,/servlet/Loginservlet?task=login,/public.jsp,/login.jsp</param-value>
</init-param>
<init-param>
<param-name>gotoUrl</param-name>
<param-value>/login.jsp</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>loginFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
四、总结JEETT文档中两段代码的差别,并分析启动代码后的效果有啥不同?
1.首先介绍一下什么是异步处理、异步任务
异步处理:异步的概念和同步相对。当一个异步过程调用发出后,调用者不能立刻得到结果。实际处理这个调用的部件在完成后,通过状态、通知和回调来通知调用者。以CAsycSocket类为例(注意,CSocket从CAsyncSocket派生,但是其功能已经由异步转化为同步),当一个客户端通过调用 Connect函数发出一个连接请求后,调用者线程立刻可以朝下运行。当连接真正建立起来以后,socket底层会发送一个消息通知该对象。这里提到执行部件和调用者通过三种途径返回结果:状态、通知和回调。可以使用哪一种依赖于执行部件的实现,除非执行部件提供多种选择,否则不受调用者控制。如果执行部件用状态来通知,那么调用者就需要每隔一定时间检查一次,效率就很低(有些初学多线程编程的人,总喜欢用一个循环去检查某个变量的值,这其实是一种很严重的错误)。如果是使用通知的方式,效率则很高,因为执行部件几乎不需要做额外的操作。
AsyncTask: 即asynchronous task,异步任务。AsyncTask实际上是围绕Thread和Handler设计的一个辅助类,在内部是对Thread和Handler的一种封装。AsyncTask的异步体现在由后台线程进行运算(访问网络等比较耗时的操作),然后将结果发布到用户界面上来更新UI,使用AsyncTask使得我不用操作Thread和Handler。
2.异步与同步的区别是什么?
同步与异步的区别:在于请求的内容是不是立刻返回,同步请求需要等待结果返回后才能继续执行。单线程的执行的时候,需要顺序执行,如果碰到一个计算量很大,很耗时的函数需要执行,该线程就必须在这里等待结果计算出来以后,才能继续执行。
异步请求理论上不需要等待请求的结果,将耗时的计算交给另外一个线程,在结果计算完成后会通知主线程。实际上,异步请求会立刻得到一个临时结果,然后异步请求就可以继续执行了,当异步线程返回真正结果后再通知主线程,然后主线程在做出动作。
3.根据上面的基础知识,可大致得出文档中代码的区别为:
(1)request.startAsync()
导致请求被异步处理; 在服务方法结束时,响应不会发送到客户端。
(2)acontext.start(new Runnable() {…?})
从容器中获取新线程。
(3)run()
内部类的方法的代码在新线程中执行。内部类可以访问异步上下文以从请求读取参数并写入响应。调用complete()
异步上下文的 方法将提交响应并将其发送给客户端。
运行效果不同之处:
使用异步处理后的例子在大负载的情况下响应速度变快,服务器吞吐量变大