08_会话技术

news2024/11/13 10:02:11

文章目录

  • 前置知识点
  • 会话技术Conversation
    • 客户端技术Cookie
      • Cookie的格式
      • Cookie的优缺点
      • 构造Cookie信息
        • 通过浏览器构造Cookie
        • 通过Postman构造Cookie
        • 通过服务器构造Cookie
      • 获取Cookie信息
      • Cookie中的信息
        • Path
        • Domain
        • MaxAge
      • 案例(cookie相关)
    • 服务器技术Session
      • 提供Session
      • 获取Session
      • 使用Session
      • Session的生命周期
    • 常见问题
    • 案例(重构登录案例,并且增加注销功能)
    • Cookie和Session的区别与联系
    • 数据共享

前置知识点

  • 响应头的设置
    • response.setHeader(String,String)
  • Postman中设置请求头
    • Header
  • URL编码
    • 浏览器能够完成编解码的工作
    • 比如我们发送一个Get请求(通过浏览器地址栏),其中的请求参数有中文,这个中文浏览器会自动进行URL编码 → Servlet中使用request获得请求参数的值,这个值是中文,说明request已经解码

eg:

public class URLEncodingDecodingExecution {
    public static void main(String[] args) throws UnsupportedEncodingException {
        // 提供编码的方法
        String encode = URLEncoder.encode("张三", "utf-8");
        System.out.println(encode); //%E5%BC%A0%E4%B8%89

        // 提供解码的方法
        String decode = URLDecoder.decode("%E5%BC%A0%E4%B8%89", "utf-8");
        System.out.println(decode); // 张三
    }
}

会话技术Conversation

  • 同一个客户端向服务器中发送的多个请求,需要信息共享
  • 在做服务器开发过程中,客户端和服务器之间,会有请求报文和响应报文
    • 客户端给服务器发送请求:请求报文
    • 服务器给客户端发送响应:响应报文
  • HTTP协议的无状态性,会导致服务器无法区分信息来自于哪个客户端
    • 无状态性:协议对于交互性场景没有记忆能力
    • eg:http://localhost:8080/demo1/user/list/user?userid=25;
    • 会产生弊端:
      • 用户信息不安全
      • 客户端和浏览器每一次发送请求的时候都需要携带请求参数比较繁琐
  • 引入会话技术,最重要的事情就是让服务器知道客户端是谁
  • 客户端直接携带确切的信息,这个就是客户端技术
    • 客户端技术:Cookie
    • eg:请求报文中携带对应的信息username=zs
  • 如果是通过客户端提供的编号,进而在服务器中进一步获得信息,那么这个就是服务器技术
    • 服务器技术:Session
    • eg:服务器中存储编号30012:zs
  • 服务器会话技术,是在客户端会话技术基础上的

客户端技术Cookie

  • 携带信息:客户端(浏览器)在向服务器发起请求的时候直接携带了信息,这些信息是通过请求头中一个特殊的请求头(特殊的请求头叫Cookie)携带的

Cookie的格式

  • Cookie:key1=value1;key2=value2
    • 携带的是键值对信息,携带的键值对信息都是字符串信息
    • 可以携带多组键值对信息,如果携带多组,中间使用分号分隔开

Cookie的优缺点

  • 优点:小巧、减轻了服务器压力、可以很轻松的实现多台主机、多个应用下的资源共享
  • 缺点:存储容量有限制 4kb、数据类型有限制只可以存储一些非敏感数据

构造Cookie信息

通过浏览器构造Cookie
  1. 打开开发者工具,快捷键F12
  2. 找应用程序(Application)
  3. 应用程序里找存储(Storage)里的Cookie
  4. 可以通过Fiddler获取Cookie值

通过Postman构造Cookie

eg:

  • 通过Postman进行创建
    在这里插入图片描述

  • 通过Fiddler进行抓取
    在这里插入图片描述


通过服务器构造Cookie

客户端 → 服务器,请求
服务器 → 客户端,响应(并且携带响应头set-cookie:key=value
客户端 → 服务器,请求(并且携带请求头cookie:key=value
客户端 → 服务器,请求(并且携带请求头cookie:key=value

eg:

/**
 * 发送请求
 * http://localhost:8080/demo1/cookie/set?username=zs
 */
@WebServlet("/cookie/set")
public class CookieSetServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String username = request.getParameter("username");
        response.setHeader("set-cookie","username=" + username);
        response.getWriter().println("cookie set finish, please check cookie");
    }
}

获取Cookie信息

  • Request中提供了直接获得Cookie的方法
    • Cookie[] cookies = request.getCookies();
  • 单个Cookie,我们先获得其键值对信息
    • 键:cookie.getName()
    • 值:cookie.getValue()

eg:

/**
 * 获取所有的cookie,然后进行打印
 */

@WebServlet("/cookie/fetch")
public class CookieFetchServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // String cookie = request.getHeader("cookie");
        Cookie[] cookies = request.getCookies();
        for (Cookie cookie : cookies) {
            String name = cookie.getName();
            String value = cookie.getValue();
            System.out.println(name + " : " + value);
        }
        /**
         * username : ls
         * Pycharm-89c7dd8b : 47f9fb69-6795-467d-875b-0a44c63e1e97
         * Idea-75c3c9a : b19ee743-c677-4bab-b7bd-673c42a25ce0
         */
    }
}


Cookie中的信息

Cookie这个实例中的封装信息:

信息方法说明
name有参构造方法核心值
value有参构造方法核心值
PathsetPath(String)设置Cookie的有效URI
DomainsetDomain(String)域名,做Cookie的共享
MaxAgesetMaxAge(int)cookie的有效时间、设置过期时间,单位是秒,如果超过这个时间Cookie就会过期
Path
  • 客户端发起的请求,是某个path的话,客户端在发起请求的时候才会携带这个cookie信息
  • 这个Path就是设置cookie的执行路径
    • cookie.setPath(String path)

eg:

@WebServlet("/cookie/path")
public class CookiePathServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse response)
            throws ServletException, IOException {
        // response.setHeader("set-cookie","xxxx=" + xxxx);
        Cookie cookie = new Cookie("username", "ls");

        // 默认Path:URI去除掉最后一级 uri=demo1/cookie/path
        // ---> path=demo1/cookie
        // 手动构造Path
        cookie.setPath("/demo1"); // 则/demo1目录下的cookie都有username=ls
        response.addCookie(cookie);
    }
}
Domain
  • 设置域名或ip,用来说不同域名下Cookie共享
    • 如果设置了Cookie的父域名,子域名下的请求可以共享父域名下的Cookie
    • eg:
      • 父域名:https://www.jd.com
      • 子域名:https://www.miaosha.jd.com
  • 不能设置和当前域名无关的domain,比如访问localhost时候设置一个ccc.com这样的domain是不可以的,否则浏览器会直接无视

eg:

@WebServlet("/cookie/domain")
public class CookieDomainServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse response)
            throws ServletException, IOException {
        Cookie cookie = new Cookie("username", "ww");
        cookie.setDomain("ccc.com");
        response.addCookie(cookie);
    }
}
MaxAge
  • 如果没有设置,则默认情况下存在于浏览器的内存中。关闭浏览器,则cookie信息失效
  • 设置一个maxAge=正数的时间,表示会在硬盘上面存活多少秒

eg:

@WebServlet("/cookie/maxage")
public class CookieMaxAgeServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse response)
            throws ServletException, IOException {
        Cookie cookie = new Cookie("userid", "251");
        cookie.setMaxAge(5); // 设置一个过期时间,如果没有设置,则浏览器关闭时会被清楚
        // 这个只有浏览器知道
        response.addCookie(cookie);
    }
}

案例(cookie相关)

在访问一个请求的时候,输出上一次访问的时间

思路:

  1. 访问该请求的时候,生成时间,放入到cookie中
  2. 访问该请求的时候,从cookie中取出这个时间,并且使用response做响应

eg:

@WebServlet("/last/access")
public class LastAccessServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 获取cookie中的上一次访问时间
        // 假设设定了cookie的name的last
        Cookie[] cookies = request.getCookies();
        String lastDateString = null;
        if (cookies != null & cookies.length != 0) {
            for (Cookie cookie : cookies) {
                if ("last".equals(cookie.getName())) {
                    lastDateString = cookie.getValue();
                }
            }
        }

        if(lastDateString != null) {
            String lastDateStringDecode = URLDecoder.decode(lastDateString, "utf-8");
            response.getWriter().println(lastDateStringDecode);
        }

        // 向浏览器的cookie中做当前时间的设置
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String nowDate = simpleDateFormat.format(new Date());
        String nowDateEncode = URLEncoder.encode(nowDate, "utf-8");
        response.addCookie(new Cookie("last", nowDateEncode));
    }
}

服务器技术Session

  • Session相当于每个用户存在服务器的保险柜,保险柜里可以存一些数据,这些数据也可以是敏感数据
  • 要获得保险柜要带着钥匙,如果钥匙丢了,就打不开这个保险柜

提供Session

  • Session不需要专门去提供,当我们获取Session的时候,其实就提供了Session给客户端
  • 在服务端获取Session的时候,其实会提供一个响应头set-cookie
    • JSESSIONID这样的一个key,其实就是保险柜的钥匙

获取Session

  • 获得Session可以使用Request提供的getSession方法
    • getSession()
      • 如果还没有创建Session,那么就创建一个Session
      • 如果已经有了Session,那么就返回这个Session
      • 当前这个客户端或用户第一个调用getSession方法的时候创建了Session
    • getSession(boolean create)
      • 如果create的值为true则同上
      • 如果create的值为false,那么如果有了Session则返回Session对象,如果没有则返回null,就不会创建Session

实际上我们使用的无参方法更多一些

eg:

@WebServlet("/session/get")
public class SessionGetServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 根据JSESSIONID,不需要我们手动取获取,内部已经封装好了

        // 获取当前用户地session,如果当前用户没有session,则新建一个session
        // Set-Cookie: JSESSIONID=DA43DEBCD0DFF4BBFC4371558FE8C7B4
        HttpSession session = request.getSession();

        // 如果boolean类型参数为true,和无参的getSession方法是一样的
        // HttpSession session = request.getSession(true);

        // 如果为false,且当前用户有session,则返回,如果没有session,则返回空
        // HttpSession session = request.getSession(false);

    }
}

在这里插入图片描述

使用Session

  • Session其实就像一个保险柜 → key-value形式的保险柜
    • key:String
    • value:Object
    • 存储:setAttribute(String,Object)
    • 获取:getAttribute(String)

eg:

WebServlet("/session/save")
public class SessionSaveServlet extends HttpServlet {
    // localhost:8080/demo2/session/save?username=zs
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 传入一个用户名 -> 找到id,将id存在session里面
        String username = request.getParameter("username"); // 根据用户名可以找到该用户的id信息

        // 假定这个id是222
        Integer id = 222;

        HttpSession session = request.getSession();

        session.setAttribute("id",id);

        session.setAttribute("username", username);
    }
}
@WebServlet("/session/fetch")
public class SessionFetchServlet extends HttpServlet {
    // localhost:8080/demo2/session/fetch
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        // 从session中获取username和id信息
        HttpSession session = request.getSession();

        Integer id = (Integer) session.getAttribute("id");

        String username = (String) session.getAttribute("username");

        System.out.println(username + " : " + id); // zs : 222

    }
}

Session的生命周期

  • 对象生命周期:
    • 对象的创建:request.getSession()
    • 对象的销毁:关闭服务器、卸载应用
  • 数据的生命周期:
    • 数据的产生:session域
    • 数据的销毁:对象的销毁不会导致数据的销毁
      • 数据的销毁只有以下两种可能性:
        1. session有效期到达(默认是30min)
        2. 主动调用session.invalidate()方法-----用在注销的场景下

常见问题

  1. 关闭浏览器,Session是否被销毁?
    • 并没有
    • 只不过当前浏览器发起请求的时候,通常没有继续携带之前的JSESSIONID,但如果你仍然携带之前的JSESSIONID,那么仍然可以获取数据
  2. 服务器关闭,Session发生了什么?
    • Session对象会被销毁,并且会被序列化(序列化:把数据写到服务器里)
    • 当服务器重启时,会被反序列化(反序列化:把数据读出),重新加载到内容。
    • 当时要注意,重启前后的Session对象并不是同一个,但是JSESSIONID是同一个值
  3. Session失效,原因会是什么?
    • Session失效就是从Session中获取不到其存储的信息,则可以认为Session失效
      • 跨域请求Session不能共享
        • 跨域:多个应用之间的ip或端口号不同
          • 比如:前端地址localhost:9527与后端服务器地址localhost:8080
        • 每发起一次请求,就会新建一个新的Session
      • 过期或手动设置
      • 请求携带的JSESSIONID变了
  4. session底层是依赖于cookie的,但是如果浏览器禁用了cookie,那么session还可以使用吗?
    • 还可以。但是必须采用一种URL重写的方式。此时session的编号会附着在地址栏的后面,以;形式来进行分割
    • eg:localhost:8080/demo2/session/fetch;JSESSIONID=aaaabc2849ea

案例(重构登录案例,并且增加注销功能)

  • bean目录
@Data
public class Order {
    private Integer id;
    private String name;
    private Double price;
    private Integer userId;
}
@Data
public class User {
    private Integer id;

    private String username;

    private String password;

    private Integer age;

    private Date birthday;

    private Date createdate;

    private String mobile;

}
  • mapper目录
public interface OrderMapper {
    List<Order> selectByUserId(Integer id);
}
public interface UserMapper {
    List<User> selectByUserNameAndPassword
            (@Param("username") String username, @Param("password") String password);

    User selectByPrimaryKey(Integer id);
}
<mapper namespace="com.coo1heisenberg.demo3.mapper.OrderMapper">

    <select id="selectByUserId" resultType="com.coo1heisenberg.demo3.bean.Order">
        select id, name, price, user_id as userId from test_product
        <where>
            user_id = #{user_id}
        </where>
    </select>
</mapper>
<mapper namespace="com.coo1heisenberg.demo3.mapper.UserMapper">

    <select id="selectByUserNameAndPassword" resultType="com.coo1heisenberg.demo3.bean.User">
        select id, username, password, age, birthday, createDate, mobile from test_user
        <where>
            username = #{username} and password = #{password}
        </where>
    </select>

    <select id="selectByPrimaryKey" resultType="com.coo1heisenberg.demo3.bean.User">
        select id, username, password, age, birthday, createDate, mobile from test_user
        <where>
            id = #{id}
        </where>
    </select>
</mapper>
  • servlet目录
/**
 * 提供一个list方法,登录成功才允许查看当前用户的订单信息,否则让其先登录
 */
@WebServlet("/order/*")
public class OrderServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        process(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        process(request, response);
    }

    private void process(HttpServletRequest request, HttpServletResponse response) {
        String requestURI = request.getRequestURI();
        String operation = requestURI.substring(requestURI.lastIndexOf("/") + 1);

        switch (operation) {
            case "list":
                list(request, response);
                break;
        }
    }

    @SneakyThrows
    private void list(HttpServletRequest request, HttpServletResponse response) {
        // 首先要保证当前用户已经登陆 ->  登录成功之后,session里才有用户信息
        // -> 可以判断session是否有用户信息
        HttpSession session = request.getSession();
        User user = (User) session.getAttribute("user");
        response.setContentType("text/html;charset=utf-8");
        if (user == null) {
            // 登录失败
            response.getWriter().println("登录失败,即将跳转登录页面");
            response.setHeader("refresh", "2;url=/demo3/login.html");
        } else {
            // 已经登录成功
            Integer userId = user.getId();
            OrderMapper orderMapper = MybatisUtil.getSqlSession().getMapper(OrderMapper.class);
            List<Order> orders = orderMapper.selectByUserId(userId);
            response.getWriter().println(orders);
        }
    }
}
@WebServlet("/user/*")
public class UserServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        process(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        process(req, resp);
    }

    private void process(HttpServletRequest request, HttpServletResponse response) {
        String requestURI = request.getRequestURI();
        String operation = null;
        operation = requestURI.substring(requestURI.lastIndexOf("/") + 1);

        switch (operation) {
            case "login":
                login(request, response);
                break;
            case "info":
                info(request, response);
                break;
            case "logout":
                logout(request,response);
                break;
        }
    }

    @SneakyThrows
    private void logout(HttpServletRequest request, HttpServletResponse response) {
        // 做注销功能 localhost:8080/demo3/user/logout
        HttpSession session = request.getSession();
        session.invalidate();
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().println("已经注销");
    }

    @SneakyThrows
    private void info(HttpServletRequest request, HttpServletResponse response) {
        HttpSession session = request.getSession();
        Object user = session.getAttribute("user");
        response.setContentType("text/html;charset=utf-8");
        if(user == null) {
            // 意味着之前未登录成功
            response.getWriter().println("还未登录,不能查看用户信息,请先登录,即将跳转");
            response.setHeader("refresh","2;url=/demo3/login.html");
        } else {
            // user != null
            // 意味着已经登录成功
            response.getWriter().println(user);
        }
    }

    @SneakyThrows
    private void login(HttpServletRequest request, HttpServletResponse response) {
        // 1. 首先获得username和password
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        // 2. 查询user记录
        UserMapper userMapper = MybatisUtil.getSqlSession().getMapper(UserMapper.class);
        List<User> users = userMapper.selectByUserNameAndPassword(username, password);

        // 3. 根据user记录判断登录状态
        response.setContentType("text/html;charset=utf-8");
        // 4. 判断登录状态 user的list是否为空
        if (users == null || users.size() == 0) {
            // 如果登陆失败(list == null || list.size() == 0)
            // 刷新到refresh --> 2;url=/demo2/login.html
            // 响应登录失败信息
            response.getWriter().println("登录失败,即将跳转登录页面");
            response.setHeader("refresh", "2;url=/demo3/login.html");
        } else {
            // 如果登录成功(list.size > 0)
            // 登录成功之后,将用户信息放在服务器Session里
            HttpSession session = request.getSession();
            session.setAttribute("user",users.get(0));
            response.getWriter().println("登录成功,可以访问其他请求");
        }
    }
}

Cookie和Session的区别与联系

  • 联系:Cookie和Session都是为了让服务端获取客户端提供的信息;提供的信息都是键值对形式的;Session技术是在Cookie技术的基础上进行的,都需要对请求头做处理
  • 区别:
    • 信息位置
      • Cookie是客户端技术,信息存储在客户端(浏览器),也意味着前端可以操作
      • Session是服务器技术,信息储存在服务器
    • 敏感性
      • Cookie共享的是常规信息,直接抓包获取的是对应的值
      • Session通常共享的是敏感信息,直接抓包获取的是id
    • 值类型
      • Cookie的值为String字符串
      • Session的值为Object
    • 跨应用
      • Cookie信息可以跨应用共享
      • Session信息局限于当前应用

数据共享

  • Request域:存在转发关系的Servlet之间的数据共享,比如Servlet和JSP数据共享
  • Context域:整个应用之中的数据共享,比如整个应用中的SqlSessionFactory、properties等
  • Session域:同一个用户(客户端)中的数据共享,比如登录之后的用户信息

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1553395.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MD5 计算 (加密辅助类, Win32, C++)

CCryptHelper.h #pragma once #include <string> #include <tchar.h> #include <windows.h>#ifdef _UNICODE using _tstring std::wstring; #else using _tstring std::string; #endif// 加密辅助类 // 客户端: Windows XP 及以上系统可用 // 服务器: Win…

VESTA模拟计算XRD标准卡片

先上Crystallography Open Database网站下载标准CIF卡片&#xff08;以PbI2为例&#xff09; 1.直接进网站搜元素就行 2.点CIF直接下载 3.打开VESTA&#xff0c;导入刚刚下载的CIF 4.导入成功就是这样的 5.按照我这个操作来计算 6.点Calculation 7.已经计算出来了&#xff…

政安晨:专栏目录【TensorFlow与Keras实战演绎机器学习】

政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: TensorFlow与Keras实战演绎机器学习 希望政安晨的博客能够对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff01; 本篇是作者政安晨的专栏《TensorFlow与Keras…

cf937Div4E题F题

题目要找到一个长为k的子串,使得x个相同的k相连长度和s相同且对应字符中只能有一个地方对应的字符不同, 那是不是说明s也能分成x段,且最多有一段中的一个字符不同,否则就不满足要求,那我们现在要讨论这个不同的字符在哪,如果在第一段比如sabaa aaaa aaaa aaaa,如果我们取了abaa…

怎么评价小米汽车SU7?

编辑搜图 请点击输入图片描述&#xff08;最多18字&#xff09; 小米汽车SU7&#xff1a;电动智能驾驶的新篇章 随着全球汽车产业的深度变革&#xff0c;新能源汽车、智能驾驶等概念逐渐深入人心。在这场汽车产业的革新中&#xff0c;小米汽车SU7无疑是一个引人注目的焦点。这…

利用 Scapy 库编写 ARP 缓存中毒攻击脚本

一、ARP 协议基础 参考下篇文章学习 二、ARP 缓存中毒原理 ARP&#xff08;Address Resolution Protocol&#xff09;缓存中毒是一种网络攻击&#xff0c;它利用了ARP协议中的漏洞&#xff0c;通过欺骗或篡改网络中的ARP缓存来实施攻击。ARP协议是用于将IP地址映射到物理MAC…

002-基于Pytorch的手写汉字数字分类

本节将介绍一种 2.1 准备 2.1.1 数据集 &#xff08;1&#xff09;MNIST 只要学习过深度学习相关理论的人&#xff0c;都一定听说过名字叫做LeNet-5模型&#xff0c;它是深度学习三巨头只有Yann Lecun在1998年提出的一个CNN模型&#xff08;很多人认为这是第一个具有实际应用…

npm install 报错ERESOLVE unable to resolve dependency tree

描述&#xff1a;npm install 报错ERESOLVE unable to resolve dependency tree 解决方案&#xff1a; npm install --legacy-peer-deps

【Linux】网络编程套接字二

网络编程套接字二 1.TCP网络编程1.1TCP Server服务端1.2 TCP Client客户端 2.Server 多进程版本2.1普通版2.2 信号版 3.Server 多线程版4.Server 线程池版5.日志函数重新设计6.守护进程7.TCP协议通讯流程8.TCP和UDP 对比 喜欢的点赞&#xff0c;收藏&#xff0c;关注一下把&…

[Java基础揉碎]抽象类

目录 通过问题引出 介绍 关键点 细节 ​编辑 抽象类的最佳设计模式--模版设计模式 1.先用最容易想到的方法 2.分析问题&#xff0c;提出使用模板设计模式 通过问题引出 假如我们有个动物类, 动物都有eat吃的方法, 但是具体吃什么, 我们不知道, 因为是什么动物我们不知道…

绘制特征曲线-ROC(Machine Learning 研习十七)

接收者操作特征曲线&#xff08;ROC&#xff09;是二元分类器的另一个常用工具。它与精确度/召回率曲线非常相似&#xff0c;但 ROC 曲线不是绘制精确度与召回率的关系曲线&#xff0c;而是绘制真阳性率&#xff08;召回率的另一个名称&#xff09;与假阳性率&#xff08;FPR&a…

【爬虫框架pyspider】01-pyspider入门与基本使用

前言 前面我们把爬虫的流程实现一遍&#xff0c;将不同的功能定义成不同的方法&#xff0c;甚至抽象出模块的概念。如微信公众号爬虫&#xff0c;我们已经有了爬虫框架的雏形&#xff0c;如调度器、队列、请求对象等&#xff0c;但是它的架构和模块还是太简单&#xff0c;远远…

|行业洞察·碳纤维|《中国碳纤维行业现状与发展趋势-39页》

报告内容的详细解读&#xff1a; 1. 战略性新材料的重要性 碳纤维是一种轻质高强的高性能纤维材料&#xff0c;在航空航天、国防军工、高端装备制造等领域具有不可替代的作用。碳纤维的应用有助于减少能源消耗和降低碳排放&#xff0c;符合全球可持续发展的要求。 |趋势洞察…

Java增强for循环和foreach循环的误区

网上很多文章都在说增强for循环和foreach循环遍历时不能修改值&#xff0c;只能查看&#xff0c;其实是有区分条件的&#xff0c;不能修改值的是包装类&#xff0c;例如List<String>,引用类型是可以修改值的&#xff0c;例如对象集合。 使用增强for循环或者foreach循环遍…

李宏毅【生成式AI导论 2024】第6讲 大型语言模型修炼_第一阶段_ 自我学习累积实力

背景知识:机器怎么学会做文字接龙 详见:https://blog.csdn.net/qq_26557761/article/details/136986922?spm=1001.2014.3001.5501 在语言模型的修炼中,我们需要训练资料来找出数十亿个未知参数,这个过程叫做训练或学习。找到参数后,我们可以使用函数来进行文字接龙,拿…

解决“Pycharm中Matplotlib图像不弹出独立的显示窗口”问题

matplotlib的绘图的结果默认显示在SciView窗口中, 而不是弹出独立的窗口, 这样看起来就不是很舒服&#xff0c;不习惯。 通过修改设置&#xff0c;改成独立弹出的窗口。 File—>Settings—>Tools—>Python Scientific—>Show plots in toolwindow 将√去掉即可

一台日本原生ip站群服务器多少钱?

一台日本原生ip站群服务器多少钱&#xff1f;日本原生ip站群服务器的价格受到多个因素的影响。以下是一些主要的因素&#xff1a; 服务器配置&#xff1a;硬件配置越高&#xff0c;自然价格也越高。对于站群服务器来说&#xff0c;由于需要同时运行多个网站&#xff0c;因此配置…

Vue挂载全局方法

简介&#xff1a;有时候&#xff0c;频繁调用的函数&#xff0c;我们需要把它挂载在全局的vue原型上&#xff0c;方便调用&#xff0c;具体怎么操作&#xff0c;这里来记录一下。 一、这里以本地存储的方法为例 var localStorage window.localStorage; const db {/** * 更新…

学习JavaEE的日子 Day32 线程池

Day32 线程池 1.引入 一个线程完成一项任务所需时间为&#xff1a; 创建线程时间 - Time1线程中执行任务的时间 - Time2销毁线程时间 - Time3 2.为什么需要线程池(重要) 线程池技术正是关注如何缩短或调整Time1和Time3的时间&#xff0c;从而提高程序的性能。项目中可以把Time…

【tensorflow框架神经网络实现鸢尾花分类】

文章目录 1、数据获取2、数据集构建3、模型的训练验证可视化训练过程 1、数据获取 从sklearn中获取鸢尾花数据&#xff0c;并合并处理 from sklearn.datasets import load_iris import pandas as pdx_data load_iris().data y_data load_iris().targetx_data pd.DataFrame…