Cookie和Session

目录

回顾

一.优化表白墙代码

二.Cookie 和 Session

1.Servlet中操作Cookie和Session Api

2.案例1:写一个模拟登录的案例:

3. 案例2:上传文件


回顾


1.Servlet API
2.HttpServlet
DoXXX处理哪种Http方法会调用到对应的方法
init/destroy/service--->servlet的生命周期
3.HttpServletRequest   Http请求      get系列方法
协议名(版本号)
url
query string
header
query String/body
HttpServletResponse Http响应    set系列方法

状态码
各种header
body


一.优化表白墙代码

当前表白墙写了多个DataSourse,使用单例模式优化
饿汉:类加载创建实例
懒汉:效率更高(首次调用创建实例)

public class DBUtil {
    private static DataSource dataSource=null;
    public DataSource getDataSource(){
        //首次调用的时候创建实例
        if(dataSource==null){
            dataSource=new MysqlDataSource();
            ((MysqlDataSource)dataSource).setURL("jdbc:/mysql://127.0.0.1:3306/java105?characterEncoding=utf8&useSSL=false");
            ((MysqlDataSource)dataSource).setUser("root");
            //数据库的密码
            ((MysqlDataSource)dataSource).setPassword("1309411303");
        }
        return dataSource;
    }
}



还要注意线程安全问题:
多个线程同时判定dataSouce为null,会创建多个实例
Servlet代码中,涉及到多线程/线程安全问题,
Servlet写的是一个服务器,同一时刻,可能要处理多个客户端的请求,一旦有多个客户端发送多个请求,服务器务必需要同时处理多个请求
Tomcat内部正式使用了多线程的方式

解决方案:
1.加上volatile

private static  volatile DataSource dataSource=null;



2.加锁

3.构造方法私有

二.Cookie 和 Session


Cookie 是浏览器在本地持久化保存数据的一种方案
一个典型的使用方式,存储登录信息

1.Servlet中操作Cookie和Session Api

在Servlet中也专门提供了相关的Api,让我们来操作Cookie和Session

HttpServlet类中的相关方法
方法描述
HttpSession getSession()

使用模式有俩中

参数填写 false 判定当前会话是否存在,如果不存在,直接返回对应的HttpSession对象

参数填写true,判定当前会话是否存在,如果不存在,就创建一个新的键值对,保存到哈希表中,并把生成的sessionId 返回到浏览器这里,

都是根据请求中的Cookie里的sessionId来查哈希表,如果存在则直接返回HttpSeeion对象

Cookie[]getCookie()返回一个数组, 包含客户端发送该请求的所有的 Cookie 对象. 会自动把Cookie 中的格式解析成键值对
HttpServletResponse类中的相关方法
方法描述
void addCookie(Cookie cookie)

返回响应,你想给浏览器返回哪些cookie,都可以通过这个方法来添加

在这里添加的键值对,都会体现在Http响应报文的SetCookie字段上

HttpSession类中的相关方法
方法描述
Object getAttribute(String
name)
该方法返回在该 session 会话中具有指定名称的对象,如果没
有指定名称的对象,则返回 null
void setAttribute(String
name, Object value)
该方法使用指定的名称绑定一个对象到该 session 会话
boolean isNew()判定当前是否是新创建出的会话
Cookie类中的相关方法
方法描述
String getName()该方法返回 cookie 的名称。名称在创建后不能改变。(这个值是 Set
Cooke 字段设置给浏览器的)
String getValue()该方法获取与 cookie 关联的值
void setValue(String
newValue)
该方法设置与 cookie 关联的值。


一个 HttpSession 对象里面包含多个键值对. 我们可以往 HttpSession 中存任何我们需要的信息.

每个 Cookie 对象就是一个键值对


理解会话机制
服务器同一时刻收到的请求是很多的. 服务器需要清除的区分清楚每个请求是从属于哪个用户, 就需要在服务器这边记录每个用户令牌以及用户的信息的对应关系


2.案例1:写一个模拟登录的案例:

构思内容:
1.登录页面,用户可以填写用户名+密码
2.Servlet来处理登录请求
3.使用另一个Servlet来生成主页内容(登录成功后,跳转到的页面)

具体步骤

1.构造form表单发给Servlet处理(注意三点匹配关系)
name(getParameter),method ,action


2.Servlet进行判定
当用户点击提交的时候,就会把刚才input框的name的值作为key,把input框里用户的输入,作为value,把这个键值对,放到body中提交给服务器,name属性决定了键值对中的建,通过服务器getParameter获取值



这里将字符串写到前面,肯定不是空的,一定不会出现空指针异常(好处double check),虽然equls内部已经针对参数为null进行从处理了

 3.登录成功创建新的会话(SessionId),设置键值对,并重定向到指定的页面

 if("zhangsan".equals(username)&&"123".equals(password)){
            //登陆成功
            //a)创建一个会话,用户刚登录成功,之前是没有会话的,重新分配一个新的会话给用户
            //创建sessionId和一个HttpSession 对象
            //把这俩个内容以键值对的形式插入到内存的哈希表中
            //把sessionId通过 set-cookie 写到响应中
            HttpSession session=req.getSession(true);
            //随意的设置键值对了(HttpSession 对象也相当于一个哈希表)
            session.setAttribute("username","zhangsan");
            //让响应重定向到主页
            resp.sendRedirect("index");
}

4.登录失败

 //登录失败
            resp.setStatus(403);
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write("登录失败,用户名或密码错误");

5.重定向后生成的主页内容

//登录成功后,跳转到的主页
@WebServlet("/index")
public class IndexServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //首页中先获取session,此处的session正是刚才登录页的时候,登录成功的逻辑中创建出来的
        //此处参数写作false即可,表示不新建,如果不存在,就返回null即可
        HttpSession session=req.getSession(false);
        if(session==null){
            resp.setStatus(403);
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write("你尚未登陆,不能访问主页");
            return;
        }
        String username=(String) session.getAttribute("username");
        resp.setContentType("text/html;charset=utf8");
        resp.getWriter().write("欢迎来到主页!" +username);
    }
}

理解3,5步骤

 完整代码:处理登录请求+登录页面+跳转后的服务器响应

 <form action="login" method="post">
    <input type="text" name="username">
    <input type="password" name="password">
    <input type="submit" value="登录">

package login;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

//使用这个类来处理登录请求
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.从请求中获取到页面提交的用户名和密码
        String username=req.getParameter("username");
        String password=req.getParameter("password");
        //2.验证用户名密码是否正确
        //正常这个操作是要查数据库,此处为了简单,直接写成硬编码了(把正确的用户名和密码写死了)
        //假定正确的密码是 zhangsan 123
        if("zhangsan".equals(username)&&"123".equals(password)){
            //登陆成功
            //a)创建一个会话,用户刚登录成功,之前是没有会话的,重新分配一个新的会话给用户
            //创建sessionId和一个HttpSession 对象
            //把这俩个内容以键值对的形式插入到内存的哈希表中
            //把sessionId通过 set-cookie 写到响应中
            HttpSession session=req.getSession(true);
            //随意的设置键值对了(HttpSession 对象也相当于一个哈希表)
            session.setAttribute("username","zhangsan");
            //让响应重定向到主页
            resp.sendRedirect("index");
        }else{
            //登录失败
            resp.setStatus(403);
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write("登录失败,用户名或密码错误");
        }
    }
}
package login;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

//登录成功后,跳转到的主页
@WebServlet("/index")
public class IndexServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //首页中先获取session,此处的session正是刚才登录页的时候,登录成功的逻辑中创建出来的
        //此处参数写作false即可,表示不新建,如果不存在,就返回null即可
        HttpSession session=req.getSession(false);
        if(session==null){
            resp.setStatus(403);
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write("你尚未登陆,不能访问主页");
            return;
        }
        String username=(String) session.getAttribute("username");
        resp.setContentType("text/html;charset=utf8");
        resp.getWriter().write("欢迎来到主页!" +username);
    }
}

3. 案例2:上传文件

前端,搭配form表单,允许通过浏览器选中一个文件,上传给服务器

<form action="upload" method="post" enctype="multipart/form-data">
    <input type="file"name="myfile">
    <input type="submit" value="提交">
</form>
HttpServletResponse类法
方法描述
Part getPart(String name)获取请求中给定 name 的文件
Collection<Part> getParts()获取所有的文件
Part类方法
String getSubmittedFileName()获取提交的文件名
String getContentType()获取提交的文件类型
long getSize()获取文件的大小
void write(String path)把提交的文件数据写入磁盘文件
方法描述
String getSubmittedFileName()获取提交的文件名
String getContentType()获取提交的文件类型
long getSize()获取文件的大小
void write(String path)把提交的文件数据写入磁盘文件

注意对应关系

 

完整代码

@WebServlet("/upload")
@MultipartConfig
public class UploadServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Part part=req.getPart("myfile");
        System.out.println(part.getSubmittedFileName());
        System.out.println(part.getSize());
        System.out.println(part.getContentType());
        part.write("c/program/result.jpg");
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值