java日期时间工具类

工具类继承了OutPut类,这个类只是提供了一个out()的静态方法,用于测试。

package system.utils;

import system.lib.OutPut;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.TextStyle;
import java.time.temporal.*;
import java.util.Date;
import java.util.Locale;

/**
 * Created by alan on 2019/4/19.
 *
 * ********************************
 * getTime():1555776871585
 * getTimeInt():1555776871
 * getLocalDate():2019-04-21
 * parseLocalDate("2019-04-20",1):2019-04-20
 * parseLocalDate(2019,04,20):2019-04-20
 * plus(getLocalDate(),2,ChronoUnit.DAYS):2019-04-23
 * --------------------------------
 * getLocalTime():00:14:31.585
 * parseLocalTime("23:56:00"):23:56
 * parseLocalTime(23,56,12):23:56:12
 * plus(getLocalTime(),-3,ChronoUnit.HOURS):21:14:31.585
 * --------------------------------
 * getLocalDateTime():2019-04-21T00:14:31.585
 * parseLocalDateTime("2019-04-20 21:05:56",1):2019-04-20T21:05:56
 * parseLocalDateTime(2019,4,20,21,05,56):2019-04-20T21:05:56
 * plus(getLocalDateTime(),-1,ChronoUnit.MONTHS):2019-03-21T00:14:31.585
 * --------------------------------
 * format(int t):2019-04-21T00:14:31
 * format(long t):2019-04-21T00:14:31.585
 * format(int t,1):2019-4-21 0:14:31
 * format(long t,1):2019-4-21 0:14:31
 * format(LocalDate d,1):2019-4-21
 * format(LocalTime t):0:14:31
 * format(LocalDateTime t,1):2019-4-21 0:14:31
 * format(ZonedDateTime.now(),1):2019-4-21 0:14:31
 * format(LocalDate d,DateTimeFormatter.ISO_DATE):2019-04-21
 * format(LocalTime t,DateTimeFormatter.ISO_TIME):00:14:31.585
 * format(LocalDateTime t,DateTimeFormatter.ISO_DATE_TIME):2019-04-21T00:14:31.585
 * format(ZonedDateTime t,DateTimeFormatter.ISO_DATE_TIME):2019-04-21T00:14:31.585+08:00[Asia/Shanghai]
 * format(LocalDateTime t,DATE_TIME_FULL):2019-04-21 00:14:31
 * format(int i,DATE_TIME_FULL):2019-04-21 00:14:31
 * format(long l,DATE_TIME_FULL):2019-04-21 00:14:31
 * --------------------------------
 * getYear():2019
 * getMonthI():4
 * getMonth():APRIL
 * getMonthS():四月
 * getDayOfMonth():21
 * getDayOfYear():111
 * getDayOfMonthMax():30
 * getWeek():星期日
 * getWeekI():7
 * getDate():Sun Apr 21 00:14:31 CST 2019
 * getTimestamp():2019-04-21 00:14:31.587
 * getTimestampL():2019-04-21 00:14:31.587
 * getHour():0
 * getMinute():14
 * getSecond():31
 */
public class DateTimeUtils extends OutPut {

    public static final String YEAR = "yyyy";
    public static final String MONTH = "MM";
    public static final String DAY = "dd";
    public static final String DATE_FULL = "yyyy-MM-dd";
    public static final String DATE_FULL2 = "yyyyMMdd";
    public static final String DATE_TIME_FULL = "yyyy-MM-dd HH:mm:ss";
    public static final String DATE_TIME_FULL2 = "yyyyMMddHHmmss";
    public static final String WEEK = "EEEE";

    private static final int ZONE_HOUR = 8;

    public DateTimeUtils() {

    }

    /**
     * 取时间戳
     *
     * @return long
     */
    public static long getTime() {
        return System.currentTimeMillis();
    }

    /**
     * 取时间戳
     *
     * @return int
     */
    public static int getTimeInt() {
        return (int) (getTime() / 1000);
    }

    /**
     * 取本地日期对象
     *
     * @return LocalDate
     */
    public static LocalDate getLocalDate() {
        return LocalDate.now();
    }

    /**
     * 字符串日期转本地日期对象
     *
     * @param str    2012/01/01|2012-01-01
     * @param format 1|2
     * @return LocalDate
     */
    public static LocalDate parseLocalDate(String str, int format) {
        /**
         * format:1=-,2=/
         */
        String regx = "/";
        if (1 == format) {
            regx = "-";
        }
        String[] s = str.split(regx);
        return parseLocalDate(Integer.valueOf(s[0]), Integer.valueOf(s[1]), Integer.valueOf(s[2]));
    }

    /**
     * 整数日期转本地日期对象
     *
     * @param y 年
     * @param m 月
     * @param d 日
     * @return LocalDate
     */
    public static LocalDate parseLocalDate(int y, int m, int d) {
        return LocalDate.of(y, m, d);
    }

    /**
     * 本地日期增减
     *
     * @param date 本地日期
     * @param n    +正数则增加;-负数则减去
     * @param unit ChronoUnit.DAYS|ChronoUnit.YEARS|ChronoUnit.MONTHS
     * @return LocalDate
     */
    public static LocalDate plus(LocalDate date, int n, ChronoUnit unit) {
        return date.plus(n, unit);
    }

    /**
     * 取本地时间对象
     *
     * @return LocalTime
     */
    public static LocalTime getLocalTime() {
        return LocalTime.now();
    }

    /**
     * 本地时间增减
     *
     * @param time 本地时间
     * @param n    +正数则增加;-负数则减去
     * @param unit ChronoUnit.HOURS|ChronoUnit.MINUTES|ChronoUnit.SECONDS
     * @return LocalTime
     */
    public static LocalTime plus(LocalTime time, int n, ChronoUnit unit) {
        return time.plus(n, unit);
    }

    /**
     * 字符串时间转本地时间对象
     *
     * @param time 00:00:00
     * @return LocalTime
     */
    public static LocalTime parseLocalTime(String time) {
        String[] s = time.split(":");
        return parseLocalTime(Integer.valueOf(s[0]), Integer.valueOf(s[1]), Integer.valueOf(s[2]));
    }

    /**
     * 整数时间转本地时间对象
     *
     * @param h 小时
     * @param m 分钟
     * @param s 秒
     * @return LocalTime
     */
    public static LocalTime parseLocalTime(int h, int m, int s) {
        return LocalTime.of(h, m, s);
    }

    /**
     * 获取本地日期时间对象
     *
     * @return
     */
    public static LocalDateTime getLocalDateTime() {
        return LocalDateTime.now();
    }

    /**
     * 本地日期时间增减
     *
     * @param time 本地日期时间
     * @param n    +正数则增加;-负数则减去
     * @param unit ChronoUnit.DAYS|ChronoUnit.YEARS|ChronoUnit.MONTHS|ChronoUnit.HOURS|ChronoUnit.MINUTES|ChronoUnit.SECONDS
     * @return LocalDateTime
     */
    public static LocalDateTime plus(LocalDateTime time, int n, ChronoUnit unit) {
        return time.plus(n, unit);
    }

    /**
     * 本地日期增减
     *
     * @param time 本地时间
     * @param n    +正数则增加;-负数则减去
     * @param unit ChronoUnit.DAYS|ChronoUnit.YEARS|ChronoUnit.MONTHS
     * @return LocalDate
     */
    public static LocalDate plusDate(LocalDate time, int n, ChronoUnit unit) {
        return time.plus(n, unit);
    }

    /**
     * 本地时间增减
     *
     * @param time 本地时间
     * @param n    +正数则增加;-负数则减去
     * @param unit ChronoUnit.HOURS|ChronoUnit.MINUTES|ChronoUnit.SECONDS
     * @return LocalTime
     */
    public static LocalTime plusTime(LocalTime time, int n, ChronoUnit unit) {
        return time.plus(n, unit);
    }

    /**
     * 字符串日期时间转本地日期时间对象
     *
     * @param datetime string like it:2019-01-01 00:00:00 other is 2019/01/01 00:00:00
     * @param format   if == 1 then 2019-01-01 00:00:00 other is 2019/01/01 00:00:00
     * @return null|LocalDateTime
     */
    public static LocalDateTime parseLocalDateTime(String datetime, int format) {
        String[] x = datetime.split(" ");
        if (x.length != 2) {
            return null;
        }
        String regx = "/";
        if (1 == format) {
            regx = "-";
        }
        String[] d = x[0].split(regx);
        String[] s = x[1].split(":");
        return parseLocalDateTime(Integer.valueOf(d[0]), Integer.valueOf(d[1]), Integer.valueOf(d[2]),
                Integer.valueOf(s[0]), Integer.valueOf(s[1]), Integer.valueOf(s[2]));
    }

    /**
     * 整数日期时间转本地日期时间对象
     *
     * @param y 年
     * @param m 月
     * @param d 日
     * @param h 小时
     * @param i 分钟
     * @param s 秒
     * @return LocalDateTime
     */
    public static LocalDateTime parseLocalDateTime(int y, int m, int d, int h, int i, int s) {
        return LocalDateTime.of(y, m, d, h, i, s);
    }

    /**
     * 格式化当前时间
     * @return
     */
    public static String format() {
        return format(getTime(),1);
    }

    /**
     * 秒时间戳转本地日期时间对象
     *
     * @param datetime 秒时间戳
     * @return LocalDateTime
     */
    public static LocalDateTime format(int datetime) {
        return format((long) datetime * 1000L);
    }

    /**
     * 微秒时间戳转本地日期时间对象
     *
     * @param datetime 微秒时间戳
     * @return LocalDateTime
     */
    public static LocalDateTime format(long datetime) {
        LocalDateTime localDateTime = Instant.ofEpochMilli(datetime).atZone(ZoneOffset.systemDefault()).toLocalDateTime();
        return localDateTime;
    }

    /**
     * 秒时间戳格式化字符串文本
     *
     * @param datetime 秒时间戳
     * @param format   格式化字符串
     * @return String
     */
    public static String format(int datetime, int format) {
        return format((long) datetime * 1000L, format);
    }

    /**
     * 微秒时间戳格式化字符串文本
     *
     * @param datetime 微秒时间戳
     * @param format   格式化字符串
     * @return String
     */
    public static String format(long datetime, int format) {
        return format(format(datetime), format);
    }

    /**
     * 本地日期对象格式化文本
     *
     * @param date   本地日期对象
     * @param format 1~2
     * @return String
     */
    public static String format(LocalDate date, int format) {
        String regx = "/";
        if (1 == format) {
            regx = "-";
        }
        StringBuffer st = new StringBuffer();
        st.append(date.getYear()).append(regx)
                .append(date.getMonthValue()).append(regx)
                .append(date.getDayOfMonth());
        return st.toString();
    }


    /**
     * 本地时间对象格式化文本
     *
     * @param time 本地时间对象
     * @return String
     */
    public static String format(LocalTime time) {
        StringBuffer st = new StringBuffer();
        st.append(time.getHour()).append(":")
                .append(time.getMinute()).append(":")
                .append(time.getSecond());
        return st.toString();
    }

    /**
     * 本地日期时间对象格式化文本
     *
     * @param dateTime 本地日期时间对象
     * @param format   1~2
     * @return String
     */
    public static String format(LocalDateTime dateTime, int format) {
        String regx = "/";
        if (1 == format) {
            regx = "-";
        }
        StringBuffer st = new StringBuffer();
        st.append(dateTime.getYear()).append(regx)
                .append(dateTime.getMonthValue()).append(regx)
                .append(dateTime.getDayOfMonth()).append(" ")
                .append(dateTime.getHour()).append(":")
                .append(dateTime.getMinute()).append(":")
                .append(dateTime.getSecond());
        return st.toString();
    }

    /**
     * 时区时间格式化文本
     *
     * @param dateTime 时区时间对象
     * @param format 1~2
     * @return String
     */
    public static String format(ZonedDateTime dateTime, int format) {
        String regx = "/";
        if (1 == format) {
            regx = "-";
        }
        StringBuffer st = new StringBuffer();
        st.append(dateTime.getYear()).append(regx)
                .append(dateTime.getMonthValue()).append(regx)
                .append(dateTime.getDayOfMonth()).append(" ")
                .append(dateTime.getHour()).append(":")
                .append(dateTime.getMinute()).append(":")
                .append(dateTime.getSecond());
        return st.toString();
    }

    /**
     * 格式化本地日期
     * @param date 本地日期对象
     * @param format 日期时间格式化对象:DateTimeFormatter.ISO_DATE
     * @return String
     */
    public static String format(LocalDate date, DateTimeFormatter format) {
        return format.format(date);
    }

    /**
     * 格式化本地时间
     * @param time 本地时间对象
     * @param format 日期时间格式化对象:DateTimeFormatter.ISO_TIME
     * @return String
     */
    public static String format(LocalTime time, DateTimeFormatter format) {
        return format.format(time);
    }

    /**
     * 格式化本地日期时间
     * @param dateTime 本地日期时间对象
     * @param format 日期时间格式化对象:DateTimeFormatter.ISO_LOCAL_DATE_TIME|ISO_DATE_TIME
     * @return String
     */
    public static String format(LocalDateTime dateTime, DateTimeFormatter format) {
        return format.format(dateTime);
    }

    /**
     * 格式化时区日期时间
     * @param dateTime 时区日期时间对象
     * @param format 日期格式化对象:DateTimeFormatter.ISO_ZONED_DATE_TIME|ISO_DATE_TIME
     * @return String
     */
    public static String format(ZonedDateTime dateTime, DateTimeFormatter format) {
        return format.format(dateTime);
    }

    /**
     * 取Date对象
     * @return Date
     */
    public static Date getDate() {
        return Date.from(Instant.now());
    }

    /**
     * 取Timestamp对象
     * @return Timestamp
     */
    public static Timestamp getTimestamp() {
        return Timestamp.from(Instant.now());
    }

    /**
     * 取Timestamp对象
     * @return Timestamp
     */
    public static Timestamp getTimestampL() {
        return Timestamp.valueOf(getLocalDateTime());
    }

    /**
     * 获取星期
     *
     * @return like 星期六|?
     */
    public static String getWeek() {
        return getLocalDate().getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.getDefault());
    }

    /**
     * 获取星期
     *
     * @return like 1~7
     */
    public static int getWeekI() {
        return getLocalDate().getDayOfWeek().getValue();
    }

    /**
     * 获取当天日(按月)
     * @return int
     */
    public static int getDayOfMonth() {
        return getLocalDate().getDayOfMonth();
    }

    /**
     * 获取当天日(按年)
     * @return int
     */
    public static int getDayOfYear() {
        return getLocalDate().getDayOfYear();
    }

    /**
     * 获取当月最后一天
     * @return int
     */
    public static int getDayOfMonthMax() {
        return getMonth().maxLength();
    }

    /**
     * 获取Month对象
     * @return Month
     */
    public static Month getMonth() {
        return getLocalDate().getMonth();
    }

    /**
     * 获取月份(当地格式)
     * @return String|六月
     */
    public static String getMonthS() {
        return getMonth().getDisplayName(TextStyle.FULL, Locale.getDefault());
    }

    /**
     * 获取月份
     * @return int
     */
    public static int getMonthI() {
        return getMonth().getValue();
    }

    /**
     * 取年份
     * @return int|2019
     */
    public static int getYear() {
        return getLocalDate().getYear();
    }

    /**
     * 取小时
     * @return int|0~23
     */
    public static int getHour() {
        return getLocalTime().getHour();
    }

    /**
     * 取分钟
     * @return int|0~59
     */
    public static int getMinute() {
        return getLocalTime().getMinute();
    }

    /**
     * 取秒
     * @return int|0~59
     */
    public static int getSecond() {
        return getLocalTime().getSecond();
    }

    /**
     * 格式化本地日期时间对象
     * @param dateTime 本地日期时间对象
     * @param pattern  public static final String YEAR = "yyyy";
     *                 public static final String MONTH = "MM";
     *                 public static final String DAY = "dd";
     *                 public static final String FULL_DATE = "yyyy-MM-dd";
     *                 public static final String FULL_DATE_Q = "yyyyMMdd";
     *                 public static final String FULL_DATE_TIME = "yyyy-MM-dd HH:mm:ss";
     *                 public static final String FULL_DATE_TIME_Q = "yyyyMMddHHmmss";
     *                 public static final String WEEK = "EEEE";
     * @return String
     */
    public static String format(LocalDateTime dateTime, String pattern) {
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        return sdf.format(Date.from(dateTime.atZone(ZoneOffset.systemDefault()).toInstant()));
    }

    /**
     * 格式化日期时间(整数)
     * @param dateTime 时间戳
     * @param pattern 格式化文本
     * @return String
     */
    public static String format(int dateTime, String pattern) {
        return format((long) dateTime * 1000L, pattern);
    }

    /**
     * 格式化日期时间(长整数)
     * @param dateTime 微秒时间戳
     * @param pattern 格式化文本
     * @return String
     */
    public static String format(long dateTime, String pattern) {
        return format(format(dateTime), pattern);
    }

    public static void main(String[] args) {
        out("********************************");
        out("getTime():"+getTime());
        out("getTimeInt():"+getTimeInt());
        out("getLocalDate():"+getLocalDate());
        out("parseLocalDate(\"2019-04-20\",1):"+parseLocalDate("2019-04-20",1));
        out("parseLocalDate(2019,04,20):"+parseLocalDate(2019,04,20));
        out("plus(getLocalDate(),2,ChronoUnit.DAYS):"+plus(getLocalDate(),2,ChronoUnit.DAYS));
        out("--------------------------------");
        out("getLocalTime():"+getLocalTime());
        out("parseLocalTime(\"23:56:00\"):"+parseLocalTime("23:56:00"));
        out("parseLocalTime(23,56,12):"+parseLocalTime(23,56,12));
        out("plus(getLocalTime(),-3,ChronoUnit.HOURS):"+plus(getLocalTime(),-3,ChronoUnit.HOURS));
        out("--------------------------------");
        out("getLocalDateTime():"+getLocalDateTime());
        out("parseLocalDateTime(\"2019-04-20 21:05:56\",1):"+parseLocalDateTime("2019-04-20 21:05:56",1));
        out("parseLocalDateTime(2019,4,20,21,05,56):"+parseLocalDateTime(2019,4,20,21,05,56));
        out("plus(getLocalDateTime(),-1,ChronoUnit.MONTHS):"+plus(getLocalDateTime(),-1,ChronoUnit.MONTHS));
        out("--------------------------------");
        out("format(int t):"+format(getTimeInt()));
        out("format(long t):"+format(getTime()));
        out("format(int t,1):"+format(getTimeInt(),1));
        out("format(long t,1):"+format(getTime(),1));
        out("format(LocalDate d,1):"+format(getLocalDate(),1));
        out("format(LocalTime t):"+format(getLocalTime()));
        out("format(LocalDateTime t,1):"+format(getLocalDateTime(),1));
        out("format(ZonedDateTime.now(),1):"+format(ZonedDateTime.now(),1));
        out("format(LocalDate d,DateTimeFormatter.ISO_DATE):"+format(getLocalDate(),DateTimeFormatter.ISO_DATE));
        out("format(LocalTime t,DateTimeFormatter.ISO_TIME):"+format(getLocalTime(),DateTimeFormatter.ISO_TIME));
        out("format(LocalDateTime t,DateTimeFormatter.ISO_DATE_TIME):"+format(getLocalDateTime(),DateTimeFormatter.ISO_DATE_TIME));
        out("format(ZonedDateTime t,DateTimeFormatter.ISO_DATE_TIME):"+format(ZonedDateTime.now(),DateTimeFormatter.ISO_DATE_TIME));
        out("format(LocalDateTime t,DATE_TIME_FULL):"+format(getLocalDateTime(),DATE_TIME_FULL));
        out("format(int i,DATE_TIME_FULL):"+format(getTimeInt(),DATE_TIME_FULL));
        out("format(long l,DATE_TIME_FULL):"+format(getTime(),DATE_TIME_FULL));
        out("--------------------------------");
        out("getYear():"+getYear());
        out("getMonthI():"+getMonthI());
        out("getMonth():"+getMonth());
        out("getMonthS():"+getMonthS());
        out("getDayOfMonth():"+getDayOfMonth());
        out("getDayOfYear():"+getDayOfYear());
        out("getDayOfMonthMax():"+getDayOfMonthMax());
        out("getWeek():"+getWeek());
        out("getWeekI():"+getWeekI());
        out("getDate():"+getDate());
        out("getTimestamp():"+getTimestamp());
        out("getTimestampL():"+getTimestampL());
        out("getHour():"+getHour());
        out("getMinute():"+getMinute());
        out("getSecond():"+getSecond());


    }
}

Java集合类(Set、List、Map)及排序

Java集合类如下图:

  • set是一个数据集合
  • List属于数组列表
  • Map也属于一个数据集合

866452-20170226172935866-1277792347

网上找了个图,方便理解。

  • List , Set, Map都是接口,前两个继承至Collection接口,Map为独立接口
  • Set下有HashSet,LinkedHashSet,TreeSet
  • List下有ArrayList,Vector,LinkedList
  • Map下有Hashtable,LinkedHashMap,HashMap,TreeMap
  • Collection接口下还有个Queue接口,有PriorityQueue类

1.Set对象

Set是最简单的一种集合。集合中的对象不按特定的方式排序,并且没有重复对象。

Modifier and Type Method and Description
boolean add(E e)

Adds the specified element to this set if it is not already present (optional operation).
boolean addAll(Collection<? extends E> c)

Adds all of the elements in the specified collection to this set if they’re not already present (optional operation).
void clear()

Removes all of the elements from this set (optional operation).
boolean contains(Object o)

Returns true if this set contains the specified element.
boolean containsAll(Collection<?> c)

Returns true if this set contains all of the elements of the specified collection.
boolean equals(Object o)

Compares the specified object with this set for equality.
int hashCode()

Returns the hash code value for this set.
boolean isEmpty()

Returns true if this set contains no elements.
Iterator<E> iterator()

Returns an iterator over the elements in this set.
boolean remove(Object o)

Removes the specified element from this set if it is present (optional operation).
boolean removeAll(Collection<?> c)

Removes from this set all of its elements that are contained in the specified collection (optional operation).
boolean retainAll(Collection<?> c)

Retains only the elements in this set that are contained in the specified collection (optional operation).
int size()

Returns the number of elements in this set (its cardinality).
default Spliterator<E> spliterator()

Creates a Spliterator over the elements in this set.
Object[] toArray()

Returns an array containing all of the elements in this set.
<T> T[] toArray(T[] a)

Returns an array containing all of the elements in this set; the runtime type of the returned array is that of the specified array.

 

HashSet

HashSet底层用的是哈希表,它把对象根据其哈希值存放到对应的区域里。由于这种特性,两个在不同区域的对象会被认为不相同的。
所以如果对象要存放到Hash集合里面,则需要重写对象的hashCode方法,让相等的对象的hashCode的值也相等。

TreeSet

TreeSet采用的数据结构是红黑树,我们可以让它按指定规则对其中的元素进行排序。它又是如何判断两个元素是否相同呢?除了用equals方法检查两个元素是否相同外,还要检查compareTo方法是否返回为0。

所以如果对象要存放到Tree集合里,需要在重写compareTo方法,把相同的对象的比较值定为0,防止相同的元素被重复添加进集合中。

LinkedHashSet

底层数据结构是链表和哈希表。(FIFO插入有序,唯一)

  • 由链表保证元素有序
  • 由哈希表保证元素唯一

set的测试:

Set<String> data = new TreeSet<>();
data.add("re");
data.add("idn");
data.add("mob");
data.add("ref");
data.add("01");
out(data);

Set<Integer> integers = new TreeSet<>();
integers.add(12);
integers.add(1);
integers.add(15);
integers.add(5);
integers.add(65);

out(integers);

 

打印结果如下:

[01, idn, mob, re, ref]
[1, 5, 12, 15, 65]

2.List对象

List 接口继承了 Collection 接口以定义一个允许重复项的有序集合。该接口不但能够对列表的一部分进行处理,还添加了面向位置的操作。

有序的 collection(也称为序列)。此接口的用户可以对列表中每个元素的插入位置进行精确地控制。用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。

Modifier and Type Method and Description
boolean add(E e)

Appends the specified element to the end of this list (optional operation).
void add(int index, E element)

Inserts the specified element at the specified position in this list (optional operation).
boolean addAll(Collection<? extends E> c)

Appends all of the elements in the specified collection to the end of this list, in the order that they are returned by the specified collection’s iterator (optional operation).
boolean addAll(int index, Collection<? extends E> c)

Inserts all of the elements in the specified collection into this list at the specified position (optional operation).
void clear()

Removes all of the elements from this list (optional operation).
boolean contains(Object o)

Returns true if this list contains the specified element.
boolean containsAll(Collection<?> c)

Returns true if this list contains all of the elements of the specified collection.
boolean equals(Object o)

Compares the specified object with this list for equality.
E get(int index)

Returns the element at the specified position in this list.
int hashCode()

Returns the hash code value for this list.
int indexOf(Object o)

Returns the index of the first occurrence of the specified element in this list, or -1 if this list does not contain the element.
boolean isEmpty()

Returns true if this list contains no elements.
Iterator<E> iterator()

Returns an iterator over the elements in this list in proper sequence.
int lastIndexOf(Object o)

Returns the index of the last occurrence of the specified element in this list, or -1 if this list does not contain the element.
ListIterator<E> listIterator()

Returns a list iterator over the elements in this list (in proper sequence).
ListIterator<E> listIterator(int index)

Returns a list iterator over the elements in this list (in proper sequence), starting at the specified position in the list.
E remove(int index)

Removes the element at the specified position in this list (optional operation).
boolean remove(Object o)

Removes the first occurrence of the specified element from this list, if it is present (optional operation).
boolean removeAll(Collection<?> c)

Removes from this list all of its elements that are contained in the specified collection (optional operation).
default void replaceAll(UnaryOperator<E> operator)

Replaces each element of this list with the result of applying the operator to that element.
boolean retainAll(Collection<?> c)

Retains only the elements in this list that are contained in the specified collection (optional operation).
E set(int index, E element)

Replaces the element at the specified position in this list with the specified element (optional operation).
int size()

Returns the number of elements in this list.
default void sort(Comparator<? super E> c)

Sorts this list according to the order induced by the specified Comparator.
default Spliterator<E> spliterator()

Creates a Spliterator over the elements in this list.
List<E> subList(int fromIndex, int toIndex)

Returns a view of the portion of this list between the specified fromIndex, inclusive, and toIndex, exclusive.
Object[] toArray()

Returns an array containing all of the elements in this list in proper sequence (from first to last element).
<T> T[] toArray(T[] a)

Returns an array containing all of the elements in this list in proper sequence (from first to last element); the runtime type of the returned array is that of the specified array.

ArrayList

  • 优点: 底层数据结构是数组,查询快,增删慢。
  • 缺点: 线程不安全,效率高

Vector

  • 优点: 底层数据结构是数组,查询快,增删慢。
  • 缺点: 线程安全,效率低

LinkedList

  • 优点: 底层数据结构是链表,查询慢,增删快。
  • 缺点: 线程不安全,效率高

PS:ArrayList是实现了基于底层的数据结构,LinkedList基于底层数据结构是链表;对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList遍历全部再确定;对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。

Collection是集合接口

|————Set子接口:无序,不允许重复。
|————List子接口:有序,可以有重复元素。

区别:Collections是集合类

Set和List对比:

  • Set:检索元素效率低下,删除和插入效率高,插入和删除不会引起元素位置改变。
  • List:和数组类似,List可以动态增长,查找元素效率高,插入删除元素效率低,因为会引起其他元素位置改变。

 

List的排序示例:

List<Integer> list = new ArrayList<>();
list.add(12);
list.add(1);
list.add(15);
list.add(5);
list.add(65);
list.sort((a,b)->{
    return a-b;
});
out(list);

打印结果:
[1, 5, 12, 15, 65]

如果降序,只需要把a-b改成b-a即可。

 

3.Map对象

Map 是一种把键对象和值对象映射的集合,它的每一个元素都包含一对键对象和值对象。 Map没有继承于Collection接口 从Map集合中检索元素时,只要给出键对象,就会返回对应的值对象。

map主要的特性:

  • key字段不可重复
  • key,value 都可以是任何引用类型的数据,包括 null
  • Map 取代了古老的 Dictionary 抽象类

因此,每个 key 只能对应一个 value, 多个 key 可以对应一个 value。Map集合维护“键、值对”的关联性,使你可以通过“键”查找“值”。

Modifier and Type Method and Description
void clear()

Removes all of the mappings from this map (optional operation).
default V compute(K key, BiFunction<? super K,? super V,? extends V> remappingFunction)

Attempts to compute a mapping for the specified key and its current mapped value (or null if there is no current mapping).
default V computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction)

If the specified key is not already associated with a value (or is mapped to null), attempts to compute its value using the given mapping function and enters it into this map unless null.
default V computeIfPresent(K key, BiFunction<? super K,? super V,? extends V> remappingFunction)

If the value for the specified key is present and non-null, attempts to compute a new mapping given the key and its current mapped value.
boolean containsKey(Object key)

Returns true if this map contains a mapping for the specified key.
boolean containsValue(Object value)

Returns true if this map maps one or more keys to the specified value.
Set<Map.Entry<K,V>> entrySet()

Returns a Set view of the mappings contained in this map.
boolean equals(Object o)

Compares the specified object with this map for equality.
default void forEach(BiConsumer<? super K,? super V> action)

Performs the given action for each entry in this map until all entries have been processed or the action throws an exception.
V get(Object key)

Returns the value to which the specified key is mapped, or null if this map contains no mapping for the key.
default V getOrDefault(Object key, V defaultValue)

Returns the value to which the specified key is mapped, or defaultValue if this map contains no mapping for the key.
int hashCode()

Returns the hash code value for this map.
boolean isEmpty()

Returns true if this map contains no key-value mappings.
Set<K> keySet()

Returns a Set view of the keys contained in this map.
default V merge(K key, V value, BiFunction<? super V,? super V,? extends V> remappingFunction)

If the specified key is not already associated with a value or is associated with null, associates it with the given non-null value.
V put(K key, V value)

Associates the specified value with the specified key in this map (optional operation).
void putAll(Map<? extends K,? extends V> m)

Copies all of the mappings from the specified map to this map (optional operation).
default V putIfAbsent(K key, V value)

If the specified key is not already associated with a value (or is mapped to null) associates it with the given value and returns null, else returns the current value.
V remove(Object key)

Removes the mapping for a key from this map if it is present (optional operation).
default boolean remove(Object key, Object value)

Removes the entry for the specified key only if it is currently mapped to the specified value.
default V replace(K key, V value)

Replaces the entry for the specified key only if it is currently mapped to some value.
default boolean replace(K key, V oldValue, V newValue)

Replaces the entry for the specified key only if currently mapped to the specified value.
default void replaceAll(BiFunction<? super K,? super V,? extends V> function)

Replaces each entry’s value with the result of invoking the given function on that entry until all entries have been processed or the function throws an exception.
int size()

Returns the number of key-value mappings in this map.
Collection<V> values()

Returns a Collection view of the values contained in this map.

Map的功能方法

  • put(Object key, Object value)添加一个“值”(想要得东西)和与“值”相关联的“键”(key)(使用它来查找)。
  • get(Object key)返回与给定“键”相关联的“值”。
  • containsKey()和containsValue()可以检查Map中是否包含某个“键”或“值”。

标准的Java类库中包含了几种不同的Map:

HashMap, TreeMap, LinkedHashMap, WeakHashMap, IdentityHashMap。

它们都有同样的基本接口Map,但是行为、效率、排序策略、保存对象的生命周期和判定“键”等价的策略等各不相同。

执行效率是Map的一个大问题,看看get方法的代码,就会明白为什么在ArrayList中搜索“键”是相当慢的。而这正是HashMap提高速度的地方。HashMap使用了特殊的值,称为“散列码”(hash code),来取代对键的缓慢搜索。“散列码”是“相对唯一”用以代表对象的int值,它是通过将该对象的某些信息进行转换而生成的。所有Java对象都能产生散列码,因为hashCode()是定义在基类Object中的方法。

HashMap

Map基于散列表的实现,就是使用对象的hashCode()进行快速查询的,插入和查询“键值对”的开销是固定的,此方法能够显着提高性能。

 

LinkedHashMap

类似于HashMap,但是迭代遍历它时,取得“键值对”的顺序是其插入次序,或者是最近最少使用(LRU算法)的次序;只比HashMap慢一点,而在迭代访问时发而更快,因为它使用链表维护内部次序。

TreeMap

基于红黑树数据结构的实现,查看“键”或“键值对”时,它们会被排序(次序由Comparabel或Comparator决定)。TreeMap的特点在于,你得到的结果是经过排序的。TreeMap是唯一的带有subMap()方法的Map,它可以返回一个子树。

WeakHashMao

弱键(weak key)Map,Map中使用的对象也被允许释放: 这是为解决特殊问题设计的。如果没有map之外的引用指向某个“键”,则此“键”可以被垃圾收集器回收。

IdentifyHashMap

使用==代替equals()对“键”作比较的hash map,专为解决特殊问题而设计。

总结

List,Set,Map将持有对象一律视为Object型别;Collection、List、Set、Map都是接口,不能实例化。继承自它们的 ArrayList, Vector, HashTable, HashMap是具体的对象,可被实例化。vector容器确切知道它所持有的对象隶属什么型别,vector不进行边界检查。

注意:

  • 如果涉及到堆栈,队列等操作,应该考虑用List,对于需要快速插入,删除元素,应该使用LinkedList,如果需要快速随机访问元素,应该使用ArrayList。
  • 如果程序在单线程环境中,或者访问仅仅在一个线程中进行,考虑非同步的类,其效率较高,如果多个线程可能同时操作一个类,应该使用同步的类。
  • 在除需要排序时使用TreeSet、TreeMap外,其他应使用HashSet,HashMap,因为他们的效率更高。
  • 要特别注意对哈希表的操作,作为key的对象要正确复写equals和hashCode方法。
  • 容器类仅能持有对象引用(指向对象的指针),而不是将对象信息copy一份至数列某位置,一旦将对象置入容器内,便损失了该对象的型别信息。
  • 尽量返回接口而非实际的类型,如返回List而非ArrayList,这样如果以后需要将ArrayList换成LinkedList时,客户端代码不用改变。这就是针对抽象编程。
  • Collection没有get()方法来取得某个元素。只能通过iterator()遍历元素。
  • Set和Collection拥有一模一样的接口。
  • List,可以通过get()方法来一次取出一个元素。
  • 一般使用ArrayList;用LinkedList构造堆栈stack、队列使用queue。
  • Map用 put(k,v) / get(k),还可以使用containsKey()/containsValue()来检查其中是否含有某个key、alue。
  • HashMap会利用对象的hashCode来快速找到key。
  • Map中元素,可以将key序列、value序列单独抽取出来。
  • 使用keySet()抽取key序列,将map中的所有keys生成一个Set。
  • 使用values()抽取value序列,将map中的所有values生成一个Collection。
  • 为什么一个生成Set,一个生成Collection呢?因为,key总是独一无二的,value允许重复。

 

Java语言Volatile原理

Java语言提供了一种稍弱的同步机制,即volatile变量,用来确保将变量的更新操作通知到其他线程。当把变量声明为volatile类型后,编译器与运行时都会注意到这个变量是共享的,因此不会将该变量上的操作与其他内存操作一起重排序。volatile变量不会被缓存在寄存器或者对其他处理器不可见的地方,因此在读取volatile类型的变量时总会返回最新写入的值。

在访问volatile变量时不会执行加锁操作,因此也就不会使执行线程阻塞,因此volatile变量是一种比sychronized关键字更轻量级的同步机制。

1553739684-9830-20160708224602686-2141387366

当对非 volatile 变量进行读写的时候,每个线程先从内存拷贝变量到CPU缓存中。如果计算机有多个CPU,每个线程可能在不同的CPU上被处理,这意味着每个线程可以拷贝到不同的 CPU cache 中。

而声明变量是 volatile 的,JVM 保证了每次读变量都从内存中读,跳过 CPU cache 这一步。

当一个变量定义为 volatile 之后,将具备两种特性:

1.保证此变量对所有的线程的可见性,这里的“可见性”,当一个线程修改了这个变量的值,volatile 保证了新值能立即同步到主内存,以及每次使用前立即从主内存刷新。但普通变量做不到这点,普通变量的值在线程间传递均需要通过主内存来完成。

2.禁止指令重排序优化。有volatile修饰的变量,赋值后多执行了一个“load addl $0x0, (%esp)”操作,这个操作相当于一个内存屏障(指令重排序时不能把后面的指令重排序到内存屏障之前的位置),只有一个CPU访问内存时,并不需要内存屏障;

什么是指令重排序:是指CPU采用了允许将多条指令不按程序规定的顺序分开发送给各相应电路单元处理。

volatile 性能:

volatile 的读性能消耗与普通变量几乎相同,但是写操作稍慢,因为它需要在本地代码中插入许多内存屏障指令来保证处理器不发生乱序执行。

Spring Cloud入门教程(服务注册和发现)

Spring Cloud(服务注册和发现

Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智能路由,微代理,控制总线)。分布式系统的协调导致了样板模式, 使用Spring Cloud开发人员可以快速地支持实现这些模式的服务和应用程序。他们将在任何分布式环境中运行良好,包括开发人员自己的笔记本电脑,裸机数据中心,以及Cloud Foundry等托管平台。

版本:Dalston.RELEASE

特性

Spring Cloud专注于提供良好的开箱即用经验的典型用例和可扩展性机制覆盖。

  • 分布式/版本化配置
  • 服务注册和发现
  • 路由
  • service – to – service调用
  • 负载均衡
  • 断路器
  • 分布式消息传递

云原生应用程序

云原生是一种应用开发风格,鼓励在持续交付和价值驱动开发领域轻松采用最佳实践。相关的学科是建立12-factor Apps,其中开发实践与交付和运营目标相一致,例如通过使用声明式编程和管理和监控。Spring Cloud以多种具体方式促进这些开发风格,起点是一组功能,分布式系统中的所有组件都需要或需要时轻松访问。

许多这些功能都由Spring Boot覆盖,我们在Spring Cloud中建立。更多的由Spring Cloud提供为两个库:Spring Cloud Context和Spring Cloud Commons。Spring Cloud上下文为Spring Cloud应用程序(引导上下文,加密,刷新范围和环境端点)的ApplicationContext提供实用程序和特殊服务。Spring Cloud Commons是一组在不同的Spring Cloud实现中使用的抽象和常用类(例如Spring Cloud Netflix vs. Spring Cloud Consul)。

Spring Cloud上下文:应用程序上下文服务

Spring Boot对于如何使用Spring构建应用程序有一个看法:例如它具有常规配置文件的常规位置,以及用于常见管理和监视任务的端点。Spring Cloud建立在此之上,并添加了一些可能系统中所有组件将使用或偶尔需要的功能。

引导应用程序上下文

一个Spring Cloud应用程序通过创建一个“引导”上下文来进行操作,这个上下文是主应用程序的父上下文。开箱即用,负责从外部源加载配置属性,还解密本地外部配置文件中的属性。这两个上下文共享一个Environment,这是任何Spring应用程序的外部属性的来源。Bootstrap属性的优先级高,因此默认情况下不能被本地配置覆盖。

引导上下文使用与主应用程序上下文不同的外部配置约定,因此使用bootstrap.ymlapplication.yml(或.properties)代替引导和主上下文的外部配置。例:bootstrap.yml

spring:
  application:
    name: foo
  cloud:
    config:
      uri: ${SPRING_CONFIG_URI:http://localhost:8888}

如果您的应用程序需要服务器上的特定于应用程序的配置,那么设置spring.application.name(在bootstrap.ymlapplication.yml)中是个好主意。

您可以通过设置spring.cloud.bootstrap.enabled=false(例如在系统属性中)来完全禁用引导过程。

应用程序上下文层次结构

如果您从SpringApplicationSpringApplicationBuilder构建应用程序上下文,则将Bootstrap上下文添加为该上下文的父级。这是一个Spring的功能,即子上下文从其父进程继承属性源和配置文件,因此与不使用Spring Cloud Config构建相同上下文相比,“主”应用程序上下文将包含其他属性源。额外的财产来源是:

  • “bootstrap”:如果在Bootstrap上下文中找到任何PropertySourceLocators,则可选CompositePropertySource显示为高优先级,并且具有非空属性。一个例子是来自Spring Cloud Config服务器的属性。
  • “applicationConfig:[classpath:bootstrap.yml]”(如果Spring配置文件处于活动状态,则为朋友)。如果您有一个bootstrap.yml(或属性),那么这些属性用于配置引导上下文,然后在父进程设置时将它们添加到子上下文中。它们的优先级低于application.yml(或属性)以及作为创建Spring Boot应用程序的过程的正常部分添加到子级的任何其他属性源。

由于属性源的排序规则,“引导”条目优先,但请注意,这些条目不包含来自bootstrap.yml的任何数据,它具有非常低的优先级,但可用于设置默认值。

您可以通过简单地设置您创建的任何ApplicationContext的父上下文来扩展上下文层次结构,例如使用自己的界面,或使用SpringApplicationBuilder方便方法(parent()child()sibling())。引导环境将是您创建自己的最高级祖先的父级。层次结构中的每个上下文都将有自己的“引导”属性源(可能为空),以避免无意中将值从父级升级到其后代。层次结构中的每个上下文(原则上)也可以具有不同的spring.application.name,因此如果存在配置服务器,则不同的远程属性源。普通的Spring应用程序上下文行为规则适用于属性解析:子环境中的属性通过名称和属性源名称覆盖父项中的属性(如果子级具有与父级名称相同的属性源,一个来自父母的孩子不包括在孩子中)。

请注意,SpringApplicationBuilder允许您在整个层次结构中共享Environment,但这不是默认值。因此,兄弟情境尤其不需要具有相同的资料或财产来源,尽管它们与父母共享共同点。

自定义引导配置

可以通过在org.springframework.cloud.bootstrap.BootstrapConfiguration键下添加条目/META-INF/spring.factories来训练引导上下文来执行任何您喜欢的操作。这是用于创建上下文的Spring @Configuration类的逗号分隔列表。您可以在此处创建要用于自动装配的主应用程序上下文的任何bean,并且还有ApplicationContextInitializer类型的@Beans的特殊合同。如果要控制启动顺序(默认顺序为“最后”),可以使用@Order标记类。

警告 添加自定义BootstrapConfiguration时,请注意,您添加的类不是错误的@ComponentScanned到您的“主”应用程序上下文中,可能不需要它们。对于您的@ComponentScan@SpringBootApplication注释配置类尚未涵盖的启动配置类,请使用单独的包名称。

引导过程通过将初始化器注入主SpringApplication实例(即正常的Spring Boot启动顺序,无论是作为独立应用程序运行还是部署在应用程序服务器中)结束。首先,从spring.factories中找到的类创建引导上下文,然后在ApplicationContextInitializer类型的所有@Beans添加到主SpringApplication开始之前。

自定义引导属性源

引导过程添加的外部配置的默认属性源是Config Server,但您可以通过将PropertySourceLocator类型的bean添加到引导上下文(通过spring.factories)添加其他源。您可以使用此方法从其他服务器或数据库中插入其他属性。

作为一个例子,请考虑以下微不足道的自定义定位器:

@Configuration
public class CustomPropertySourceLocator implements PropertySourceLocator {

    @Override
    public PropertySource<?> locate(Environment environment) {
        return new MapPropertySource("customProperty",
                Collections.<String, Object>singletonMap("property.from.sample.custom.source", "worked as intended"));
    }

}

传入的Environment是要创建的ApplicationContextEnvironment,即为我们提供额外的属性来源的。它将已经具有正常的Spring Boot提供的资源来源,因此您可以使用它们来定位特定于此Environment的属性源(例如通过将其绑定在spring.application.name上,如在默认情况下所做的那样Config Server属性源定位器)。

如果你在这个类中创建一个jar,然后添加一个META-INF/spring.factories包含:

org.springframework.cloud.bootstrap.BootstrapConfiguration=sample.custom.CustomPropertySourceLocator

那么“customProperty”PropertySource将显示在其类路径中包含该jar的任何应用程序中。

环境变化

应用程序将收听EnvironmentChangeEvent,并以几种标准方式进行更改(用户可以以常规方式添加ApplicationListeners附加ApplicationListeners)。当观察到EnvironmentChangeEvent时,它将有一个已更改的键值列表,应用程序将使用以下内容:

  • 重新绑定上下文中的任何@ConfigurationProperties bean
  • logging.level.*中的任何属性设置记录器级别

请注意,配置客户端不会通过默认轮询查找Environment中的更改,通常我们不建议检测更改的方法(尽管可以使用@Scheduled注释进行设置)。如果您有一个扩展的客户端应用程序,那么最好将EnvironmentChangeEvent广播到所有实例,而不是让它们轮询更改(例如使用Spring Cloud总线)。

EnvironmentChangeEvent涵盖了大量的刷新用例,只要您真的可以更改Environment并发布事件(这些API是公开的,部分内核为Spring)。您可以通过访问/configprops端点(普通Spring Boot执行器功能)来验证更改是否绑定到@ConfigurationProperties bean。例如,DataSource可以在运行时更改其maxPoolSize(由Spring Boot创建的默认DataSource是一个@ConfigurationProperties bean),并且动态增加容量。重新绑定@ConfigurationProperties不会覆盖另一大类用例,您需要更多的控制刷新,并且您需要更改在整个ApplicationContext上是原子的。为了解决这些担忧,我们有@RefreshScope

刷新范围

当配置更改时,标有@RefreshScope的Spring @Bean将得到特殊处理。这解决了状态bean在初始化时只注入配置的问题。例如,如果通过Environment更改数据库URL时DataSource有开放连接,那么我们可能希望这些连接的持有人能够完成他们正在做的工作。然后下一次有人从游泳池借用一个连接,他得到一个新的URL。

刷新范围bean是在使用时初始化的懒惰代理(即当调用一个方法时),并且作用域作为初始值的缓存。要强制bean重新初始化下一个方法调用,您只需要使其缓存条目无效。

RefreshScope是上下文中的一个bean,它有一个公共方法refreshAll()来清除目标缓存中的范围内的所有bean。还有一个refresh(String)方法可以按名称刷新单个bean。此功能在/refresh端点(通过HTTP或JMX)中公开。

注意 @RefreshScope(技术上)在@Configuration类上工作,但可能会导致令人惊讶的行为:例如,这并不 意味着该类中定义的所有@Beans本身都是@RefreshScope。具体来说,任何取决于这些bean的东西都不能依赖它们在刷新启动时被更新,除非它本身在@RefreshScope(在其中将重新刷新并重新注入其依赖关系),那么它们将从刷新的@Configuration)重新初始化。

加密和解密

Spring Cloud具有一个用于在本地解密属性值的Environment预处理器。它遵循与Config Server相同的规则,并通过encrypt.*具有相同的外部配置。因此,您可以使用{cipher}*格式的加密值,只要有一个有效的密钥,那么在主应用程序上下文获取Environment之前,它们将被解密。要在应用程序中使用加密功能,您需要在您的类路径中包含Spring安全性RSA(Maven协调“org.springframework.security:spring-security-rsa”),并且还需要全面强大的JCE扩展你的JVM

端点

对于Spring Boot执行器应用程序,还有一些额外的管理端点:

  • POST到/env以更新Environment并重新绑定@ConfigurationProperties和日志级别
  • /refresh重新加载引导带上下文并刷新@RefreshScope bean
  • /restart关闭ApplicationContext并重新启动(默认情况下禁用)
  • /pause/resume调用Lifecycle方法(stop()start() ApplicationContext

例子:

建立EurekaServer服务端

@EnableEurekaServer
@SpringBootApplication
public class ServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ServerApplication.class, args);
    }

}

EurekaServer服务端pom.xml

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-config-server</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

EurekaServer服务端application.properties

server.port=7080

eureka.instance.hostname=localhost
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
eureka.client.service-url.defaultZone=http://127.0.0.1:7080/eureka/

*注:这里defaultZone必须是驼峰法,否则会出现连接服务端失败的错误。

建立EurekaClient客户端

@EnableEurekaClient
@EnableWebMvc
@SpringBootApplication
public class Demo1Application {

    public static void main(String[] args) {
        SpringApplication.run(Demo1Application.class, args);
    }

}

Eureka客户端pom.xml

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>

    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>2.0.0</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

Eureka客户端application.properties

server.port=7081
eureka.instance.hostname=localhost
eureka.client.register-with-eureka=true
eureka.client.fetch-registry=true
eureka.client.service-url.defaultZone=http://127.0.0.1:7080/eureka/


spring.application.name=Eureka-Demo-Client

spring.datasource.url=jdbc:mysql://127.0.0.1/test
spring.datasource.username=root
spring.datasource.password=root

*注:这里defaultZone必须是驼峰法,否则会出现连接服务端失败的错误。

Eureka运行截图

a001

1181920212232
 
Copyright © 2008-2021 lanxinbase.com Rights Reserved. | 粤ICP备14086738号-3 |