Servlet——Session(2)之简单应用

来源:互联网 发布:剑三萝莉脸型数据网盘 编辑:程序博客网 时间:2024/05/22 22:49

Session技术的应用

1.防止用户非法登录到某个页面

比如我们的用户管理系统,必须要登录成功后才能跳转到主页面,而不能直接绕过登录页面直接到主页面,这个应用是一个非常常见的应用。
这时候,我们需要使用到Session技术,如下,当在验证用户的控制器LoginClServlet.java验证用户成功后,将当前的用户信息保存在Session对象中:

// 把user对象保存在sessionHttpSession session = request.getSession();session.setAttribute("login-user", user);

然后在主页面MainFrame.java最开始的地方,取出Session中的登录用户信息,如果信息为空,则为非法访问,直接跳转到登录页面,并提示相关信息:

// 取出login-user这个sessionUser login_user = (User)request.getSession().getAttribute("login-user");if(login_user == null){    // 说明用户没有登录,让他跳转到登录页面    request.setAttribute("error", "请登录!");    request.getRequestDispatcher("/LoginServlet").forward(request,response);    // 这个return很重要!    return;}

那么这里就存在一个问题,一个网站会有很多个需要防止非法访问的页面,如果都是用这种方法岂不是很麻烦?

这里有两种解决办法:
第一种是将这段验证用户的代码封装成函数,每次调用
第二种是使用过滤器(后面会介绍)

2.用户登录时验证输入的验证码是否正确

原理:使用到java的绘图技术
假设我们编写登录页面Login,验证用户的LoginClServlet,以及生成验证码的CreateCode,如下所示:

目录结构

用户在访问登录页面Login的时候,Login页面会去请求CreateCode这个Servlet生成验证码,然后显示在自己的页面上,然后再提交到LoginClServlet进行验证。很显然,访问Login和请求CreateCode这是从浏览器发出的两次不同的请求,所以,CreateCode产生的验证码字符串必须放入Session中,才能让LoginClServlet拿到,然后进行验证。

那么怎么让登录页面Login显示验证码呢?其实很简单,直接将img的src指向CreateCode这个Servlet即可,如下所示:

out.println("<font color=white>验证码:<input type='text' name='checkcode'/><img src='/mycheckcode/CreateCode'>");

可以看到运行结果:

运行结果

这个登录表单提交到LoginClServlet进行验证,它需要从参数中获取用户输入的验证码,再从Session中取出CreateCode这个Servlet放入Session中的正确的验证码,然后对比两者,它的doGet方法的关键代码如下:

//获取用户的id/password/输入的验证码String id = request.getParameter("id");String passwd = request.getParameter("passwd");// 用户输入的验证码String input_checkcode = request.getParameter("checkcode");// 正确的验证码String checkcode = (String)request.getSession().getAttribute("checkcode");// 先看验证码对不对if(input_checkcode.toLowerCase().equals(checkcode)){    // 验证码OK,再到数据库验证id和passwd}else{    request.setAttribute("error", "验证码有误");    request.getRequestDispatcher("/Login").forward(request, response);}

这里最重要的其实是生成验证码的Servlet,Servlet代码如下

import java.awt.Color;import java.awt.Font;import java.awt.Graphics;import java.awt.image.BufferedImage;import java.io.IOException;import java.util.Random;import javax.imageio.ImageIO;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class CreateCode extends HttpServlet {    public void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        // 7.禁止浏览器缓存随机图片        response.setDateHeader("Expires", -1);        response.setHeader("Cache-Control", "no-cache");        response.setHeader("Pragma", "no-cache");        // 6.通知客户机以图片方式打开发送过去的数据        response.setHeader("Content-Type", "image/jpeg");        // 1.在内存中创建一幅图片        BufferedImage image = new BufferedImage(110, 30,                BufferedImage.TYPE_INT_BGR);        // 2.向图片上写数据        Graphics g = image.getGraphics();        // 设背景色        g.setColor(Color.white);        g.fillRect(0, 0, 110, 30);        String checkcode = "";        // 画5个验证码字符        for(int i=0;i<5;i++){            g.setColor(generateColor());            g.setFont(generateFont());            String str = generateStr();            checkcode += str;            g.drawString(str,20*i,25);        }        // 画干扰点        for(int i=0;i<100;i++){            Random random = new Random();            int x = random.nextInt(110);            int y = random.nextInt(30);            g.setColor(generateColor());            g.fillOval(x, y, 2, 2);        }        // 画干扰线        for(int i=0;i<5;i++){            Random random = new Random();            int x1 = random.nextInt(110);            int y1 = random.nextInt(30);            int x2 = random.nextInt(110);            int y2 = random.nextInt(30);            g.setColor(generateColor());            g.drawLine(x1, y1, x2, y2);        }        // 这句话就是把随机生成的验证码,保存到session        // 验证码不区分大小写,所以这里转为小写        request.getSession().setAttribute("checkcode", checkcode.toLowerCase());        // 5.把写好数据的图片输出给浏览器        ImageIO.write(image, "jpg", response.getOutputStream());    }    /**     * 生成随机字体     * @return     */    public Font generateFont() {        String[] font_names = new String[] { "Broadway", "方正姚体",                "Footlight MT Light", "Sitka Text", "方正舒体", "幼圆" ,"Colonna MT"};        int[] font_styles = new int[]{Font.BOLD, Font.ITALIC, Font.BOLD|Font.ITALIC};        Random random = new Random();        int name_index = random.nextInt(font_names.length);        int style_index = random.nextInt(font_styles.length);        return new Font(font_names[name_index],font_styles[style_index],28);    }    /**     * 生成随机颜色     *      * @return     */    public Color generateColor() {        Random random = new Random();        return new Color(random.nextInt(256), random.nextInt(256),                random.nextInt(256));    }    /**     * 生成随机数[0-9a-zA-Z]     *      * @return     */    public String generateStr() {        String[] nums = new String[62];        // 添加0-9这10个数字        for (int i = 0; i < 10; i++) {            nums[i] = String.valueOf(i);        }        // 添加A-Z这26个大写字母        for (int i = 65; i < 91; i++) {            nums[i - 55] = Character.toString((char) i);        }        // 添加a-z这26个小写字母        for (int i = 97; i < 123; i++) {            nums[i - 61] = Character.toString((char) i);        }        // 产生一个随机数        Random random = new Random();        int index = random.nextInt(62);        return nums[index];    }    public void doPost(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        this.doGet(request, response);    }}

3.实现简易购物车

假设我们要在网上买书,那么怎么实现添加到购物车,并可以查看购物车的功能呢?肯定要使用Session。
首先,我们先写一个Book类,该类封装Book的相关信息,这里简单起见,主要有ID号,书名,以及购买的本数。然后模拟一个数据库,如下:

import java.util.HashMap;import java.util.LinkedHashMap;/** * 模拟数据库 */final public class DB {    private static HashMap<String, Book> hm = null;    private DB(){    }    static{        hm = new LinkedHashMap<String, Book>();        Book book1 = new Book("1", "Java基础", 0);        Book book2 = new Book("2", "Oracle数据库", 0);        Book book3 = new Book("3", "C语言", 0);        Book book4 = new Book("4", "Python核心教程", 0);        Book book5 = new Book("5", "Web技术", 0);        hm.put(book1.getId(),book1);        hm.put(book2.getId(),book2);        hm.put(book3.getId(),book3);        hm.put(book4.getId(),book4);        hm.put(book5.getId(),book5);    }    /**     * 得到数据库中所有的书     * @return     */    public static HashMap<String, Book> getBooks(){        return hm;    }    /**     * 根据ID得到书     * @param id     * @return     */    public static Book getBookById(String id){        if(hm.containsKey(id)){            return hm.get(id);        }        return null;    }}

然后在我们的showBook这个Servlet中读取数据库中所有的书的信息,显示在页面上,它的doGet方法为:

public void doGet(HttpServletRequest request, HttpServletResponse response)        throws ServletException, IOException {    response.setContentType("text/html;charset=utf-8");    PrintWriter out = response.getWriter();    out.println("<h2>欢迎光临</h2>");    out.println("<table border=1>");    HashMap<String, Book> books = DB.getBooks();    Iterator it = books.keySet().iterator();    while(it.hasNext()){        Book book = books.get(it.next());        out.println("<tr><td>"+book.getName()+"</td><td><a href='/MyCart/BuyBookCl?id="+book.getId()+"'>点击购买</a></td></tr>");    }    out.println("</table>");}

可以看到,当用户点击购买的链接时,跳到BuyBookCl这个Servlet进行处理,并且一同传递过去的参数为书的id号,我们看看BuyBookCl是怎么写的:

public void doGet(HttpServletRequest request, HttpServletResponse response)        throws ServletException, IOException {    response.setContentType("text/html;charset=utf-8");    //接收用户购买书的名字    String id = request.getParameter("id");    String name = DB.getBookById(id).getName();    HttpSession session = request.getSession();    // 用HashMap更简单    // 从session中得到购买的 书    HashMap<String,Book> books = (HashMap<String,Book>) session.getAttribute("books");    if(books == null){        books = new LinkedHashMap<String,Book>();    }    if(books.containsKey(id)){        Book book = books.get(id);        book.setNum(book.getNum()+1);    }else{        Book book = new Book(id, name, 1);        books.put(id, book);    }    session.setAttribute("books", books);    // 转发到ShowMyCart查看购物车       request.getRequestDispatcher("/ShowMyCart").forward(request, response);}

我们接收到书的id后,然后从Session中取出保存购物车信息的HashMap,如果这个HashMap为空,则新建一个HashMap;如果这个HashMap不为空,则去查找是否存在该书的ID号,如果已经存在,说明之前已经购买过该书,则将这本书的数量加1,,反之将新购买的书添加进去,并且数量设置为1。

看一下运行结果:
1.ShowBook的页面:

ShowBook

2.点击购买之后跳转到购物车的页面:

ShowMyCart


以上是应用Session的三个简单的例子,在实际项目中,肯定不止这么简单,比如购物车,最终肯定是要存储在数据库中的。

1 0
原创粉丝点击