1、安全性

MySQL 5.7 的目标是成为发布以来最安全的 MySQL 服务器,其在 SSL/TLS 和全面安全开发方面有一些重要的改变。

mysql.user表结构升级

MySQL5.7用户表mysql.user的plugin字段不允许为空,默认值是mysql_native_password,而不是mysql_old_password,不再支持旧密码格式。

从旧版本升级,直接将原有的SQL导入到MySQL5.7,需要进行user表结构的升级:

  1. shell> /usr/local/mysql/bin/mysql_upgrade -uroot -p
  2. 重启MySQL

mysql.user表中已经没有了password字段,取而代之的是“authentication_string

# 修改密码(或者忘记密码的处理方式):
# 运行:
shell> mysqld_safe --skip-grant-tables &
# 如果此时不想被远程连接:
shell> mysqld_safe --skip-grant-tables --skip-networking & # 更改密码:
mysql> update mysql.user set authentication_string=password('123AAAbbb2323#') where user='root' and Host = 'localhost';
mysql> flush privileges;
或者:
mysql> alter user 'root'@'localhost' identified by '123AAAbbb2323#';
mysql> flush privileges;

账号安全

用户长度最大为32字节,之前最大长度为16字节,并且CREATE USER 和 DROP USER 命令里实现了 IF [NOT] EXISTS 条件判断。

创建用户分2步:先通过create user 创建用户,再通过grant来授权。

# 先创建用户
mysql> CREATE USER 'dba'@'localhost' IDENTIFIED BY '123456';
# 或者
mysql> CREATE USER 'dba'@'localhost' IDENTIFIED WITH 'mysql_native_password' BY '123456';
# 或者
mysql> create user ‘test1’@’%’ identified with mysql_native_password as ‘23AE809DDACAF96AF0FD78ED04B6A265E05AA257’ # 再授权
mysql> grant select,insert,update,delete on *.* to dba@localhost;

直接使用grant命令创建用户将会报如下警告:

Using GRANT for creating new user is deprecated and will be removed in future release. Create new user with CREATE USER statement.

密码过期策略

增加密码过期机制,过期后需要修改密码,否则可能会被禁用,或者进入沙箱模式。

为用户设置密码过期时间,一定时间以后,强制用户修改密码。可以直接在create user的时候设置,也可以alter user设置:

  • PASSWORD EXPIRE DEFAULT   # 默认,过期时间受全局变量 default_password_lifetime 控制

    • PASSWORD EXPIRE NEVER #永不过期
  • PASSWORD EXPIRE INTERVAL N DAY  #N天后过期
    • PASSWORD EXPIRE #过期

举例:

# 直接创建用户的时候设置 10天后过期:
mysql> create user dba@localhost identified by '123456' password expire interval 10 day; # 对已有用户设置 永不过期:
mysql> alter user dba@localhost password expire never;

默认密码过期时间受变量default_password_lifetime控制,为0表示默认永不过期

mysql> set global  default_password_lifetime=0;
Query OK, 0 rows affected (0.00 sec)

密码安全策略

为防止用户设置过简单的密码,mysql在5.6开始就已经支持了密码安全策略的插件。

开启密码安全策略,2种方法:

① 在配置文件里修改:

[mysqld]
plugin-load=validate_password.so
validate-password=FORCE_PLUS_PERMANENT

② 在线修改

mysql> INSTALL PLUGIN validate_password SONAME 'validate_password.so';
Query OK, 0 rows affected (0.01 sec)

开启安全策略的时候,不能为用户设置一个简单的密码:

mysql> grant all on *.* to dba@localhost identified by '123';
ERROR 1819 (HY000): Your password does not satisfy the current policy requirements

密码要求的强度手参数:validate_password_policy 的影响。validate_password_policy的值有:

  • 0 or LOW:仅需需符合密码长度(由参数validate_password_length指定,默认为8)
  • 1 or MEDIUM:满足LOW策略,同时还需满足至少有1个数字,小写字母,大写字母和特殊字符,默认。
  • 2 or STRONG:满足MEDIUM策略,同时密码不能存在字典文件(dictionary file)中

相关参数:

  • validate_password_dictionary_file:在STRONG模式下还能设置字典文件,字典中存在的密码不得使用。可以通过该参数来设置字典文件。
  • validate_password_length:设置密码的最小长度,默认值为8。
  • validate_password_mixed_case_count:小写和大写字符的最小数目,如果密码策略是MEDIUM或STRONG的,有validate_password插件检查,默认1。
  • validate_password_number_count:数字字符的最小数目,如果密码策略是MEDIUM或STRONG的,有validate_password插件检查,默认1。
  • validate_password_special_char_count:非字母字符(特殊字符)的最小数目,如果密码策略是MEDIUM或STRONG的,有validate_password插件检查,默认1。

根据上面的参数,按照自己想要的密码复杂度,进行设置。

对普通用户进行lock

锁定用户:
mysql> alter user admin@localhost account lock; 登陆报错:
ERROR 3118 (HY000): Access denied for user 'admin'@'localhost'. Account is locked. 解锁用户:
mysql> alter user admin@localhost account unlock;

初始化方式

高版本的MySQL,逐步废弃mysql_install_db的初始化方式

在5.7中,推荐使用bin/mysqld –-initialize对数据库进行初始化,初始化过程会创建带随机密码的 root@localhost 账号并不再创建test 库,初始化输出如下:

[Note] A temporary password is generated for root@localhost: KJ1foE6BFX;3

在初始化时如果使用–initial-insecure,则会创建空密码的 root@localhost 账号

新初始化的 root@localhost 账号,第一次登录时,需要修改新的密码才能正常使用

SSL 特性

MySQL 5.7版本提供了更为简单SSL安全访问配置,并且默认连接就采用SSL的加密方式

姜承尧文章中的测试案例显示 开启SSL 性能开销在25% 左右

2、新支持

原生支持JSON

5.7版本之前,只能在varchar或是text等字符类型的列中存储json类型的字符串,并通过程序解析使用json字符串。这种做法当然有其缺陷:必须自行确认/解析数据、解决更新中的困难、或在执行插入操作时忍受较慢的速度。

5.7版本:增加了json列类型以及json_开头的函数,如json_type(),json_object(),json_merge()等。

从MySQL5.7.8之后,由于原生支持JSON,处理JSON文件就非常简单。现在执行插入与更新操作时可以自动确认了,而且效率很高;使用新定制的一系列功能访问对象与数组成员的速度也更快了。

举个栗子:

创建表json_test:

CREATE TABLE json_test(
id INT(11) AUTO_INCREMENT PRIMARY KEY,
person_desc JSON
)ENGINE INNODB;

插入一条记录:

INSERT INTO json_test(person_desc) VALUES ('{
"programmers": [{
"firstName": "Brett",
"lastName": "McLaughlin",
"email": "aaaa"
}, {
"firstName": "Jason",
"lastName": "Hunter",
"email": "bbbb"
}, {
"firstName": "Elliotte",
"lastName": "Harold",
"email": "cccc"
}],
"authors": [{
"firstName": "Isaac",
"lastName": "Asimov",
"genre": "sciencefiction"
}, {
"firstName": "Tad",
"lastName": "Williams",
"genre": "fantasy"
}, {
"firstName": "Frank",
"lastName": "Peretti",
"genre": "christianfiction"
}],
"musicians": [{
"firstName": "Eric",
"lastName": "Clapton",
"instrument": "guitar"
}, {
"firstName": "Sergei",
"lastName": "Rachmaninoff",
"instrument": "piano"
}]
}');

查看插入的这行JSON数据有哪些KEY:

mysql> SELECT id,json_keys(person_desc) as "keys" FROM json_test\G
*************************** 1. row ***************************
id: 1
keys: ["authors", "musicians", "programmers"]
1 row in set (0.00 sec)

可以看到里面有三个KEY,分别为authors,musicians,programmers。

又例如:

# 转换为json对象
mysql> select json_object('name','tom','age',20) ;
+------------------------------------+
| json_object('name','tom','age',20) |
+------------------------------------+
| {"age": 20, "name": "tom"} |
+------------------------------------+
1 row in set (0.00 sec)
# 转换为json数组
mysql> select json_array('a','b',now()) ;
+------------------------------------------+
| json_array('a','b',now()) |
+------------------------------------------+
| ["a", "b", "2019-01-08 13:40:21.000000"] |
+------------------------------------------+
1 row in set (0.00 sec)

支持空间数据类型

空间数据类型常用于处理地理空间信息,它们描述了几何对象的真实坐标与形状。在MySQL中,可以使用像Point、LineString或Polygon之类的几何对象代表,还有一些很有用的空间函数k。

支持为表计算列

所谓计算列,就是通过其他列计算得到的值。

5.7之前版本实现计算列一般通过触发器实现。如下:​

mysql> create trigger insr_tig before insert on t1 for each row set new.c3=new.c1+new.c2;

Query OK, 0 rows affected (0.09 sec)

mysql> create trigger upd_tig before update on t1 for each row set new.c3=new.c1+new.c2;
Query OK, 0 rows affected (0.01 sec)

5.7版本实现计算列只需要在建表/修改表时添加列的as参数就可以了,如下:

mysql> create table t2(id int auto_increment not null,c1 int ,c2 int ,c3 int as(c1+c2),primary key(id));
Query OK, 0 rows affected (0.03 sec) mysql> insert into t2(c1,c2) values(2,3);
Query OK, 1 row affected (0.01 sec) mysql> select * from t2;
+----+------+------+------+
| id | c1 | c2 | c3 |
+----+------+------+------+
| 1 | 2 | 3 | 5 |
+----+------+------+------+
1 row in set (0.00 sec) mysql> update t2 set c1=10 where id=1;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from t2;
+----+------+------+------+
| id | c1 | c2 | c3 |
+----+------+------+------+
| 1 | 10 | 3 | 13 |
+----+------+------+------+
1 row in set (0.00 sec)

Online rename index name

alter table ttt1 rename index idx to idxx;

mysql> show create table ttt1 ;
+-------+--------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+--------------------------------------------------------------------------------------+
| ttt1 | CREATE TABLE `ttt1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`person_desc` json DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx` (`id`)
) /*!50100 TABLESPACE `tb_space1` */ ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+-------+--------------------------------------------------------------------------------------+
1 row in set (0.00 sec) mysql> alter table ttt1 rename index idx to idxx;
Query OK, 0 rows affected (0.05 sec)
Records: 0 Duplicates: 0 Warnings: 0 mysql> show create table ttt1 ;
+-------+--------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+--------------------------------------------------------------------------------------+
| ttt1 | CREATE TABLE `ttt1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`person_desc` json DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idxx` (`id`)
) /*!50100 TABLESPACE `tb_space1` */ ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+-------+--------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

动态修改varchar 长度大小

可以通过ALTER TABLE 语句以in place方式修改varchar的大小且无需table-copy

但存在限制:表示 varchar 长度的字节数不能变化(如果变更前使用1个字节表示长度,变更后也必须使用1个字节表示),即只支持0~255内的或者255以上的范围变更(增大),如果字段的长度从254增到256时就不能使用in-place算法,必须使用copy算法,否侧报错,这个原理就是varchar会在头部存储一个长度,如果小于255就是一个BYTES,8位;如果大于255当然就需要两个BYTES了。头部都变了,自然要重新copy table了。

需要注意的是 减小 varchar(N)长度的大小必须使用copy类型

举个栗子:

# varchar(20) -- varchar(300),只能使用copy算法
mysql> create table testtb2 (id int , vvv varchar(20)) ;
Query OK, 0 rows affected (0.02 sec)
mysql> alter table testtb2 change column vvv vvv varchar(300),algorithm=inplace;
ERROR 1846 (0A000): ALGORITHM=INPLACE is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY.
mysql> alter table testtb2 change column vvv vvv varchar(300),algorithm=copy;
Query OK, 0 rows affected (0.32 sec)
Records: 0 Duplicates: 0 Warnings: 0

新增临时表空间

为所有非压缩的innodb临时表提供一个独立的表空间,默认的临时表空间文件为ibtmp1,位于数据目录。我们可通过innodb_temp_data_file_path参数指定临时表空间的路径和大小

mysql> show global variables like 'innodb_temp_data_file_path';
+----------------------------+-----------------------+
| Variable_name | Value |
+----------------------------+-----------------------+
| innodb_temp_data_file_path | ibtmp1:12M:autoextend |
+----------------------------+-----------------------+
1 row in set (0.01 sec)

MySQL每次重新启动时,会重新创建临时表空间

**注意 **:

从5.7.5开始,新增一个系统选项 internal_tmp_disk_storage_engine 可定义OnDisk临时表的引擎类型为 InnoDB,而在这以前,只能使用 MyISAM。(HEAP临时表,内部临时表有两种类型:HEAP临时表和OnDisk临时表)

而在5.6.3以后新增的参数default_tmp_storage_engine是控制create temporary table创建的外部临时表的存储引擎,在以前默认是MEMORY。(外部临时表:临时表只对当前用户可见,当前会话结束的时候,该临时表会自动关闭)

mysql> show global variables like '%_storage_engine';
+----------------------------------+--------+
| Variable_name | Value |
+----------------------------------+--------+
| default_storage_engine | InnoDB |
| default_tmp_storage_engine | InnoDB |
| enforce_storage_engine | |
| internal_tmp_disk_storage_engine | InnoDB |
+----------------------------------+--------+
4 rows in set (0.01 sec)

sys schema

MySQL 5.7 版本新增了sys 数据库,该库通过视图的形式把information_schema 和performance_schema结合起来,查询出更加令人容易理解的数据,帮助DBA快速获取数据库系统的各种纬度的元数据信息,帮助DBA和开发快速定位性能瓶颈。

mysql client

旧版本的mysql客户端在执行Control+C,如果有SQL在运行会中断SQL,没有会退出mysql客户端,新版本也会中断SQL,但是不会退出。

3、InnoDB增强

在线调整InnoDB缓冲池大小

MySql5.7之前:要变更innodb_buffer_pool大小必须更改my.cnf文件后重启数据库服务器方生效

MySql5.7之后:变为动态参数,可以在线调整大小

  • nnodb_buffer_pool_size 缓池区大小
  • innodb_buffer_pool_chunk_size 缓池区块的大小  默认128M
  • innodb_buffer_pool_instances 缓池区实例的个数

innodb_buffer_pool_size  必须是 innodb_buffer_pool_chunk_size * innodb_buffer_pool_instances 倍数,如果不是mysql也会自动取整为倍数。

修改缓冲池的大小,会对运行的事务有影响,尽量在少操作的情况下修改。

mysql> show global status where variable_name='InnoDB_buffer_pool_resize_status';
+----------------------------------+----------------------------------------------------------------------+
| Variable_name | Value |
+----------------------------------+----------------------------------------------------------------------+
| Innodb_buffer_pool_resize_status | Size did not change (old size = new size = 134217728. Nothing to do. |
+----------------------------------+----------------------------------------------------------------------+
1 row in set (0.01 sec) mysql> set global innodb_buffer_pool_size=268435456 ;
Query OK, 0 rows affected (0.00 sec) mysql> SHOW STATUS WHERE Variable_name='InnoDB_buffer_pool_resize_status';
+----------------------------------+----------------------------------------------------+
| Variable_name | Value |
+----------------------------------+----------------------------------------------------+
| Innodb_buffer_pool_resize_status | Completed resizing buffer pool at 190108 16:24:05. |
+----------------------------------+----------------------------------------------------+
1 row in set (0.00 sec)

支持为Innodb建立表空间

MySql5.7之前:具有系统共享表空间和为每个表建立的独立表空间

MySql5.7之后:支持create tablespace语法为一个表或者多个表建立公用表空间

举个栗子:

mysql> create tablespace tb_space1 add datafile 'tb_space11.ibd' engine=innodb;
Query OK, 0 rows affected (0.30 sec) mysql> create table ttt1 (id INT(11) AUTO_INCREMENT PRIMARY KEY,person_desc JSON) tablespace tb_space1;
Query OK, 0 rows affected (0.06 sec) mysql> create table ttt2 (id INT(11) AUTO_INCREMENT PRIMARY KEY,person_desc JSON) tablespace tb_space1;
Query OK, 0 rows affected (0.06 sec) mysql> show create table ttt3 ;
+-------+-----------------------------------------------------------------------------------+
| Table | Create Table |
+-------+-----------------------------------------------------------------------------------+
| ttt2 | CREATE TABLE `ttt2` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`person_desc` json DEFAULT NULL,
PRIMARY KEY (`id`)
) /*!50100 TABLESPACE `tb_space1` */ ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+-------+-----------------------------------------------------------------------------------+
1 row in set (0.00 sec)

tb_space11.ibd表空间文件被创建在数据目录下

InnoDB缓冲池导入导出

增加以下参数控制InnoDB缓冲池的导入导出:

  • innodb_buffer_pool_filename   如果开启InnoDB预热功能,停服务时,MySQL将InnoDB缓冲池中的热数据保存到数据目录中,默认文件名为ib_buffer_pool
  • innodb_buffer_pool_dump_pct     导出缓存池的百分比,默认25%
  • innodb_buffer_pool_dump_now   用手工方式立刻做一次把热数据dump到本地磁盘。
  • innodb_buffer_pool_dump_at_shutdown   正常停止服务时,InnoDB将InnoDB缓冲池中的热数据保存到本地硬盘,默认为OFF
  • innodb_buffer_pool_load_now  停止MySQL服务时,以手动方式立刻做一次将InnoDB缓存池中的热数据保存到本地硬盘,默认为OFF
  • innodb_buffer_pool_load_abort  如果开启该参数,即便开启InnoDB预热功能,启动服务时,MySQL也不会将本地硬盘的热数据加载到InnoDB缓冲池中,默认为OFF
  • innodb_buffer_pool_load_at_startup   如果开启该参数,启动MySQL服务时,MySQL将本地热数据加载到InnoDB缓冲池中,默认为OFF

支持多线程刷脏页

5.6.2版本中,MySQL将刷脏页的线程从master线程独立出来,5.7.4版本之后,MySQL系统支持多线程刷脏页,进程的数量由innodb_page_cleaners参数控制,该参数不能动态修改,最小值为1 ,最大值支持64,5.7.7以及之前默认值是1 ,5.7.8版本之后修改默认参数为4。

当启用多线程刷脏页,系统将innodb buffer instance脏页分配到各个空闲的刷脏页线程上,如果设置的innodb_page_cleaners>innodb_buffer_pool_instances,系统会自动重置为innodb_buffer_pool_instances大小。

4、复制增强

MySQL5.7在主从复制上面相对之前版本多了一些新特性,包括多源复制、基于组提交的并行复制、在线修改Replication Filter、GTID增强、半同步复制增强等

多源复制、基于组提交的并行复制、在线修改Replication Filter 的内容这里先略去

MySql5.7之前,要把基于日志点的复制方式变为基于GTID的复制方式或者把基于GTID的复制方式变为基于日志点的复制方式必须要重启master服务器。MySql5.7之后可以在线变更,不需要重启服务器。

5、弃用

以下特性在5.7里已经弃用,在后续的版本可能会移除。

–skip-innodb–innodb=OFF, –disable-innodb 弃用了

因为5.7innodb是不能禁用的。

系统变量storage_engine 用 default_storage_engine代替

mysql.user表中的password字段被弃用 ,改为authentication_string

MySQL5.7 的新特点的更多相关文章

  1. MySQL5.6 GTID新特性实践

    MySQL5.6 GTID新特性实践 GTID简介 搭建 实验一:如果slave所需要事务对应的GTID在master上已经被purge了 实验二:忽略purged的部分,强行同步 本文将简单介绍基于 ...

  2. MySQL5.7的新特性

    MySQL 5.7版本据说已经在了很大的性能提升以及做得更加安全了,想了解更多MySQL 5.7的新特性可以参考我转载叶金荣老师的MySQL 5.7的新特性说明.这里我简单演示一下MySQL 5.7的 ...

  3. MySQL5.7.12新密码登录方式及密码策略

    在Centos6.6上安装MySQL5.7.12时,遇到了一个问题 安装后在/root目录下没有发现有.mysql_secret这个文件,所以没有没法按照官方文档上说的那样使用,这里记录下, 解决方式 ...

  4. mysql5.6创建新用户并给授权指定的数据库权限

    一.环境: CentOS 6.8 mysql 5.6 二.背景 给外包的工作人员提供我司某台服务器的 mysql 中某个数据库的访问权限. 之所以要做限制,是防止他们对我司其他的数据库非法进行操作. ...

  5. 利用Mysql5.7的新特性实现多机房高可用架构【转】

    再牛逼的架构也敌不过挖掘机,无论单机房内你的架构多么的高可用,多么的完善,当挖掘机挖下去那一瞬间,都是扯蛋,楼主所在的公司也被挖掘机挖断过光纤.电力线. 为什么大家都在谈论服务冗余,缓存击穿等高可用时 ...

  6. mysql5.7 创建新表时提示时间戳非法

    # 背景 mysql版本5.7.8,需要创建新表,研发提供的sql文件,执行后报错如下: ERROR (): Invalid default value for 'deleted_at' 就猜测到时因 ...

  7. 初试mysql5.7.2新特性:多源复制(MySQL 5.7 multi-source replication)

    多源复制和多主复制的区别: 多主复制示意图: 多源复制示意图: 在my.cnf中添加crash safe特性参数:master_info_repository=TABLE;relay_log_info ...

  8. Mysql5.7.10新加用户

    INSERT INTO mysql.user(HOST,USER,authentication_string,ssl_cipher,x509_issuer,x509_subject,select_pr ...

  9. MySQL5.6新特性Index conditontion pushdow

    index condition pushdown是MySQL5.6的新特性,主要是对MySQL索引使用的优化. Index condition push简称ICP,索引条件下推,将索引条件从serve ...

随机推荐

  1. nginx 多级反向代理获取客户端真实IP

    set_real_ip_from ; set_real_ip_from ; set_real_ip_from ; set_real_ip_from ; set_real_ip_from 127.0.0 ...

  2. openshift node资源限制

    在oc的node配置文件中添加 ...... kubeletArguments: cgroups-per-qos: - "true" cgroup-driver: - " ...

  3. 一个基于JRTPLIB的轻量级RTSP客户端(myRTSPClient)——实现篇:(十)使用JRTPLIB传输RTP数据

    myRtspClient通过简单修改JRTPLIB的官方例程作为其RTP传输层实现.因为JRTPLIB使用的是CMAKE编译工具,这就是为什么编译myRtspClient时需要预装CMAKE. 该部分 ...

  4. iNotify.js通知JS 实现浏览器的 title 闪烁、滚动、声音提示、chrome、Firefox、Safari等系统通知。

    https://github.com/jaywcjlove/iNotify     JS 实现浏览器的 title 闪烁.滚动.声音提示.chrome.Firefox.Safari等系统通知. 这是重 ...

  5. 利用TensorFlow实现线性回归模型

    准备数据: import numpy as np import tensorflow as tf import matplotlib.pylot as plt # 随机生成1000个点,围绕在y=0. ...

  6. 移动开发--移动web特别样式处理

    高清图片:100px*200px的图片 设置100px*100px的大小,会被拉大,变模糊,应该用100dp*100dp(物理像素)去渲染. 一像素边框: 相对单位rem: 多行文本溢出.

  7. ASP.Net Core 2.2 MVC入门到基本使用系列 (三)(转)

    本教程会对基本的.Net Core 进行一个大概的且不会太深入的讲解, 在您看完本系列之后, 能基本甚至熟练的使用.Net Core进行Web开发, 感受到.Net Core的魅力. 本教程知识点大体 ...

  8. gitlab4.0备份还原

    一,备份 备份默认路径查看: gitlab/config/gitlab.yml 中的backup: 默认tmp/backups ====>这个是gitlab/tmp/backups/  可不是系 ...

  9. EL的隐含对象(三)【访问环境信息的隐含对象】

    EL中提供了6个访问环境信息的隐含对象.分别是: (1)param对象 param对象用于获取请求参数的值,应用在参数值只有一个的情况.在应用param对象时,返回的结果为字符串. 例:在JSP页面中 ...

  10. c#之根据出生日期获得星座信息

    星座定义如下: 代码如下: public enum Constellation { Aquarius = , // 水瓶座 1.20 - 2.18 Pisces = , // 双鱼座 2.19 - 3 ...