Java必修课——Spring框架

Java必修课——Spring框架Spring 是轻量级的开源的 JAVAEE 框架 Spring 可以解决企业应用开发的复杂性 Spring 有两个核心部分 IOC 和 AopIOC 控制反转 把创建对象的过程交个 Spring 进行管理 Aop

大家好,欢迎来到IT知识分享网。

一、Spring框架概述

IOC:控制反转,把创建对象的过程交个Spring进行管理 Aop:面向切面,不修改源代码进行功能增强 

Spring特点

方便解耦,简化开发 Aop编程支持 方便程序测试 方便和其他框架进行整合 方便进行事务操作 降低API的使用难度 

IOC容器

IOC底层原理 IOC接口(BeanFactory) IOC操作Bean管理(基于XML) IOC操作Bean管理(基于注解) 

二、IOC概念和原理

2.1、什么是IOC

控制反转,把对象创建和对象之间调用过程,交给Spring进行管理

使用IOC目的:为了耦合度降低

2.2、IOC接口

  1. IOC思想基于IOC容器完成,IOC容器底层就是对象工厂
  2. Spring提供IOC容器实现两种方式:(两个接口)
    2.1 BeanFactory:
    IOC容器基本实现方式,是spring内部使用接口,不提供开发人员进行使用
    加载配置文件不会创建对象,在获取对象才去创建对象
    2.2 ApplicationContext:
    BeanFactory接口的子接口,提供更多更强大的功能,一般是由开发人员进行使用
    加载配置文件时候就会把配置文件对象进行创建





  3. 使用ApplicationContext把加载过程交给启动服务器,不要留给运行中。
  4. ApplicationContext接口有实现类

在这里插入图片描述
盘路径 类路径

IOC操作Bean管理

  1. 什么是Bean管理
    Spring创建对象
    Spring注入属性

  2. Bean管理操作有两种方式
    基于xml配置文件方式实现
    基于注解方式实现

IOC操作Bean管理(xml)

  1. 在Spring配置文件中,使用bean标签,标签里面添加对应属性,就可以实现对象创建
  2. 在bean标签有很多属性,常用属性:
    id属性:唯一标识
    class属性:类全路径

  3. 创建对象时候,默认是执行无参构造

基于xml方式注入属性

  1. DI:依赖注入,注入属性
    使用set方法注入
    属性:类全路径

  2. 创建对象时候,默认是执行无参构造

三、深入理解Java基础中的集合框架

Java集合框架 (Java Collections Framework, JCF) 也称容器,这里可以类比 C++ 中的 STL,在市面上似乎还没能找到一本详细介绍的书籍。在这里主要对如下部分进行源码分析,及在面试中常见的问题。

例如,在阿里面试常问到的 HashMap 和 ConcurrentHashMap 原理等等。

Java集合框架提供了数据持有对象的方式,提供了对数据集合的操作。Java 集合框架位于java.util包下,主要有三个大类:Collection(接口)、Map(接口)、集合工具类。

3.1、Collection

  • ArrayList:线程不同步。默认初始容量为 10,当数组大小不足时容量扩大为 1.5 倍。为追求效率,ArrayList 没有实现同步(synchronized),如果需要多个线程并发访问,用户可以手动同步,也可使用 Vector 替代。
  • LinkedList:线程不同步。双向链接实现。LinkedList 同时实现了 List 接口和 Deque 接口,也就是说它既可以看作一个顺序容器,又可以看作一个队列(Queue),同时又可以看作一个栈(Stack)。这样看来,LinkedList 简直就是个全能冠军。当你需要使用栈或者队列时,可以考虑使用 LinkedList,一方面是因为 Java 官方已经声明不建议使用 Stack 类,更遗憾的是,Java 里根本没有一个叫做 Queue 的类(它是个接口名字)。关于栈或队列,现在的首选是 ArrayDeque,它有着比 LinkedList(当作栈或队列使用时)有着更好的性能。
  • Stack and Queue:Java 里有一个叫做 Stack 的类,却没有叫做 Queue 的类(它是个接口名字)。当需要使用栈时,Java 已不推荐使用 Stack,而是推荐使用更高效的 ArrayDeque;既然 Queue 只是一个接口,当需要使用队列时也就首选 ArrayDeque 了(次选是 LinkedList )。
  • Vector:线程同步。默认初始容量为 10,当数组大小不足时容量扩大为 2 倍。它的同步是通过Iterator方法加synchronized实现的。
  • Stack:线程同步。继承自 Vector,添加了几个方法来完成栈的功能。现在已经不推荐使用 Stack,在栈和队列中有限使用 ArrayDeque,其次是 LinkedList。
  • TreeSet:线程不同步,内部使用NavigableMap操作。默认元素 “自然顺序” 排列,可以通过Comparator改变排序。TreeSet 里面有一个 TreeMap(适配器模式)
  • HashSet:线程不同步,内部使用 HashMap 进行数据存储,提供的方法基本都是调用 HashMap 的方法,所以两者本质是一样的。集合元素可以为 NULL。
  • Set:Set 是一种不包含重复元素的 Collection,Set 最多只有一个 null 元素。Set 集合通常可以通过 Map 集合通过适配器模式得到。
  • PriorityQueue:Java 中 PriorityQueue 实现了 Queue 接口,不允许放入 null 元素;其通过堆实现,具体说是通过完全二叉树(complete binary tree)实现的小顶堆(任意一个非叶子节点的权值,都不大于其左右子节点的权值),也就意味着可以通过数组来作为 PriorityQueue 的底层实现。
  • 优先队列的作用是能保证每次取出的元素都是队列中权值最小的(Java 的优先队列每次取最小元素,C++ 的优先队列每次取最大元素)。这里牵涉到了大小关系,元素大小的评判可以通过元素本身的自然顺序(natural ordering),也可以通过构造时传入的比较器(Comparator,类似于 C++ 的仿函数)。
  • NavigableSet:添加了搜索功能,可以对给定元素进行搜索:小于、小于等于、大于、大于等于,放回一个符合条件的最接近给定元素的 key。
  • EnumSet:线程不同步。内部使用 Enum 数组实现,速度比HashSet快。只能存储在构造函数传入的枚举类的枚举值。

3.2、Map

  • TreeMap:线程不同步,基于红黑树(Red-Black tree)的 NavigableMap 实现,能够把它保存的记录根据键排序,默认是按键值的升序排序,也可以指定排序的比较器,当用 Iterator 遍历 TreeMap 时,得到的记录是排过序的。
  • TreeMap 底层通过红黑树(Red-Black tree)实现,也就意味着containsKey(),get(),put(),remove()都有着log(n)的时间复杂度。其具体算法实现参照了《算法导论》。
    HashTable:线程安全,HashMap 的迭代器 (Iterator) 是fail-fast迭代器。HashTable 不能存储 NULL 的 key 和 value。
  • HashMap:线程不同步。根据key的hashcode进行存储,内部使用静态内部类Node的数组进行存储,默认初始大小为 16,每次扩大一倍。当发生 Hash 冲突时,采用拉链法(链表)。JDK 1.8中:当单个桶中元素个数大于等于8时,链表实现改为红黑树实现;当元素个数小于6时,变回链表实现。由此来防止hashCode攻击。
Java HashMap 采用的是冲突链表方式。 HashMap 是 Hashtable 的轻量级实现,可以接受为 null 的键值 (key) 和值 (value),而 Hashtable 不允许。 
  • LinkedHashMap:保存了记录的插入顺序,在用 Iterator 遍历 LinkedHashMap 时,先得到的记录肯定是先插入的。也可以在构造时用带参数,按照应用次数排序。在遍历的时候会比 HashMap 慢,不过有种情况例外,当 HashMap 容量很大,实际数据较少时,遍历起来可能会比 LinkedHashMap 慢,因为 LinkedHashMap 的遍历速度只和实际数据有关,和容量无关,而 HashMap 的遍历速度和他的容量有关。
  • WeakHashMap:从名字可以看出它是某种 Map。它的特殊之处在于 WeakHashMap 里的 entry 可能会被 GC 自动删除,即使程序员没有调用remove()或者clear()方法。 WeakHashMap 的存储结构类似于HashMap
既然有 WeekHashMap,是否有 WeekHashSet 呢?答案是没有!不过 Java Collections 工具类给出了解决方案,Collections.newSetFromMap(Map<E,Boolean> map)方法可以将任何 Map包装成一个Set。 

3.3、集合工具类

  • Collections、Arrays:集合类的一个工具类帮助类,其中提供了一系列静态方法,用于对集合中元素进行排序、搜索以及线程安全等各种操作。
  • Comparable、Comparator:一般是用于对象的比较来实现排序,两者略有区别。

在这里插入图片描述
在这里插入图片描述

四、练习写一个SpringMVC框架

1、介绍

熟悉SpringMVC框架的同学一定清楚下面这张图,

在这里插入图片描述

这张图就是 SpringMVC 在处理 http 请求的整个流程中所做的一些事情。

  • 1、用户发送请求至前端控制器DispatcherServlet
  • 2、DispatcherServlet收到请求调用HandlerMapping处理器映射器。
  • 3、处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
  • 4、DispatcherServlet通过HandlerAdapter处理器适配器调用处理器
  • 5、执行处理器(Controller,也叫后端控制器)。
  • 6、Controller执行完成返回ModelAndView
  • 7、HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet
  • 8、DispatcherServlet将ModelAndView传给ViewReslover视图解析器
  • 9、ViewReslover解析后返回具体View
  • 10、DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)。
  • 11、DispatcherServlet响应用户。
    DispatcherServlet 主要承担接收请求、响应结果、转发等作用,剩下的就交给容器来处理!

基于上面的流程,我们可以编写出一款简化版的Spring MVC框架。

2、程序实践

这个就是我们简易版的Spring MVC框架的实现流程图!

1、首先创建一个DispatcherServlet类,在服务启动的时候,读取要扫描的包路径,然后通过反射将类信息存储到ioc容器,同时通过@Autowired注解,实现自动依赖注入,最后读取@RequestMapping注解中的方法,将映射路径与类的关系存储到映射容器中。

2、当用户发起请求的时候,通过请求路径到映射容器中找到对应的执行类,然后调用具体的方法,发起逻辑处理,最后将处理结果返回给前端用户!

以下是具体实践过程!

2.1、创建扫描注解
因为Spring MVC基本全部都是基于注解开发,因此我们事先也需要创建对应的注解,各个含义与Spring MVC一致!

控制层注解

/ * 控制层注解 * @Controller */ @Target({ 
   ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Controller { 
    String value() default ""; } 

请求路径注解

/ * 请求路径注解 * @RequestMapping */ @Target({ 
   ElementType.METHOD,ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface RequestMapping { 
    String value() default ""; } 

参数注解

/ * 参数注解 * @RequestParam */ @Target({ 
   ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface RequestParam { 
    String value() default ""; } 

服务层注解

/ * 服务层注解 * @Controller */ @Target({ 
   ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Service { 
    String value() default ""; } 

自动装载注解

/ * 自动装载注解 * @Autowrited */ @Target({ 
   ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Autowired { 
    String value() default ""; } 

2.2、编写 DispatcherServlet 类
DispatcherServlet是一个Servlet类,主要承担的任务是:接受前端用户的请求,然后进行转发,最后响应结果给前端用户!

详细代码如下:

/ * servlet跳转层 */ @WebServlet(name = "DispatcherServlet",urlPatterns = "/*", loadOnStartup = 1, initParams = { 
   @WebInitParam(name="scanPackage", value="com.example.mvc")}) public class DispatcherServlet extends HttpServlet { 
    private static final long serialVersionUID = 1L; private static final Logger logger = LoggerFactory.getLogger(DispatcherServlet.class); /请求方法映射容器*/ private static List<RequestHandler> handlerMapping = new ArrayList<>(); / * 服务启动的时候,进行初始化,流程如下: * 1、扫描指定包下所有的类 * 2、通过反射将类实例,放入ioc容器 * 3、通过Autowired注解,实现自动依赖注入,也就是set类中的属性 * 4、通过RequestMapping注解,获取需要映射的所有方法,然后将类信息存放到容器中 * @param config * @throws ServletException */ @Override public void init(ServletConfig config) throws ServletException { 
    try { 
    //1、扫描指定包下所有的类 String scanPackage = config.getInitParameter("scanPackage"); //1、扫描指定包下所有的类 List<String> classNames = doScan(scanPackage); //2、初始化所有类实例,放入ioc容器,也就是map对象中 Map<String, Object> iocMap = doInstance(classNames); //3、实现自动依赖注入 doAutowired(iocMap); //5、初始化方法mapping initHandleMapping(iocMap); } catch (Exception e) { 
    logger.error("dispatcher-servlet类初始化失败!",e); throw new ServletException(e.getMessage()); } } / * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { 
    doPost(request, response); } / * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { 
    //跳转 doDispatch(request, response); } / * 扫描指定包下的类文件 * @param packageName * @return */ private List<String> doScan(String packageName){ 
    if(StringUtils.isBlank(packageName)){ 
    throw new RuntimeException("mvc配置文件中指定扫描包名为空!"); } return PackageHelper.getClassName(packageName); } private Map<String, Object> doInstance(List<String> classNames) { 
    Map<String, Object> iocMap = new HashMap<>(); if(!CollectionUtils.isNotEmpty(classNames)){ 
    throw new RuntimeException("获取的类为空!"); } for (String className : classNames) { 
    try { 
    //通过反射机制构造对象 Class<?> clazz = Class.forName(className); if(clazz.isAnnotationPresent(Controller.class)){ 
    //将类名第一个字母小写 String baneName = firstLowerCase(clazz.getSimpleName()); iocMap.put(baneName, clazz.newInstance()); }else if(clazz.isAnnotationPresent(Service.class)){ 
    //服务层注解判断 Service service = clazz.getAnnotation(Service.class); String beanName = service.value(); //如果该注解上没有自定义类名,则默认首字母小写 if(StringUtils.isBlank(beanName)){ 
    beanName = clazz.getName(); } Object instance = clazz.newInstance(); iocMap.put(beanName, instance); //如果注入的是接口,可以巧妙的用接口的类型作为key Class<?>[] interfaces = clazz.getInterfaces(); for (Class<?> clazzInterface : interfaces) { 
    iocMap.put(clazzInterface.getName(), instance); } } } catch (Exception e) { 
    logger.error("初始化mvc-ioc容器失败!",e); throw new RuntimeException("初始化mvc-ioc容器失败!"); } } return iocMap; } / * 实现自动依赖注入 * @throws Exception */ private void doAutowired(Map<String, Object> iocMap) { 
    if(!MapUtils.isNotEmpty(iocMap)){ 
    throw new RuntimeException("初始化实现自动依赖失败,ioc为空!"); } for(Map.Entry<String, Object> entry : iocMap.entrySet()){ 
    //获取对象下所有的属性 Field[] fields = entry.getValue().getClass().getDeclaredFields(); for (Field field : fields) { 
    //判断字段上有没有@Autowried注解,有的话才注入 if(field.isAnnotationPresent(Autowired.class)){ 
    try { 
    Autowired autowired = field.getAnnotation(Autowired.class); //获取注解上有没有自定义值 String beanName = autowired.value().trim(); if(StringUtils.isBlank(beanName)){ 
    beanName = field.getType().getName(); } //如果想要访问到私有的属性,我们要强制授权 field.setAccessible(true); field.set(entry.getValue(), iocMap.get(beanName)); } catch (Exception e) { 
    logger.error("初始化实现自动依赖注入失败!",e); throw new RuntimeException("初始化实现自动依赖注入失败"); } } } } } / * 初始化方法mapping */ private void initHandleMapping(Map<String, Object> iocMap){ 
    if(!MapUtils.isNotEmpty(iocMap)){ 
    throw new RuntimeException("初始化实现自动依赖失败,ioc为空"); } for(Map.Entry<String, Object> entry:iocMap.entrySet()){ 
    Class<?> clazz = entry.getValue().getClass(); //判断是否是controller层 if(!clazz.isAnnotationPresent(Controller.class)){ 
    continue; } String baseUrl = null; //判断类有没有requestMapping注解 if(clazz.isAnnotationPresent(RequestMapping.class)){ 
    RequestMapping requestMapping = clazz.getAnnotation(RequestMapping.class); baseUrl= requestMapping.value(); } Method[] methods = clazz.getMethods(); for (Method method : methods) { 
    //判断方法上有没有requestMapping if(!method.isAnnotationPresent(RequestMapping.class)){ 
    continue; } RequestMapping requestMethodMapping = method.getAnnotation(RequestMapping.class); //"/+",表示将多个"/"转换成"/" String regex = (baseUrl + requestMethodMapping.value()).replaceAll("/+", "/"); Pattern pattern = Pattern.compile(regex); handlerMapping.add(new RequestHandler(pattern, entry.getValue(), method)); } } } / * servlet请求跳转 * @param request * @param response * @throws IOException */ private void doDispatch(HttpServletRequest request, HttpServletResponse response) throws IOException { 
    try { 
    request.setCharacterEncoding("UTF-8"); response.setHeader("Cache-Control", "no-cache"); response.setHeader("Pragma", "no-cache"); response.setDateHeader("Expires", -1); response.setContentType("text/html"); response.setHeader("content-type", "text/html;charset=UTF-8"); response.setCharacterEncoding("UTF-8"); RequestHandler handle = getHandleMapping(request); if(Objects.isNull(handle)){ 
    //异常请求地址 logger.warn("异常请求地址!地址:" + request.getRequestURI()); response.getWriter().append("error request url"); return; } //获取参数列表 Object[] paramValues = RequestParamHelper.buildRequestParam(handle, request, response); Object result = handle.getMethod().invoke(handle.getController(), paramValues); if(result != null){ 
    PrintWriter out = response.getWriter(); out.println(result); out.flush(); out.close(); } } catch (Exception e) { 
    logger.error("接口请求失败!",e); PrintWriter out = response.getWriter(); out.println("请求异常,请稍后再试"); out.flush(); out.close(); } } / * 将类名第一个字母小写 * @param clazzName * @return */ private String firstLowerCase(String clazzName){ 
    char[] chars = clazzName.toCharArray(); chars[0] += 32; return String.valueOf(chars); } / * 获取用户请求方法名 * 与handlerMapping中的路径名进行匹配 * @param request * @return */ private RequestHandler getHandleMapping(HttpServletRequest request){ 
    if(CollectionUtils.isNotEmpty(handlerMapping)){ 
    //获取用户请求路径 String url = request.getRequestURI(); String contextPath = request.getContextPath(); String serviceUrl = url.replace(contextPath, "").replaceAll("/+", "/"); for (RequestHandler handle : handlerMapping) { 
    //正则匹配请求方法名 Matcher matcher = handle.getPattern().matcher(serviceUrl); if(matcher.matches()){ 
    return handle; } } } return null; } } 

这里要重点介绍一下初始化阶段所做的操作!

DispatcherServlet在服务启动阶段,会调用init方法进行服务初始化,此阶段所做的事情主要有以下内容:

  • 1、扫描指定包下所有的类信息,返回的结果主要是包名 + 类名
  • 2、通过反射机制,将类进行实例化,将类实例化对象存储到ioc容器中,其中key是类名(小些驼峰),value是类对象
  • 3、通过Autowired注解找到类对象中的属性,通过小驼峰从ioc容器中寻找对应的属性值,然后进行set操作
  • 4、通过Controller和RequestMapping注解寻找需要暴露的方法,并获取对应的映射路径,最后将映射路径
  • 5、最后,当前端用户发起一个请求时,DispatcherServlet获取到请求路径之后,通过与RequestMapping中的路径进行匹配,找到对应的controller类中的方法,然后通过invoke完成方法调用,将调用结果返回给前端!

2.3、编写 controller 类
当DispatcherServlet编写完成之后,紧接着我们需要编写对应的controller控制类来接受前端用户请求,下面我们以用户登录为例,程序示例如下:

编写一个LoginController控制类,接受前端用户调用

@Controller @RequestMapping("/user") public class LoginController { 
    @Autowired private UserService userService; / * 用户登录 * @param request * @param response * @param userName * @param userPwd * @return */ @RequestMapping("/login") public String login(HttpServletRequest request, HttpServletResponse response, @RequestParam("userName") String userName, @RequestParam("userPwd") String userPwd){ 
    boolean result = userService.login(userName, userPwd); if(result){ 
    return "登录成功!"; } else { 
    return "登录失败!"; } } } 

编写一个UserService服务类,用于判断账户、密码是否正确

public interface UserService { 
    / * 登录 * @param userName * @param userPwd * @return */ boolean login(String userName, String userPwd); } 

最后,将项目打包成war,通过tomcat启动服务!

可以很清晰的看到,服务调用正常!

3、总结

本文主要以Spring MVC框架为背景,手写了一个简易版的Spring MVC框架,虽然功能简陋了一点,但是基本无张俱全,里面讲解了ioc和自动依赖注入的实现过程,还有前端发起一个路径请求,是如何映射到对应的controller类中的方法上!

当然实际的Spring MVC框架的跳转流程比这个复杂很多很多,里面包括各种拦截器、权限安全管理等等。

在这里插入图片描述

五、Java开发者必备10大数据工具和框架

根据外媒的一项调查报告,中软卓越专家列出了Java程序员在过去12个月内一直使用的一些工具或框架,或许会对你有意义。

先来看看大数据的概念。根据维基百科,大数据是庞大或复杂的数据集的广义术语,因此传统的数据处理程序不足以支持如此庞大的体量。

在许多情况下,使用SQL数据库存储/检索数据都是很好的选择。而现如今的很多情况下,它都不再能满足我们的目的,这一切都取决于用例的变化。

现在来讨论一些不同的非SQL存储/处理数据工具,例如,NoSQL数据库,全文搜索引擎,实时流式处理,图形数据库等。

1、MongoDB——最受欢迎的,跨平台的,面向文档的数据库。

MongoDB是一个基于分布式文件存储的数据库,使用C++语言编写。旨在为Web应用提供可扩展的高性能数据存储解决方案。应用性能高低依赖于数据库性能,MongoDB则是非关系数据库中功能最丰富,最像关系数据库的,随着MongDB 3.4版本发布,其应用场景适用能力得到了进一步拓展。

MongoDB的核心优势就是灵活的文档模型、高可用复制集、可扩展分片集群。你可以试着从几大方面了解MongoDB,如实时监控MongoDB工具、内存使用量和页面错误、连接数、数据库操作、复制集等。

2、Elasticsearch ——为云构建的分布式RESTful搜索引擎。

ElasticSearch是基于Lucene的搜索服务器。它提供了分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是比较流行的企业级搜索引擎。

ElasticSearch不仅是一个全文本搜索引擎,还是一个分布式实时文档存储,其中每个field均是被索引的数据且可被搜索;也是一个带实时分析功能的分布式搜索引擎,并且能够扩展至数以百计的服务器存储及处理PB级的数据。ElasticSearch在底层利用Lucene完成其索引功能,因此其许多基本概念源于Lucene。

3、Cassandra——开源分布式数据库管理系统。

最初是由Facebook开发的,旨在处理许多商品服务器上的大量数据,提供高可用性,没有单点故障。

Apache Cassandra是一套开源分布式NoSQL数据库系统。集Google BigTable的数据模型与Amazon Dynamo的完全分布式架构于一身。于2008开源,此后,由于Cassandra良好的可扩展性,被Digg、Twitter等Web 2.0网站所采纳,成为了一种流行的分布式结构化数据存储方案。

因Cassandra是用Java编写的,所以理论上在具有JDK6及以上版本的机器中都可以运行,官方测试的JDK还有OpenJDK 及Sun的JDK。 Cassandra的操作命令,类似于我们平时操作的关系数据库,对于熟悉MySQL的朋友来说,操作会很容易上手。

4、Redis ——开源(BSD许可)内存数据结构存储,用作数据库,缓存和消息代理。

Redis是一个开源的使用ANSI C语言编写的、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。Redis 有三个主要使其有别于其它很多竞争对手的特点:Redis是完全在内存中保存数据的数据库,使用磁盘只是为了持久性目的; Redis相比许多键值数据存储系统有相对丰富的数据类型; Redis可以将数据复制到任意数

5、Hazelcast ——基于Java的开源内存数据网格。

Hazelcast 是一种内存数据网格 in-memory data grid,提供Java程序员关键任务交易和万亿级内存应用。虽然Hazelcast没有所谓的“Master”,但是仍然有一个Leader节点(the oldest member),这个概念与ZooKeeper中的Leader类似,但是实现原理却完全不同。同时,Hazelcast中的数据是分布式的,每一个member持有部分数据和相应的backup数据,这点也与ZooKeeper不同。

Hazelcast的应用便捷性深受开发者喜欢,但如果要投入使用,还需要慎重考虑。

6、Ehcache——广泛使用的开源Java分布式缓存。

主要面向通用缓存、Java EE和轻量级容器。

EhCache 是一个纯Java的进程内缓存框架,具有快速、精干等特点,是hibernate中默认的CacheProvider。主要特性有:快速简单,具有多种缓存策略;缓存数据有两级,内存和磁盘,因此无需担心容量问题;缓存数据会在虚拟机重启的过程中写入磁盘;可以通过RMI、可插入API等方式进行分布式缓存;具有缓存和缓存管理器的侦听接口;支持多缓存管理器实例,以及一个实例的多个缓存区域;提供Hibernate的缓存实现。

7、Hadoop ——用Java编写的开源软件框架。

用于分布式存储,并对非常大的数据用户可以在不了解分布式底层细节的情况下,开发分布式程序。充分利用集群进行高速运算和存储。Hadoop实现了一个分布式文件系统(Hadoop Distributed File System),简称HDFS。Hadoop的框架最核心的设计就是:HDFS和MapReduce。HDFS为海量的数据提供了存储,MapReduce则为海量的数据提供了计算。

8、Solr ——开源企业搜索平台,用Java编写,来自Apache Lucene项目。

Solr是一个独立的企业级搜索应用服务器,它对外提供类似于Web-service的API接口。用户可以通过http请求,向搜索引擎服务器提交一定格式的XML文件,生成索引;也可以通过Http Get操作提出查找请求,并得到XML格式的返回结果。

与ElasticSearch一样,同样是基于Lucene,但它对其进行了扩展,提供了比Lucene更为丰富的查询语言,同时实现了可配置、可扩展并对查询性能进行了优化。

9、Spark ——Apache Software Foundation中最活跃的项目,是一个开源集群计算框架。

Spark 是一种与 Hadoop 相似的开源集群计算环境,但是两者之间还存在一些不同之处,这些不同之处使 Spark 在某些工作负载方面表现得更加优越,换句话说,Spark 启用了内存分布数据集,除了能够提供交互式查询外,它还可以优化迭代工作负载。

Spark 是在 Scala 语言中实现的,它将 Scala 用作其应用程序框架。与 Hadoop 不同,Spark 和 Scala 能够紧密集成,其中的 Scala 可以像操作本地集合对象一样轻松地

10、Memcached ——通用分布式内存缓存系统。

Memcached是一套分布式快取系统,当初是Danga Interactive为了LiveJournal所发展的,但被许多软件(如MediaWiki)所使用。Memcached作为高速运行的分布式缓存服务器,具有以下的特点:协议简单,基于libevent的事件处理,内置内存存储方式。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/117538.html

(0)
上一篇 2025-11-20 11:10
下一篇 2025-11-20 11:20

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信