〇、HttpSession原理详解
HttpSession借助Cookie技术的。
HttpSession getSession():服务器会根据用户带来的JSESSIONIDcookie的值,先查找。找到继续为你服务,没有找到,创建新的HttpSession对象。
HttpSession getSession(boolean b):
b为true:效果同getSession()
b为false:只是查询。

一、HttpSession的案例:
1、简单的不能再简单的购物车(先建立JavaBean,然后JavaBeanDB)
浏览器关闭了,会话结束了。但是服务器端原来为您服务的HttpSession对象并没有消失(等待超时,默认30分钟)
//显示所有的产品。提供购买和显示已买产品的链接
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType( "text/html;charset=UTF-8" );
PrintWriter out = response.getWriter();
request.getSession();
out.write( "本站有以下好书:<br/>" );
Map<String, Book> books= BookDB. findAllBooks ();
for (Map.Entry<String, Book> me:books.entrySet()){
String url = request.getContextPath()+"/servlet/BuyServlet?id="+me.getKey();
url = response.encodeURL(url);
out.write(me.getValue().getName()+ " <a href='" +url+"'>购买</a><br/>" );
}
String url = request.getContextPath()+"/servlet/ShowCartServlet" ;
url = response.encodeURL(url);
out.write( "<hr/><a href='" +url+ "'>显示已购买商品</a>" ); }
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType( "text/html;charset=UTF-8" );
PrintWriter out = response.getWriter();
request.getSession();
out.write( "本站有以下好书:<br/>" );
Map<String, Book> books= BookDB. findAllBooks ();
for (Map.Entry<String, Book> me:books.entrySet()){
String url = request.getContextPath()+"/servlet/BuyServlet?id="+me.getKey();
url = response.encodeURL(url);
out.write(me.getValue().getName()+ " <a href='" +url+"'>购买</a><br/>" );
}
String url = request.getContextPath()+"/servlet/ShowCartServlet" ;
url = response.encodeURL(url);
out.write( "<hr/><a href='" +url+ "'>显示已购买商品</a>" ); }
//购买 Servlet :把购买的书籍放入购物车(容器)。提供继续购物的链接
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType( "text/html;charset=UTF-8" );
PrintWriter out = response.getWriter();
String id = request.getParameter( "id" );
Book book = BookDB. findBookById (id);
//放入购物车:一个客户端只有一个购物车,且不能被替换
HttpSession session = request.getSession();
List<Book> cart= (List<Book>) session.getAttribute("cart" ) ;
if (cart== null ){
cart = new ArrayList<Book>();
session.setAttribute( "cart" , cart);
}
cart.add(book);
String url = request.getContextPath()+"/servlet/ShowProductServlet" ;
url = response.encodeURL(url);
out.write(book.getName()+ "已放入您的购物车!<a href='" +url+"'>继续购物</a>" ); }
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType( "text/html;charset=UTF-8" );
PrintWriter out = response.getWriter();
String id = request.getParameter( "id" );
Book book = BookDB. findBookById (id);
//放入购物车:一个客户端只有一个购物车,且不能被替换
HttpSession session = request.getSession();
List<Book> cart= (List<Book>) session.getAttribute("cart" ) ;
if (cart== null ){
cart = new ArrayList<Book>();
session.setAttribute( "cart" , cart);
}
cart.add(book);
String url = request.getContextPath()+"/servlet/ShowProductServlet" ;
url = response.encodeURL(url);
out.write(book.getName()+ "已放入您的购物车!<a href='" +url+"'>继续购物</a>" ); }
//显示购物车中的内容
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType( "text/html;charset=UTF-8" );
PrintWriter out = response.getWriter();
//getSession()等于getSession(true),如果有Session,则返回,如果没有则创建.
//getSession(false),如果有Session,则返回,如果没有Session,则返回null
HttpSession session = request.getSession( false );
if (session== null ){
out.write( "哥们,你TMD真有才,什么都木有买就看看,SB" );
return ;
}
//session肯定创建过了:需要进一步显示
out.write( "您购买的商品如下:<br/>" );
List<Book> cart= (List<Book>) session.getAttribute("cart" ) ;
if (cart== null ){
out.write( "您还没有购买任何商品" );
} else
for (Book b:cart){
out.write(b.getName()+ "<br/>" );
}
String url = request.getContextPath()+"/servlet/ShowProductServlet" ;
url = response.encodeURL(url);
out.write( "<a href='" +url+ "' target='_blank'>继续购物</a>" ); }
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType( "text/html;charset=UTF-8" );
PrintWriter out = response.getWriter();
//getSession()等于getSession(true),如果有Session,则返回,如果没有则创建.
//getSession(false),如果有Session,则返回,如果没有Session,则返回null
HttpSession session = request.getSession( false );
if (session== null ){
out.write( "哥们,你TMD真有才,什么都木有买就看看,SB" );
return ;
}
//session肯定创建过了:需要进一步显示
out.write( "您购买的商品如下:<br/>" );
List<Book> cart= (List<Book>) session.getAttribute("cart" ) ;
if (cart== null ){
out.write( "您还没有购买任何商品" );
} else
for (Book b:cart){
out.write(b.getName()+ "<br/>" );
}
String url = request.getContextPath()+"/servlet/ShowProductServlet" ;
url = response.encodeURL(url);
out.write( "<a href='" +url+ "' target='_blank'>继续购物</a>" ); }
2、完成用户登陆和一次性的验证码验证
建立一个JavaBean,存用户信息
建立一个ImageServlet,验证图片
建立登录HTML页面
< form action ="/day06_00_session/servlet/LoginServlet" method
="post" >
用户名: < input type ="text" name ="username" />< br />
密码: < input type ="password" name ="password" />< br />
验证码: < input type ="text" name ="code" size ="4" />< img id ="code" src ="/day06_00_session/servlet/ImageServlet" />
< a href ="javascript:changeNum()" > 看不清 </a >
< br />
< input type ="submit" value ="登陆" />
</ form >
< script type ="text/javascript" >
function changeNum(){
//alert("haha");
//地址如果相同,浏览器不会发出请求
document.getElementById("code" ).src="/day06_00_session/servlet/ImageServlet?" + new Date().getTime();
} </ script >
用户名: < input type ="text" name ="username" />< br />
密码: < input type ="password" name ="password" />< br />
验证码: < input type ="text" name ="code" size ="4" />< img id ="code" src ="/day06_00_session/servlet/ImageServlet" />
< a href ="javascript:changeNum()" > 看不清 </a >
< br />
< input type ="submit" value ="登陆" />
</ form >
< script type ="text/javascript" >
function changeNum(){
//alert("haha");
//地址如果相同,浏览器不会发出请求
document.getElementById("code" ).src="/day06_00_session/servlet/ImageServlet?" + new Date().getTime();
} </ script >
//用户登陆
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding( "UTF-8" );
response. setContentType ( "text/html;charset=UTF-8" );
PrintWriter out = response.getWriter();
//验证“验证码”是否正确:从session中取出,与用户提交过来的参数进行对比
HttpSession session = request.getSession();
String sCode = (String) session.getAttribute("code" );
String pCode = request.getParameter( "code" );
if (!pCode.equalsIgnoreCase(sCode)){
response.setHeader( "Refresh" , "2;URL="+request.getContextPath()+"/login.html" );
out.write( "验证码有误!2秒后自动转向登陆页面" );
return ;
}
//验证用户名和密码
User user = new User();
user.setUsername(request.getParameter( "username" ));
session.setAttribute( "user" , user);
response.setHeader( "Refresh" , "2;URL="+request.getContextPath()+"/servlet/IndexServlet" );
out.write( "登陆成功!2秒后转向主页" ); }
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding( "UTF-8" );
response. setContentType ( "text/html;charset=UTF-8" );
PrintWriter out = response.getWriter();
//验证“验证码”是否正确:从session中取出,与用户提交过来的参数进行对比
HttpSession session = request.getSession();
String sCode = (String) session.getAttribute("code" );
String pCode = request.getParameter( "code" );
if (!pCode.equalsIgnoreCase(sCode)){
response.setHeader( "Refresh" , "2;URL="+request.getContextPath()+"/login.html" );
out.write( "验证码有误!2秒后自动转向登陆页面" );
return ;
}
//验证用户名和密码
User user = new User();
user.setUsername(request.getParameter( "username" ));
session.setAttribute( "user" , user);
response.setHeader( "Refresh" , "2;URL="+request.getContextPath()+"/servlet/IndexServlet" );
out.write( "登陆成功!2秒后转向主页" ); }
//模拟默认主页
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType( "text/html;charset=UTF-8" );
PrintWriter out = response.getWriter();
HttpSession session = request.getSession();
User user = (User)session.getAttribute( "user" );
if ( user == null ){
out.write( "<a href='" +request.getContextPath()+ "/login.html'>登陆</a>" );
} else {
out.write( "欢迎您:" +user.getUsername()+ " <a href='" +request.getContextPath()+"/servlet/LogoutServlet'>注销</a>" );
}
out.write( "<hr/>这是主页内容" ); }
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType( "text/html;charset=UTF-8" );
PrintWriter out = response.getWriter();
HttpSession session = request.getSession();
User user = (User)session.getAttribute( "user" );
if ( user == null ){
out.write( "<a href='" +request.getContextPath()+ "/login.html'>登陆</a>" );
} else {
out.write( "欢迎您:" +user.getUsername()+ " <a href='" +request.getContextPath()+"/servlet/LogoutServlet'>注销</a>" );
}
out.write( "<hr/>这是主页内容" ); }
//注销
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpSession session = request.getSession();
session.invalidate(); //立即失效 }
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpSession session = request.getSession();
session.invalidate(); //立即失效 }
3、防止表单重复提交
原理图:

MD5加密
public static String md5Encode(String str){
try {
//返回实现指定摘要算法的 MessageDigest 对象
MessageDigest md = MessageDigest. getInstance ("md5" );
//进行MD5编码
byte b[] = md.digest(str.getBytes()); //得到加密后的字节码
//把b字节码转换成字符串
BASE64Encoder base64 = new BASE64Encoder();
return base64.encode(b);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
} }
try {
//返回实现指定摘要算法的 MessageDigest 对象
MessageDigest md = MessageDigest. getInstance ("md5" );
//进行MD5编码
byte b[] = md.digest(str.getBytes()); //得到加密后的字节码
//把b字节码转换成字符串
BASE64Encoder base64 = new BASE64Encoder();
return base64.encode(b);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
} }
Base64编码:(3字节--->4字节)
1001 1000 0101 1111 1010 1001
0010 0110 0000 0101 0011 1110

编码之后,每个字节表示的范围:0000 0000~0011 1111 共64个数
每个数都有与之对应的字符,Base64其实是一个码表。
任何的字节序列都可以转换为字符串,所以可以用Base64把中文编码后存放到cookie的value中去
SESSIONID如何弄一个出来,且唯一
return new BigInteger(165, new Random()).toString(36).toUpperCase();
二、客户端禁用Cookie后的会话数据保存:URL重写
解决办法:
1、主页提示:为了更好的浏览本网站,请不要禁用您的cookie
2、URL重写:很麻烦。必须对网站的所有地址都重写。
重写后有以下效果:
http://localhost:8080/day06_00_session/servlet/ShowCartServlet
http://localhost:8080/day06_00_session/servlet/ShowCartServlet;JSESSIONID=sessionId
用户禁用后,可以用一下方法重写地址。
String response.encodeURL(String url); 自动判断用户有无禁用cookie,禁用了,重写。没有禁用,就不重写了。
三、HttpSession对象的状态转换(要实现Serializable接口,以序列化.?)
关闭session的两种方式:
1,在web.XML中进行一下配置,更改session保持时间,到时间就会被干掉。
<session-config>
<session-timeout>1</session-timeout><!-- 1分钟,默认30分钟 -->
</session-config>
2,session.invalidate();语句

四、IE浏览器何时才会开启一次新的会话
1、IE8+:开启一个新的浏览器进程,都是一次会话。
2、开启选项卡或者在新窗口中打开新页面都是同一此会话。
3、开启新会话:“文件”-->"新建会话"
五、JSP语法
学好JSP的关键:时刻想着JSP对应的Servlet是什么?
JSP模版元素:JSP中的那些HTML。(做页面前先搞它)
JSP脚本表达式:(实际开发中是不用的)
作用:输出值到页面上。
语法:<%=表达式%> == java:out.print(now);
JSP脚本片断:(实际开发中是不用的)
作用:在JSP中写Java语句逻辑
语法:<%java代码语句;%>
JSP引擎在翻译JSP页面中,会将JSP脚本片断中的Java代码将被原封不动地放到Servlet的_jspService方法中。
JSP声明:(少用)
语法:<%! java语句;%>
作用:定义成员属性、方法,静态代码块。
Jsp声明中的java代码被翻译到_jspService方法的外面。
可用于定义JSP页面转换成的Servlet程序的静态代码块、成员变量和方法 。
JSP隐式对象的作用范围仅限于Servlet的_jspService方法,所以在JSP声明中不能使用这些隐式对象。
JSP注释 :
语法:<%--这是注释--%> 服务器根本不把他们翻译到java代码中
六、JSP指令
作用:不是给JSP用的,写在JSP中的。给JSP引擎(服务器)用的
语法:<%@ 指令名称 属性1="值1" 。。。%>
举例:<%@ page contentType="text/html;charset=gb2312"%>
有3个:
page:
属性:
language:指示JSP中使用脚本语言。默认是java,目前只支持java。
extends:指示JSP生成的那个Servlet的爸爸是谁。不要修改。
*import:JSP中java脚本用到的类导入。java代码中的import一样的。
import="java.io.*,java.util.Date"
*session:默认值是true。指示是否创建HttpSession对象。
*buffer:指示JSP中的输出流的缓存大小。默认8Kb。
*isThreadSafe:指示JSP对应的Servlet是否是线程安全的。false才继承SingleThreadModel接口(过时了)
*errorPage:当JSP出现异常时,转向的页面
以下配置是全局错误信息
<error-page>
<exception-type>java.lang.Exception</exception-type>
<location>/error.jsp</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/404.jsp</location>
</error-page>
*isErrorPage:指示JSP对应的Servlet中是否产生exception内置对象。
*contentType:作用就是response.setContentType("")
*pageEncoding:指定JSP引擎读取JSP文件时使用的编码
pageEncoding有双重作用,在实际开发中,指定为UTF-8即可
TOmcat会用UTF-8读JSP
同时JSP对应的Servlet字符输出流使用UTF-8,还告知了IE用UTF-8进行显示
*isELIgnored:是否忽略EL表达式。默认是false。
include:
作用:包含.静态包含,多个文件翻译成一个文件
动作指令:<jsp:include/>动态包含,文件还是独立的,但是服务器还是合一起输出
静态包含比动态包含少占资源,能用静态就用静态包含.

taglib:
作用:引入外部标签