Java web开发——会话与状态

打个广告,帮朋友卖点东西,东西超便宜的哟【衣服鞋子等】,厂家直接出货,绝对低于市场价!!! 一般都比市场价便宜3—7折【都是牌子货】,如果您感兴趣,可以扫描屏幕下方的二维码,感谢关注!!!

微信

一、request和response

1、request

1.获取环境信息

public class ServletRequest extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
​
        test1(request);
    }
​
    //获取环境信息
    private void test1(HttpServletRequest request) {
        //uri是url的子集
        System.out.println(request.getRequestURL());//得到请求url地址;http://localhost:8080/day08/servlet
        System.out.println(request.getRequestURI());//得到请求的资源;/day08/servlet

        //得到来访者的ip
        System.out.println(request.getRemoteAddr());

        //http:.......servlet?name=sax
        System.out.println(request.getQueryString());//返回name=sax

        System.out.println(request.getRemoteHost());//返回客户机的主机名,
        System.out.println(request.getRemotePort());//返回客户机网络端口号
        System.out.println(request.getLocalAddr());//返回服务器的ip
        System.out.println(request.getLocalName());//返回服务器的主机名

        //返回请求方式
        System.out.println(request.getMethod());//get,post
    }

2.获取请求头

//获取请求头
    private void test2(HttpServletRequest request) {
​
        //该方法只获取一个值(第一个)
        String head=request.getHeader("Accept-Encoding");//获取支持的压缩格式
        if(head.contains("gzip")){//获取支持的压缩格式
            //输出压缩数据
        }else{
            //输出不压缩数据
        }

        //获取指定名称的头的所有值
        Enumeration e=request.getHeaders("Accept-Encoding");
        while(e.hasMoreElements()){
            String value=(String) e.nextElement();
            System.out.println(value);
        }

        //获取所有请求头的名称和值
        e=request.getHeaderNames();
        while(e.hasMoreElements()){
            String name=(String) e.nextElement();
            String value=request.getHeader(name);
        }

    }

3.获取请求数据

//获取客户机的请求数据
    private void test3(HttpServletRequest request) {
​
        //localhost......?name=sax
        String value=request.getParameter("name");//返回sax

        //localhost.....?like=string&like=hhhd
        String likes[]=request.getParameterValues("like");
        for(int i=0;likes!=null&&i<likes.length;i++){//防止空指针
            System.out.println(likes[i]);
        }

        localhost.....?name=string&password=hhhd
        Enumeration e=request.getParameterNames();
        while(e.hasMoreElements()){
            String name=(String) e.nextElement();
            value=request.getParameter(name);
            System.out.println(name+"="+value);
        }

        //name=sax&like=ss&like=ff,框架中常用
        Map<String, String[]> map=request.getParameterMap();
        for(Entry<String, String[]> me:map.entrySet()){
            String name=me.getKey();
            String[] v=(String[])me.getValue();
            System.out.println(name+"="+v[0]);
        }
        
    }

4.常见问题

1.数据检查

    //检查数据是否为空
    private void test4(HttpServletRequest request) {
​
        //localhost......?name=sax
        String value=request.getParameter("name");//返回sax
        if(value==null||value.trim().equals(""))//null ;""; "   ";都不行,trim()表示去掉字符串中的空格
        {System.out.println("不行");}  
    }

2.提交中文数据

    //数据为中文,浏览器以哪个码表打开提交的数据就是哪个码表,
    private void test5(HttpServletRequest request) throws IOException {
​
        //post方式,setCharacterEncoding对get无效
        //localhost......?name=中国
        request.setCharacterEncoding("UTF-8");//在编写网页时控制浏览器编码方式为UTF-8
        String value=request.getParameter("name");//返回中国
        System.out.println(value);
        
        //get方式
        byte source[]=value.getBytes("iso8859-1");//得到客户机提交的原始数据(Tomcat默认)
        value=new String(source,"UTF-8");//UTF-8是浏览器提交的编码方式
        System.out.println(value);
    }

注意:该方法不建议使用,get方式乱码还可以通过改服务器配置service.xml来解决

方法1:

    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" URIEncoding="UTF-8"/>

方法2:

    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" useBodyEncodingForURI="true"/>

但是该方法还是要依赖环境(Tomcat服务器),也不推荐,而如果采用url编码则可以解决以上问题。浏览器中两次URL编码。服务器中自己再做一次URL解码。

3.请求的转发

    //用request实现请求转发
    private void test4(HttpServletRequest request) {
        String data="asda";
        
        //11this.getServletContext().setAttribut("data",data);//开发中不能用这个取数据(并发)    
        
        //22
        request.setAttribute("data",data);//因为每次访问都创建一个request,故不会有并发问题
             //方法1
        RequestDispatcher rd = request.getRequestDispatcher("/test.jsp");
        rd.forward(request, response);
             
            /*方法2:用servletContext
        ServletContext context = this.getServletContext();
        RequestDispatcher rd = context.getRequestDispatcher("/test.jsp");
        rd.forward(request, response);  //相当于调用ServletDemo2的doget(),故地址栏不变
            */
    }

在test.jsp中

<body>
<%
//对应11
//String data=(String)this.getServletContext.getAttribut("data");
//out.write(data);
//对应22
String data=(String)request.getAttribut("data");
out.write(data);
%>
</body>

注意:

1、在forward(req,res)之前的输出数据缓存区中的内容都会被清掉,响应头中的数据不会被清掉。

2、获取当前web应用的名称可以用request.contextPath来获取

3、请求转发除了forward之外还有include,用来包含另外一个servlet

    //用request实现请求转发
    private void test4(HttpServletRequest request) {
​
        request.getRequestDispatcher("/head").include(request, response);
        response.getWriter().write("<br/>adf<>br/>")
        request.getRequestDispatcher("/foot").include(request, response);
​
    }

注意:包含不会清除之前的输出数据缓存区中的内容。

2、response

1.基本方法

     在HttpServletresponse中封装了向客户端响应的响应状态码、响应头和数据(参照HTTP协议)

                                    方法                             含义
setStatus(int sc)设置状态码
setHeader(String name,String value)设置响应头
getWriter()获取字符流
getOutprintStream()获取字节流

注意:getWriter()方法和getOutprintStream()方法互斥,只能调用一个方法。(注意在servlet的转发中可能碰到)

2.常见应用

1.输出文字

通过字节流

public class ServletResponse1 extends HttpServlet {
​
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
​
        test1(response);

    }
​
    //通过字节流获取汉字
    private void test1(HttpServletResponse response) throws IOException {
        String data="中国";
        /*
        OutputStream out=response.getOutputStream();
        out.write(data.getBytes());
        //该代码可能出现乱码(除非字节在编码时的方式与浏览器打开的时的编码方式相同)
        //详细原理:
         * out.write(data.getBytes())=
         * bety b[]=data.getBytes();采用gb2312保存到b[]
         * out.write(b);
         * 浏览器取出b,可能采用不同的编码
        */
        //方法1
        OutputStream out=response.getOutputStream();
        response.setHeader("content-type", "text/html;charset=UTF-8");//告诉浏览器编码方式为UTF-8
        byte b[]=data.getBytes("UTF-8");//保存形式为UTF-8
        out.write(b);
        
        /*
        //方法2:模拟http响应头
        OutputStream out=response.getOutputStream();
        out.write("<meta http-equiv='content-type' content='text/html;charset=UTF-8'>".getBytes());
        byte b[]=data.getBytes("UTF-8");//保存形式为UTF-8
        out.write(b);
        */
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
​
    }
​
}

通过字符流

// 通过字符流获取汉字
    private void test2(HttpServletResponse response) throws IOException {
        String data = "中国";
​
        // 告诉浏览器编码方式为UTF-8
        response.setHeader("content-type", "text/html;charset=UTF-8");
​
        // 设置response字符转换为字节时的编码方式(字符流转换为字节流这一过程response自己完成)
        response.setCharacterEncoding("UTF-8");
​
        PrintWriter out = response.getWriter();// 默认为iso8859-1
        out.write(data);
​
    }

2.文件下载

// 通过字节流下载文件
    private void test3(HttpServletResponse response) throws IOException {

        String realpath=this.getServletContext().getRealPath("/down/1.jpg");//获取其绝对路径,webroot路径下
        String filename=realpath.substring(realpath.lastIndexOf("\\"+1));//含义看Servlet下ServletContext

        response.setHeader("content-disposition", "attachment;filename="+filename);
        //如果文件名是中文名,中文名要经过URL编码
        //response.setHeader("content-disposition", "attachment;filename="+URLEncoder.encode(filename,"UTF-8"));

        FileInputStream in=new FileInputStream(realpath);//文件装载

        //文件打出
        int len = 0;
        byte buffer[] = new byte[1024];
        OutputStream out = response.getOutputStream();
        while((len=in.read(buffer))>0){
            out.write(buffer,0,len);
        }
        in.close();
    }

注意:读取除字符串以外的文件只能通过字节流,因为如果采用字符流可能导致数据丢失(编码转换问题)

3.生成动态图片

    private void test1(HttpServletResponse response) throws IOException {

        //6.通知浏览器不要缓存图片,不然回车不改变
        response.setHeader("Expires", "-1");
        response.setHeader("Cache-Control", "no-cache");
        response.setHeader("Pragma", "no-cache");
        //5.通知浏览器以图片方式打开
        response.setHeader("Content-type", "image/jpeg");

        //1.在内存中创建一幅图片
        BufferedImage image=new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB);

        //2.得到图片
        Graphics g=image.getGraphics();

        //3.向图片上写数据
        g.setColor(Color.RED);//设置背景的颜色         
        g.fillRect(0,0,80,20);//设置背景的颜色 
       
        g.setColor(Color.RED);//设置数字的颜色
        g.setFont(new Font(null,Font.BOLD,20));
        g.drawString(markNum(), 0,20);//markNum()为生成随机数的方法(生成7位数字)

        //4.将图片写到浏览器
        ImageIO.write(image, "jpg",  response.getOutputStream());

    }
    private String markNum(){
        Random r=new Random();
        String num=r.nextInt(9999999)+"";//0-99999999
        StringBuffer sb=new StringBuffer();
        for(int i=0;i<7-num.length();i++)
        {
            sb.append("0");//在前面补零
        }
        num =sb.toString()+num;
        return num;
}

4.定时刷新

    private void test1(HttpServletResponse response) throws IOException {

        response.setHeader("refresh", "5");//五秒刷新一次

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

        response.setCharacterEncoding("UTF-8");
        response.getWriter().write("我是中国人");
    }

5.请求的重定向

    private void test1(HttpServletResponse response) throws IOException {

        response.sendRedirect("/day06/1.html");//项目名为day06!!!
        /*实际上重写了
        response.setHeader("location", "/day06/1.html");
        response.setStatus(302);
        */
    }

注意:

1.尽量不使用重定向,因为该方法将向服务器发送两次请求

2.“/”如果是给服务器用的,则代表web工程,“/”如果是给浏览器用的,则代表webapps

    private void test1(HttpServletResponse response) throws IOException {
        //程序处理的是url资源,用“/”,程序读取硬盘用“\\”

        //servletContent
        this.getServletContext().getRealPath("/download/11.jpg");//表示项目名

        //forward
        this.getServletContext().getRequestDispatcher("/register.html");//表示项目名

        //sendRedirct
        response.sendRedirect("/day08/register.html");//表示webapps

        //html <a href=""></a>
        /*
         <a href="/day08/servlet">点我</a>//表示webapps
         */
    }

二、会话的管理

1、基本概念

1.会话的含义

     会话可简单理解为:用户开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一个会话。

2.要解决的问题

每个用户在使用浏览器与服务器进行会话的过程中,不可避免各自会产生一些数据,程序要想办法为每个用户保存这些数据。例如:用户点击超链接通过一个servlet购买了一个商品,程序应该想办法保存用户购买的商品,以便于用户点结帐servlet时,结帐servlet可以得到用户购买的商品为用户结帐。

 

思考:用户购买的商品保存在request或servletContext中行不行?不行,request(保存时间仅仅为一次请求),servletContext(有并发问题)

2、保存会话

1.Cookie

Cookie是客户端技术,程序把每个用户的数据以cookie的形式写给用户各自的浏览器。当用户使用浏览器再去访问服务器中的web资源时,就会带着各自的数据去。这样,web资源处理的就是用户各自的数据了。

2.Session

Session是服务器端技术,利用这个技术,服务器在运行时可以为每一个用户的浏览器创建一个其独享的session对象,由于session为用户浏览器独享,所以用户在访问服务器的web资源时,可以把各自的数据放在各自的session中,当用户再去访问服务器中的其它web资源时,其它web资源再从用户各自的session中取出数据为用户服务。

3、Cookie

1.示意图

2.常用方法

javax.servlet.http.Cookie类用于创建一个Cookie,response接口也中定义了一个addCookie方法,它用于在其响应头中增加一个相应的Set-Cookie头字段。 同样,request接口中也定义了一个getCookies方法,它用于获取客户端提交的Cookie。Cookie类的方法: 

  • public Cookie(String name,String value)
  • setValue与getValue方法 
  • setMaxAge与getMaxAge方法  //Cookie的有效时间,如果不设置一个会话结束(即浏览器打开和关闭的时间)
  • setPath与getPath方法   //此处Path表示有效域,即指定该Cookie在哪个路径下有效(如有项目svn,下有路径servlet/Demo;可以将其设置为/svn或/svn/servlet,分别表示在其路径下有效)
  • setDomain与getDomain方法
  • getName方法 

3.举例说明

1.显示上次访问的时间

//网站首页:可以实现显示用户上次访问时间
public class CookieDemo1 extends HttpServlet {
​
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
​
        response.setContentType("text/html;charset=UTF-8");

        PrintWriter out = response.getWriter();
        out.write("这是网站首页!!<br/><br/>");

        out.write("您上次访问时间是:");
        //得到上次访问时间
        Cookie cookies[] = request.getCookies();//获取Cookie
        for(int i=0;cookies!=null && i<cookies.length;i++){
            Cookie cookie = cookies[i];
            if(cookie.getName().equals("lastAccessTime")){
                Long time = Long.parseLong(cookie.getValue());
                Date d = new Date(time);
                out.write(d.toLocaleString());
            }
        }



        //给用户以cookie的形式送最新的时间
        Cookie cookie = new Cookie("lastAccessTime",System.currentTimeMillis()+"");//给lastAccessTime=当前时间
        cookie.setMaxAge(10000);  //保存时间(秒),不设置,一个会话结束 
        cookie.setPath("/day06");表示在day06这个项目下有效,如果不设,默认在该servlet访问路径同级有效,如该servlet为local.../day6/servlet/ServletCookie,则其有效路径为day6/servlet

        response.addCookie(cookie);//将该cookie发给浏览器

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

2.删除Cookie(已存在浏览器中)

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
​
        Cookie cookie = new Cookie("lastAccessTime",System.currentTimeMillis()+"");
        cookie.setMaxAge(0);将其保存时间设置为0
        cookie.setPath("/day06");

        response.addCookie(cookie);

    }

4.注意事项

  • 一个Cookie只能标识一种信息,它至少含有一个标识该信息的名称(NAME)和设置值(VALUE)。 
  • 一个WEB站点可以给一个WEB浏览器发送多个Cookie,一个WEB浏览器也可以存储多个WEB站点提供的Cookie。
  • 浏览器一般只允许存放300个Cookie,每个站点最多存放20个Cookie,每个Cookie的大小限制为4KB。
  • 如果创建了一个cookie,并将他发送到浏览器,默认情况下它是一个会话级别的cookie(即存储在浏览器的内存中),用户退出浏览器之后即被删除。若希望浏览器将该cookie存储在磁盘上,则需要使用maxAge,并给出一个以秒为单位的时间。将最大时效设为0则是命令浏览器删除该cookie。
  • 注意,删除cookie时,path必须一致,否则不会删除

5.应用举例

1.程序说明

     设置一个程序,可以记录你曾经访问过的商品:首页中有所有商品,和曾经访问过的商品(显示3个),如果点击商品,进入详细页面并返回id=?(2,3,5,1,3,1),设置Cookie book=(2,3_2,5_3_2,1_5_3,3_1_5,1_3_5)

2.详细设计

首页(要获取cookie)

//首页
public class CookieDemo3 extends HttpServlet {
​
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
​
        //1.显示网站所有商品
        out.write("本网站有如下书籍:<br><br>");
        Set<Map.Entry<String, Book>> set = DB.getAll().entrySet();
        for(Map.Entry<String, Book> me : set){
            Book book = me.getValue();
            out.write("<a href='/day07/servlet/CookieDemo4?id="+book.getId()+"' target='_blank'>"+book.getName()+"</a>");//target='_blank'表示在新窗口打开
            out.write("<br/>");
        }


        //2.显示用户曾经浏览过的商品
        out.write("<br/><br/>您曾经浏览过的商品:<br/>" );
        Cookie cookies[] = request.getCookies();
        for(int i=0;cookies!=null && i<cookies.length;i++){
            Cookie cookie = cookies[i];
            if(cookie.getName().equals("bookHistory")){
                String bookHistory = cookie.getValue();  //  2_3
                String ids[] = bookHistory.split("\\_");  //将2_4_1格式拆成2,4,1
                for(String id: ids){
                    Book book = (Book) DB.getAll().get(id);
                    out.write(book.getName() + "<br/>");
                }
            }
        }


    }
​
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
​
        doGet(request, response);
    }
}
​
class DB//模拟数据库,存放数据
{
    private static Map<String,Book> map = new LinkedHashMap();
    static{
        map.put("1", new Book("1","javaweb开发","老张","一本好书"));
        map.put("2", new Book("2","spring开发","老黎","一本好书"));
        map.put("3", new Book("3","hibernate开发","老佟","一本好书"));
        map.put("4", new Book("4","struts开发","老毕","一本好书"));
        map.put("5", new Book("5","ajax开发","老张","一本好书"));
    }

    public static Map getAll(){
        return map;
    }


}
​
​
class Book{//书的属性

    private String id;
    private String name;
    private String author;
    private String description;

    //alt+ shift + s


    public Book() {
        super();
        // TODO Auto-generated constructor stub
    }
    public Book(String id, String name, String author, String description) {
        super();
        this.id = id;
        this.name = name;
        this.author = author;
        this.description = description;
    }

        //get,set方法

}

详细页(要添加cookie,获取cookie)

public class CookieDemo4 extends HttpServlet {
​
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
​
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();

        //1.根据用户带过来的id号,显示商品的详细信息
        String id = request.getParameter("id");
        Book book = (Book) DB.getAll().get(id);

        out.write("您要查看的书的详细信息如下:<br/><br/>");
        out.write(book.getId() + "<br/>");  
        out.write(book.getName() + "<br/>");
        out.write(book.getAuthor() + "<br/>");
        out.write(book.getDescription() + "<br/>");


        //2.给用户回送包含当前商品id的cookie
        String bookHistory = makeHistory(request,id);    //  3_2
        Cookie cookie = new Cookie("bookHistory",bookHistory);
        cookie.setMaxAge(1*30*24*3600);

        response.addCookie(cookie);

    }
​
    private String makeHistory(HttpServletRequest request, String id) {

        String bookHistory = null;
        Cookie cookies[] = request.getCookies();//获取Cookie
        for(int i=0;cookies!=null&&i<cookies.length;i++){
            if(cookies[i].getName().equals("bookHistory")){
                bookHistory = cookies[i].getValue();
            }
        }

        //  bookHistory=null      1    bookHistory=1
        //  bookHistory=3_1_5     1    bookHistory=1_3_5
        //  bookHistory=3_2_5     1    bookHistory=1_3_2
        //  bookHistory=3_2       1    bookHistory=1_3_2


        //  bookHistory=null      1    bookHistory=1
        if(bookHistory==null){
            return id;
        }

        List l = Arrays.asList(bookHistory.split("\\_"));   //拆分[3,4]  //数组  链接
        LinkedList<String> list = new  LinkedList();
        list.addAll(l);

        if(list.contains(id)){
            //  bookHistory=3_1_5     1    bookHistory=1_3_5
            list.remove(id);
            list.addFirst(id);
        }else{
            if(list.size()>=3){
                //  bookHistory=3_2_5     1    bookHistory=1_3_2
                list.removeLast();
                list.addFirst(id);
            }else{
                //  bookHistory=3_2       1    bookHistory=1_3_2
                list.addFirst(id);
            }
        }

        StringBuffer sb = new StringBuffer();  //2_3_4,合成
        for(String lid: list){
            sb.append(lid + "_");//每个数字后面加一个“_”
        }

        return sb.deleteCharAt(sb.length()-1).toString();//把最后一个“_”去掉并返回
    }
​
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
​
        doGet(request, response);
    }
​
}

4、session

1.示意图

注意:每个浏览器对应一个session(默认情况下),服务器在获取session时直接调用request.getSession方法,如果有,则调用,没有,则先创建(服务器会自己创建)

2.案例分析

     做一个购物程序,用session存储用户购买的商品,在首页中有商品名称及购买链接,点击购买跳到显示所有购买过的商品页面中

显示所有商品的页面:

//首页:列出所有书
public class IndexServlet extends HttpServlet {
​
    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/>");

        Set<Map.Entry<String,Book>> set = DB.getAll().entrySet();
        for(Map.Entry<String,Book> me : set){
            Book book = me.getValue();
            out.write(book.getName()  + "   <a href='/day07/servlet/BuyServlet?id="+ book.getId() +"'>购买</a><br/>");
        }

    }
​
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
​
        doGet(request, response);
    }
​
}
​
​
class DB
{
    private static Map<String,Book> map = new LinkedHashMap();
    static{
        map.put("1", new Book("1","javaweb开发","老张","一本好书"));
        map.put("2", new Book("2","spring开发","老黎","一本好书"));
        map.put("3", new Book("3","hibernate开发","老佟","一本好书"));
        map.put("4", new Book("4","struts开发","老毕","一本好书"));
        map.put("5", new Book("5","ajax开发","老张","一本好书"));
    }

    public static Map getAll(){
        return map;
    }
}
​
​
class Book{

    private String id;
    private String name;
    private String author;
    private String description;

    //alt+ shift + s


    public Book() {
        super();
        // TODO Auto-generated constructor stub
    }
    public Book(String id, String name, String author, String description) {
        super();
        this.id = id;
        this.name = name;
        this.author = author;
        this.description = description;
    }

    //get和set

}

处理页面:

public class BuyServlet extends HttpServlet {
​
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
​
        String id = request.getParameter("id");
        Book book = (Book) DB.getAll().get(id);  //得到用户想买的书

        HttpSession session = request.getSession();

        List list = (List) session.getAttribute("list");  //得到用户用于保存所有书的容器
        if(list==null){
            list = new ArrayList();
            session.setAttribute("list", list);
        }
        list.add(book);//不懂

        //request.getRequestDispatcher("/servlet/ListCartServlet").forward(request, response);转发
        resquest.sendRedirect("/day07/servlet/ListCartServlet");//重定向       

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

显示购买过的商品:

    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();
        List<Book> list = (List) session.getAttribute("list");
        if(list==null || list.size()==0){
            out.write("对不起,您还没有购买任何商品!!");
            return;
        }

        //显示用户买过的商品
        out.write("您买过如下商品:<br>");
        for(Book book : list){
            out.write(book.getName() + "<br/>");
        }

    }

注意:以上案例仅在一次会话中有效

3.原理解析

以下分析可参照上例

     服务器用session保存会话的原理是在服务器为一个浏览器创建一个session时,服务器将session的id已cookie(默认情况下一个会话就失效)的形式发送给服务器,同时自己保存该session(默认30分钟为被使用后失效),如果该浏览器再次访问该服务器,将会将session的id带给服务器,然后服务器将再行查找。

故,如果想让浏览器在关闭后仍然有效,需要:

        HttpSession session = request.getSession();
        Cookie cookie = new Cookie("JSESSIONID",session.getId());//获取其id
        cookie.setMaxAge(30*60);
        cookie.setPath("/day07");
        response.addCookie(cookie);

注意:在一个地方设置即可

 

同时如果浏览器禁用的Cookie,将导致服务器无法正常使用session(表现为点击购买后跳转到的显示购买商品为无,本次刚点击的也不存在),可以采用URL重写方法来解决(将session的id附在url后面),在处理页面中:

URL重写:

  • response. encodeRedirectURL(java.lang.String url) :用于对sendRedirect方法后的url地址进行重写。
  • response. encodeURL(java.lang.String url):用于对表单action和超链接的url地址进行重写 

//request.getRequestDispatcher("/servlet/ListCartServlet").forward(request, response);//原

String url = response.encodeRedirectURL("/day07/servlet/ListCartServlet");//显示交给其去处理
System.out.println(url);
response.sendRedirect(url);

如此修改后可以显示本次点的的商品(但之前的不存在),如果列出所有的购买过的商品,修改显示所有商品的页面:

out.write("本网站有如下书:<br/>");

Set<Map.Entry<String,Book>> set = DB.getAll().entrySet();
for(Map.Entry<String,Book> me : set){
    Book book = me.getValue();
    //out.write(book.getName()  + "   <a href='/day07/servlet/BuyServlet?id="+ book.getId() +"'>购买</a><br/>");
    String url = "/day07/servlet/BuyServlet?id=" + book.getId();//在day07项目下
    url = response.encodeURL(url);
    out.println(book.getName()  + "   <a href='"+url+"'>购买</a><br/>");

注意:如果浏览器不禁用Cookie,URL将不会被重写(服务器自己判断),重写并不能实现关闭浏览器后再打开还有信息

4.常见应用

  • 使用Session完成用户登陆
  • 利用Session防止表单重复提交
  • 利用Session实现一次性验证码

 

以实现验证码为例:

     有登陆页面login.html其中有随机验证码图片,在进入该页面时服务器将产生一个随机数保存在session中,同时将其显示在图片中,用户填写后提交,服务器在和session中的值进行对比

login.html

    <form action="/day07/servlet/LoginServlet2" method="post">
        用户名:<input type="text" name="username"><br/>
        密码:<input type="password" name="password"><br/>
        认证码:<input type="text" name="checkcode"><img src="/day07/servlet/ImageServlet"><br/>
        
        <input type="submit" value="登陆">
    </form>

ImageServlet(参加response中的生成动态图片)

 

LoginServlet2

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
​
        String checkcode = request.getParameter("checkcode");
        String s_checkcode = (String) request.getSession().getAttribute("checkcode");
        if(checkcode==null || s_checkcode==null || !checkcode.equals(s_checkcode)){
            System.out.println("认证码错误!!");
            return;
        }


        //得到用户名和密码,帮用户完成登陆

    }

 

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

盡盡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值