目录
1.Servlet中操作Cookie和Session Api
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 是浏览器在本地持久化保存数据的一种方案
一个典型的使用方式,存储登录信息
在Servlet中也专门提供了相关的Api,让我们来操作Cookie和Session
| 方法 | 描述 |
| HttpSession getSession() | 使用模式有俩中 参数填写 false 判定当前会话是否存在,如果不存在,直接返回对应的HttpSession对象 参数填写true,判定当前会话是否存在,如果不存在,就创建一个新的键值对,保存到哈希表中,并把生成的sessionId 返回到浏览器这里, 都是根据请求中的Cookie里的sessionId来查哈希表,如果存在则直接返回HttpSeeion对象 |
| Cookie[]getCookie() | 返回一个数组, 包含客户端发送该请求的所有的 Cookie 对象. 会自动把Cookie 中的格式解析成键值对 |
| 方法 | 描述 |
| void addCookie(Cookie cookie) | 返回响应,你想给浏览器返回哪些cookie,都可以通过这个方法来添加 在这里添加的键值对,都会体现在Http响应报文的SetCookie字段上 |
| 方法 | 描述 |
| Object getAttribute(String name) | 该方法返回在该 session 会话中具有指定名称的对象,如果没 有指定名称的对象,则返回 null |
| void setAttribute(String name, Object value) | 该方法使用指定的名称绑定一个对象到该 session 会话 |
| boolean isNew() | 判定当前是否是新创建出的会话 |
| 方法 | 描述 |
| String getName() | 该方法返回 cookie 的名称。名称在创建后不能改变。(这个值是 Set Cooke 字段设置给浏览器的) |
| String getValue() | 该方法获取与 cookie 关联的值 |
| void setValue(String newValue) | 该方法设置与 cookie 关联的值。 |
一个 HttpSession 对象里面包含多个键值对. 我们可以往 HttpSession 中存任何我们需要的信息.
每个 Cookie 对象就是一个键值对
理解会话机制
服务器同一时刻收到的请求是很多的. 服务器需要清除的区分清楚每个请求是从属于哪个用户, 就需要在服务器这边记录每个用户令牌以及用户的信息的对应关系
构思内容:
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);
- }
- }
前端,搭配form表单,允许通过浏览器选中一个文件,上传给服务器
- <form action="upload" method="post" enctype="multipart/form-data">
- <input type="file"name="myfile">
- <input type="submit" value="提交">
- form>
| 方法 | 描述 |
| Part getPart(String name) | 获取请求中给定 name 的文件 |
| Collection | 获取所有的文件 |
| 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");
- }
- }