为了账号安全,请及时绑定邮箱和手机立即绑定

JavaWeb基础(六)-Cookie和Session

标签:
Java

1.Cookie和Session

在JavaWeb基础(五)中,我们分享了.Servlet规范Servlet生命周期Servlet请求流程Servlet初始化参数Servlet继承体系结构和设计原因
今天我主要来分享下Cookie和Session, Cookie和Session使用起来其实很简单, 主要用来解决多个request之间的数据共享问题。先说下我这篇博客会分享的内容.

  • Servlet3.0的注解Http协议存的问题Cookie技术Session技术总结下使用场景

1.1 Servlet3.0新增的注解

之前的编码中,我们每次增加一个Servlet。都需要到WEB-INF下配置web.xml.我们需要注册Servlet关联资源名.
而从J2EE6规范起, 我们就可以用注解的方式来配置这些信息.这个版本的Servlet即Servlet3.0, 对应着J2EE6的规范Tomcat7.*.

为什么引入Servlet配置注解方式

每个新技术的引入都是有一定应用场景, Servlet注解的引入主要是为了解决配置xml的繁琐和臃肿.因为随着Sevlet的增加, web.xml里的配置会爆炸性的增长, 这时候对于修改和维护该配置文件效率往往会非常低.

web.xml中的metadata-complete属性

该属性表示元数据的完整性.即xml是用来描述Servlet的,我们也可以把XML看成是描述Servlet的一种元数据.

  • 如果我们声明其为true。表示xml描述信息是完整的,那么这时候tomcat就不会再去解析Servlet的注解信息.

  • 如果我们声明其为false。表示xml描述信息是不完整的,那么这时候tomcat机会再去解析Servlet的注解信息, 这时候我们使用注解替代web.xml才会生效.

代码演示

我们之前分享的中,提到最多的配置是资源名称映射到Servlet配置Servlet初始化参数配置.我们就来看下如何使用注解来配置.首先这两个配置对应的是@WebServlet注解@WebInitParam注解.以下是其源代码, 我们只列出部分常见属性.

@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface WebServlet {    String name() default "";
    String[] value() default {};
    String[] urlPatterns() default {};    int loadOnStartup() default -1;
    WebInitParam[] initParams() default {};
}
@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface WebInitParam {    String name();    String value();
}

@WebServlet有namevalueurlPatternsloadOnStartupinitParams五个常用属性.

  • value和urlPatterns作用一样, 只是因为value是默认属性,所以我们可以不用写Key

  • initParams属性是一个数组, 元素类型是@WebInitParams注解, 其属性为name和value,name确定key值, value确定对应key的值。

  • 并且这些注解的生命周期都是能存储到运行时.所以其原理就是利用运行时在确定要资源名要关联的Servlet.

如下代码,使用Servlet注解

package com.sweetcs.web.servlet.servlet3_0;import java.io.IOException;import java.util.Arrays;import javax.jws.soap.InitParam;import javax.servlet.ServletException;import javax.servlet.annotation.WebInitParam;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;@WebServlet(
value={"/annotation_servlet"}, 
initParams={        @WebInitParam(name = "enocding", value ="UTF-8")
        })public class AnnotationServlet extends HttpServlet {    
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {        
        // 使用反射读取配置初始化参数
        Class<AnnotationServlet> clazz = null;        try {
             clazz = (Class<AnnotationServlet>) Class.forName("com.sweetcs.web.servlet.servlet3_0.AnnotationServlet");
             WebServlet annOfWebServlet = clazz.getAnnotation(WebServlet.class);
             System.out.println(Arrays.toString(annOfWebServlet.value()));
             System.out.println(Arrays.toString(annOfWebServlet.urlPatterns()));
             System.out.println(Arrays.toString(annOfWebServlet.initParams()));
        } catch (ClassNotFoundException e) {            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

启动浏览器, 输入http://127.0.0.1:8080/annotation_servlet. 运行输出如下.注解能在运行时成功读取到,其中value和urlpattern属性作用是一样,但是如果我们只配置其中一个,其只能读取到其中一个的值.

webp

web.xml和注解的选择

XML和注解区别

  • XML使得配置和Java相分离, 维护性较高。注解和Java代码耦合, 维护性低.

  • XML维护繁琐, 配置文件臃肿, 开发效率低。注解使得开发效率高, 方便快速定位.

选择
一般在企业级开发中, 我们当然要尽量的选择其优点, 所以我们在xml中做通用配置。个别的Servlet配置才用注解。

1.2 Http协议无状态带来的问题

一次会话

从打开浏览器,到关闭浏览器过程中的操作可以称为一次会话.我们把一次会话也称为Session。而一次会话中我们可以发送多次的请求Request.

Http协议的问题

http协议是一种无状态连接的协议.导致了服务端无法让多个请求共享数据.

说白话就是

  • 服务端不知道上一次是哪个客户端请求了自己

  • 一次会话中可以发送多次请求, 但是服务器却不知道这多次请求是来自同一个客户端

  • 问题:这也就导致了服务端无法让多个请求共享数据.为了解决这个问题就引入了参数传递机制Cookie技术Session技术

举个栗子

客户端例子

学过移动端开发的同学都知道, 对于同一个用户, 我们需要在多个页面之前传递数据.而因为Http协议的无状态连接问题导致我们无法在多个页面之前传递数据.这只是在客户端之前的一个例子, 并不准确。

服务端例子

在服务端开发中,涉及到网络通信,所以可以理解为多个请求无法标识,导致了服务端无法有效的利用之前的数据在多个请求前实现共享.这也就是导致了你发次请求过来,下次我就不知道是你了,如果有很多页面需要做权限控制,那么每次页面一跳转,由于Http协议的健忘性.你又得重新登入做权限验证

1.3 参数传递机制

为了解决服务端无法识别请求。我们可以在请求中自己附加参数,用来标记请求,这是最原始的解决方案。如下代码使用参数传递来解决数据共享问题.

登入界面

webp

登入界面

LoginServlet

@WebServlet(urlPatterns={"/login"})public class LoginServlet extends HttpServlet {    
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        
        req.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=UTF-8");
        
        String username = req.getParameter("username");
        String password =  req.getParameter("password");
        System.out.println("username = " + username +"password = " + password);
        IUserDAO userDAO = new UserDAOImpl();
        User user = userDAO.loginReturnUserOrNull(username, password);
        
        PrintWriter printWriter = resp.getWriter();        
        if (null == user) {
            printWriter.write("login failed");
        }else {
            resp.sendRedirect("/get?username=" + username);
        }
    }
    
}

GetServlet
负责显示邮件箱

@WebServlet(urlPatterns={"/get"})public class GetServlet extends HttpServlet{    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=UTF-8"); 
        PrintWriter pw = resp.getWriter();
        String username = req.getParameter("username");
        pw.write("用户:" + username + "<br />");        for (int i = 0; i < 6; i++) {
            pw.write("<a href="+"'/content?username="+ username +"'>第(" + i +")封邮件</a> <br />");
        }       
    }
}

邮箱界面, 显示邮件

webp



作者:sixleaves
链接:https://www.jianshu.com/p/c904e5116c9b


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消