mybatis类型转换器处理PostGis数据库geometry类型转换
在入库和查询中需要自动的让geometry的类型和实体类中的类型映射。
实体类中接收参数是String类型(geoJson)
PostGis中的geometry类型是十六进制的扩展WKB类型(EWKB),
虽然Postgis数据库中提供类类型转换函数,能转换各种类型postgis常用命令_yaoct的博客-CSDN博客
但是基于mybatis框架查询时,就需要用java代码来转换。初步方案时mybatis中的类型转换器。
先引入java处理GIS的库,这里用的是Geotools库。
1.java代码中数据类型的转换
geotools的maven引入:
<!-- geotools的远程库 --><repositories><repository><id>osgeo</id><name>OSGeo Release Repository</name><url>https://repo.osgeo.org/repository/release/</url><snapshots><enabled>false</enabled></snapshots><releases><enabled>true</enabled></releases></repository><repository><id>osgeo-snapshot</id><name>OSGeo Snapshot Repository</name><url>https://repo.osgeo.org/repository/snapshot/</url><snapshots><enabled>true</enabled></snapshots><releases><enabled>false</enabled></releases></repository></repositories><dependencies><!--geotool https://docs.geotools.org/latest/userguide/tutorial/quickstart/maven.html--><dependency><groupId>org.geotools</groupId><artifactId>gt-geojson</artifactId><version>${geotools.version}</version></dependency><dependency><groupId>org.geotools</groupId><artifactId>gt-main</artifactId><version>${geotools.version}</version></dependency><dependency><groupId>org.geotools</groupId><artifactId>gt-opengis</artifactId><version>${geotools.version}</version></dependency><dependency><groupId>org.geotools</groupId><artifactId>gt-referencing</artifactId><version>${geotools.version}</version></dependency><dependency><groupId>org.geotools</groupId><artifactId>gt-metadata</artifactId><version>${geotools.version}</version></dependency><dependency><groupId>org.geotools</groupId><artifactId>gt-epsg-hsql</artifactId><version>${geotools.version}</version></dependency></dependencies>
Geotools工具类转换WKB和Geojson
WKBReader reader = new WKBReader( );Geometry geometry = reader.read(WKBReader.hexToBytes("0101000020E61000002C39382229FD5D4085716007088C3E40"));// 设置保留6位小数,否则GeometryJSON默认保留4位小数GeometryJSON geometryJson = new GeometryJSON(7);String s = geometryJson.toString(geometry);System.out.println(s);//{"type":"Point","coordinates":[119.9556356,30.5469975]}//EWKB->转geojson丢失信息Geometry read = geometryJson.read("{\"type\":\"Point\",\"coordinates\":[119.9556356,30.5469975]}");System.out.println(read.toString());WKBWriter wkbWriter = new WKBWriter();byte[] write = wkbWriter.write(geometry);String s1 = WKBWriter.toHex(write);System.out.println(s1);
2.mybatis-plus类型转换器
这里框架用的是mybatis-plus,所有使用转换时,mybatis-plus中的实体类也要配置一些转换注解,其他和mybaitis中的xml配置属性相同。参考
MyBatis Plus 自动类型转换之TypeHandler
@Data
@ToString
@TableName (value = "test_table",autoResultMap = true)
@ApiModel ("test")
public class TestTable implements Serializable {private static final long serialVersionUID = 8881418345724766899L;@TableId(value = "id")private Integer id;@ApiModelProperty(value = "二进制WKB数据")@TableField(value = "position",typeHandler = WKB2GeoJsonTypeHandler.class)@JsonRawValueprivate String position;@TableField("name")private String name;}
mybatis-plus配置添加转换器包路径,类似mybatis,之后用于写xml中sql
mybatis-plus:type-handlers-package: com.zjzy.mapper.typehandlerconfiguration:map-underscore-to-camel-case: trueauto-mapping-behavior: fulllog-impl: org.apache.ibatis.logging.stdout.StdOutImplmapper-locations: classpath*:mapper/**/*Mapper.xml
3.mybatis类型转换器转换geometry格式
因为缺少JDBC映射,数据库开始报错:‘类型为 geometry, 但表达式的类型为 character varying’
参考:Mybatis-plus读取和保存Postgis geometry数据 - 简书
应该是缺少JDBC-type类型。引入响应的postGIS驱动
添加maven包:
<!-- 这里会补充mybatis缺少的JDBC-Type如postGis中的geometry类型 --><dependency><groupId>net.postgis</groupId><artifactId>postgis-jdbc</artifactId><version>2.5.0</version></dependency>
类型转换器代码:
package com.zjzy.mapper.typehandler;import com.zjzy.mapper.CommonCodeMapper;
import com.zjzy.util.SpringContextUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import org.apache.ibatis.type.TypeHandler;
import org.geotools.geojson.geom.GeometryJSON;
import org.geotools.geometry.jts.WKBReader;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.io.ParseException;
import org.postgis.PGgeometry;import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Set;/*** @version 2.0* @description* @Author yaoct* @create 2021/12/22 16:19*/
@Slf4j
public class WKB2GeoJsonTypeHandler implements TypeHandler<String> {/*** 插入数据,转换,geoJson2EWKB* @param ps* @param i* @param parameter* @param jdbcType* @throws SQLException*/@Overridepublic void setParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
//EWKB是pg数据库自定义的类型,所以需要用数据库函数,插入数据库一般次数较少,这样并不会对数据库造成过大负担
// CommonCodeMapper mapper = SpringContextUtil.getBean(CommonCodeMapper.class);
// String EWKB = mapper.geo2EWKB(parameter);
// PGgeometry ewkb = new PGgeometry(EWKB);
// ps.setObject(i,ewkb);//通过geoTool转换WKBGeometryJSON geometryJson = new GeometryJSON(7);Geometry read = null;try {read = geometryJson.read(parameter);} catch (IOException e) {e.printStackTrace();}
// System.out.println(read.toString());read.setSRID(4326);
// GeometryJSON geometryJson = new GeometryJSON(7);WKBWriter wkbWriter = new WKBWriter(2, ByteOrderValues.BIG_ENDIAN,true);byte[] write = wkbWriter.write(read);String s1 = WKBWriter.toHex(write);PGgeometry ewkb = new PGgeometry(s1);ps.setObject(i,ewkb);}/*** 取出数据转换,WKB->Geojson* @param rs* @param columnName* @return* @throws SQLException*/@Overridepublic String getResult(ResultSet rs, String columnName) throws SQLException {String WKB = rs.getString(columnName);if(WKB==null){return null;}WKBReader reader = new WKBReader( );Geometry geometry = null;try {geometry = reader.read(WKBReader.hexToBytes(WKB));} catch (ParseException e) {//转换失败return null;}//转换成4326try {int srid = geometry.getSRID();CoordinateReferenceSystem sourceCRS = CRS.decode("EPSG:"+srid,true);CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:4326",true);MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS,true);geometry = JTS.transform(geometry, transform);} catch (Exception e) {e.printStackTrace();}// 设置保留6位小数,否则GeometryJSON默认保留4位小数GeometryJSON geometryJson = new GeometryJSON(7);return geometryJson.toString(geometry);}@Overridepublic String getResult(ResultSet rs, int columnIndex) throws SQLException {return null;}@Overridepublic String getResult(CallableStatement cs, int columnIndex) throws SQLException {return null;}
}
@Component
public class SpringContextUtil implements ApplicationContextAware {private static ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {SpringContextUtil.applicationContext = applicationContext;}//获取applicationContextpublic static ApplicationContext getApplicationContext() {return applicationContext;}//通过name获取 Bean.public static Object getBean(String name) {return getApplicationContext().getBean(name);}//通过class获取Bean.public static <T> T getBean(Class<T> clazz) {return getApplicationContext().getBean(clazz);}//通过name,以及Clazz返回指定的Beanpublic static <T> T getBean(String name, Class<T> clazz) {return getApplicationContext().getBean(name, clazz);}//关闭springbootpublic static void close(){((ConfigurableApplicationContext)(getApplicationContext())).close();}//得到当前线程的HttpServletResponse,可在静态方法中得到public static HttpServletResponse getHttpServletResponse(){return ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getResponse();}//得到当前线程的HttpServletRequest,可在静态方法中得到public static HttpServletRequest getHttpServletRequest(){return ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();}}
@Repository
public interface CommonCodeMapper extends BaseMapper<CommonCode> {/*** EWKB是pg数据库自定义的类型,所以需要用数据库函数* @param geoJson* @return*/@Select("select ST_GeomFromGeoJSON(#{geoJson})")String geo2EWKB(String geoJson);}
=============================mybatis中使用================================
在mapper类中使用示例:https://www.jianshu.com/p/6465189984b0
/*** 使用ResultMap */
@Results(id = "userMap", value = {//可以使用这种方式来处理字段名和数据库表字段名不一致的情况@Result(column = "username", property = "username", jdbcType=JdbcType.VARCHAR,typeHandler = WKB2GeoJsonTypeHandler.class),@Result(column = "passwd", property = "passwd", jdbcType=JdbcType.VARCHAR),@Result(column = "birth_day", property = "birthDay", jdbcType=JdbcType.VARCHAR)})
@Select("SELECT * FROM t_user WHERE id=#{id}")
User loadByIdResultMap(Long id);/*** 引用其他的Result */
@ResultMap("userMap")
@Select("SELECT * FROM t_user WHERE id=#{id}")
User loadByIdResultMapReference(Long id);
在xml中使用示例示例:
<resultMap id="locationResultMap" type="com.zjzy.model.po.ExaminationApplication"><result typeHandler="com.zjzy.mapper.typehandler.WKB2GeoJsonTypeHandler" column="dig_position" javaType="String"property="digPosition"/></resultMap><select id="selectExaminationApplicationByPage" resultMap="locationResultMap"></select>
注意:
1.postgresql的JDBC实现中(驱动),数据自定义的类型对应java类型一般都通过实现
org.postgresql.util.PGobject。
2.对应数据库geometry类型的java类不在PG的JDBC驱动的实现类中,因为geometry类型在PG的扩展postgis中,所以响应的要引入postGIS这部分的驱动,
3. PG的JDBC驱动底层也是通过SOCKET连接org.postgresql.core.PGStream#createSocket
4.原生jdbc接口在java.sql包中。
5.一定要实现org.postgresql.util.PGobject#getValue方法因为,org.postgresql.jdbc.PgPreparedStatement#setPGobject底层调用org.postgresql.jdbc.PgPreparedStatement#setString(int, java.lang.String, int)时
要用到org.postgresql.util.PGobject#getValue方法
==============================2022.12.12============================
以下方式不用导入 net.postgis包
package com.zjzy.mapper.typehandler;import com.alibaba.fastjson.JSONObject;
import com.zjzy.util.GisUtil;
import com.zjzy.util.SpringContextUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeHandler;
import org.geotools.geojson.geom.GeometryJSON;
import org.geotools.geometry.jts.JTS;
import org.geotools.geometry.jts.WKBReader;
import org.geotools.referencing.CRS;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.io.ByteOrderValues;
import org.locationtech.jts.io.ParseException;
import org.locationtech.jts.io.WKBWriter;
import org.locationtech.jts.io.WKTWriter;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
import org.postgis.PGbox2d;
import org.postgis.PGgeometry;
import org.postgresql.util.PGobject;
import org.springframework.core.env.Environment;import java.io.IOException;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;/*** @version 1.0* @description* @Author yaoct* @create 2021/12/22 16:19*/
@Slf4j
public class WKB2GeoJsonTypeHandler implements TypeHandler<String> {/*** 插入数据,转换,geoJson2EWKB* @param ps* @param i* @param parameter* @param jdbcType* @throws SQLException*/@Overridepublic void setParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {//EWKB是pg数据库自定义的类型,所以需要用数据库函数,插入数据库一般次数较少,这样并不会对数据库造成过大负担
// CommonCodeMapper mapper = SpringContextUtil.getBean(CommonCodeMapper.class);
// String EWKB = mapper.geo2EWKB(parameter);
// PGgeometry ewkb = new PGgeometry(EWKB);
// ps.setObject(i,ewkb);//通过geoTool转换WKBGeometryJSON geometryJson = new GeometryJSON(7);Geometry geometry = null;try {geometry = geometryJson.read(parameter);} catch (IOException e) {e.printStackTrace();}
// System.out.println(read.toString());geometry.setSRID(4326);
// GeometryJSON geometryJson = new GeometryJSON(7);//方式1.基于net.postgis
// WKBWriter wkbWriter = new WKBWriter(2, ByteOrderValues.BIG_ENDIAN,true);
// byte[] write = wkbWriter.write(geometry);
// String s1 = WKBWriter.toHex(write);
// PGgeometry ewkb = new PGgeometry(s1);//EWKB比WKB多了SRID头字符串,PGgeometry.toString()会自动添加SRID
// ps.setObject(i,ewkb);//方式2.设置ewkb,Postgresql驱动会先去数据库 pg_catalog.pg_type 查出geometry的类型id,这里的geometry字符串对应数据库pg_catalog.pg_type表中的geometry//以下方式不用导入net.postgis包
// PGobject pGobject = new PGobject();
// pGobject.setType("geometry");
// pGobject.setValue(s1);
// ps.setObject(i,pGobject);//方式3.设置拼接ewkt//以下方式不用导入net.postgis包,ewkb太长会超出sql限制,以下转换为ewktPGobject pGobject = new PGobject();pGobject.setType("geometry");String pre="SRID="+4326+";";pGobject.setValue(pre+GisUtil.Geometry2WKT(geometry));ps.setObject(i,pGobject);}/*** 取出数据转换,WKB->Geojson* @param rs* @param columnName* @return* @throws SQLException*/@Overridepublic String getResult(ResultSet rs, String columnName) throws SQLException {String WKB = rs.getString(columnName);if(WKB==null){return null;}WKBReader reader = new WKBReader( );Geometry geometry = null;try {geometry = reader.read(WKBReader.hexToBytes(WKB));} catch (ParseException e) {//转换失败return null;}//转换成4326try {int srid = geometry.getSRID();if(srid==0)srid=4549;//默认4549int targetSrid=4326;//默认4326Environment environment = SpringContextUtil.getBean(Environment.class);if(environment!=null){String sridTarget = environment.getProperty("sridTarget");if(sridTarget!=null){try {targetSrid=Integer.valueOf(sridTarget);} catch (Exception e){//转换失败}}}CoordinateReferenceSystem sourceCRS = CRS.decode("EPSG:"+srid,true);CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:"+targetSrid,true);MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS,true);geometry = JTS.transform(geometry, transform);} catch (Exception e) {e.printStackTrace();}// 设置保留6位小数,否则GeometryJSON默认保留4位小数GeometryJSON geometryJson = new GeometryJSON(7);String json = geometryJson.toString(geometry);JSONObject jsonObject = JSONObject.parseObject(json);jsonObject.put("srid",geometry.getSRID());return jsonObject.toJSONString();}@Overridepublic String getResult(ResultSet rs, int columnIndex) throws SQLException {return null;}@Overridepublic String getResult(CallableStatement cs, int columnIndex) throws SQLException {return null;}}
package com.zjzy.util;import org.geotools.geojson.geom.GeometryJSON;
import org.geotools.geometry.jts.JTS;
import org.geotools.geometry.jts.WKBReader;
import org.geotools.referencing.CRS;
import org.geotools.referencing.GeodeticCalculator;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.io.*;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;import java.io.IOException;/*** @Author yaoct* @Date 2022/9/16 10:55* @Version 1.0* @description*/
public class GisUtil {/*** WKB字符串转Geometry格式* @param WKB* @return*/public static Geometry WKB2Geometry(String WKB){WKBReader reader = new WKBReader();Geometry geometry = null;try {geometry = reader.read(WKBReader.hexToBytes(WKB));} catch (ParseException e) {//转换失败throw new RuntimeException("转换失败",e);}return geometry;}/*** Geometry格式转WKB字符串* @param geometry* @return*/public static String Geometry2WKB(Geometry geometry){WKBWriter wkbWriter = new WKBWriter(2, ByteOrderValues.BIG_ENDIAN,true);byte[] write = wkbWriter.write(geometry);String ret = WKBWriter.toHex(write);return ret;}/*** WKT字符串转Geometry格式* @param WKT* @return*/public static Geometry WKT2Geometry(String WKT){WKTReader reader = new WKTReader();Geometry geometry = null;try {geometry = reader.read(WKT);} catch (ParseException e) {//转换失败throw new RuntimeException("转换失败",e);}return geometry;}/*** Geometry格式转WKT字符串* @param geometry* @return*/public static String Geometry2WKT(Geometry geometry){WKTWriter wktWriter = new WKTWriter();String wkt= wktWriter.write(geometry);return wkt;}/*** 转换Geometry坐标* @param geometry* @param targetSrid 新坐标* @return*/public static Geometry coordinateTransfer(Geometry geometry, int targetSrid){int originSrid = geometry.getSRID();CoordinateReferenceSystem sourceCRS = null;CoordinateReferenceSystem targetCRS = null;MathTransform transform=null;try {sourceCRS = CRS.decode("EPSG:"+originSrid,true);targetCRS = CRS.decode("EPSG:"+targetSrid,true);transform = CRS.findMathTransform(sourceCRS, targetCRS,true);} catch (FactoryException e) {throw new RuntimeException("坐标错误",e);}Geometry ret = null;try {ret = JTS.transform(geometry, transform);} catch (TransformException e) {throw new RuntimeException("坐标转换错误",e);}return ret;}/*** Geometry->geoJson* @param geometry* @return*/public static String geometry2GeoJson(Geometry geometry){// 设置保留6位小数,否则GeometryJSON默认保留4位小数GeometryJSON geometryJson = new GeometryJSON(7);String json = geometryJson.toString(geometry);
// JSONObject jsonObject = JSONObject.parseObject(json);
// jsonObject.put("srid",geometry.getSRID());
// return jsonObject.toJSONString();return json;}/*** geoJson->Geometry* @param geoJson* @return*/public static Geometry geoJson2Geometry(String geoJson){GeometryJSON geometryJson = new GeometryJSON(7);Geometry ret=null;try {Geometry read = geometryJson.read(geoJson);} catch (IOException e) {throw new RuntimeException("转换失败",e);}return ret;}/*** 计算两点间的距离* @param lon1* @param lat1* @param lon2* @param lat2* @return*/public static double calculateDistance(double lon1,double lat1,double lon2,double lat2){//CoordinateReferenceSystem sourceCRS = CRS.decode("EPSG:"+srid,true);GeodeticCalculator geodeticCalculator = new GeodeticCalculator(DefaultGeographicCRS.WGS84);// 起点经纬度geodeticCalculator.setStartingGeographicPoint(lon1,lat1);// 末点经纬度geodeticCalculator.setDestinationGeographicPoint(lon2,lat2);// 计算距离,单位:米double distance = geodeticCalculator.getOrthodromicDistance();return distance;}
}
===================================================================
参考:
Mybatis-plus读取和保存Postgis geometry数据 - 简书
MyBatis Plus 自动类型转换之TypeHandler - 周世元ISO8859-1 - 博客园
GeoTools The Open Source Java GIS Toolkit — GeoTools
Geotools中Geometry对象与GeoJson的相互转换_mathyrs的博客-CSDN博客_geojson转geometry
mybatis 自定义TypeHandler映射Geometry空间几何数据 PGPoint (java +mybatis+ pgsql) - 灰信网(软件开发博客聚合)
Mybatis常用注解
mybatis类型转换器处理PostGis数据库geometry类型转换相关推荐
- Mybatis类型转换器使用
1.mybatis类型转换器,就是Java类型与数据库的类型之间转换的一个中介,由这个转换器可以对类型进行映射,mybatis对于基础类型都有默认类型转换器,你可以自定义类型转换器替代默认的转换器,大 ...
- 通过mybatis自定义参数类型转换器,进行数据库字段加密脱敏
1 问题背景 在数据库存储人员的信息时,有一些信息是敏感数据,如身份证号.出生地等.为了防止信息泄漏,这些信息不允许直接在数据库中查看,此时就需要对这些字段进行加密存储,但在页面查看的仍旧是解密后的数 ...
- mysql mybatis类型对应_Mybatis与数据库的类型对应
Mybatis与数据库的类型对应 由于业务的改变,在首次存入数据库时某些int属性并没有赋值,于是默认值就开始污染数据库了. java实体属性对应mysql和SQL Server 和Oracle 数据 ...
- spring 类型转换器_Spring中的类型转换
spring 类型转换器 以下是一些需要类型转换的简单情况: 情况1. 为了帮助简化bean配置,Spring支持属性值与文本值之间的转换. 每个属性编辑器仅设计用于某些类型的属性. 为了使用它们,我 ...
- Spring MVC Converter(类型转换器)详解
Spring MVC 框架的 Converter<S,T> 是一个可以将一种数据类型转换成另一种数据类型的接口,这里 S 表示源类型,T 表示目标类型.开发者在实际应用中使用框架内置的类型 ...
- SpringMVC-应用(数据绑定-自定义类型转换器,数据的格式化,数据校验)
一.提出问题 SpringMVC封装自定义类型对象的时候,JavaBean要和页面提交的数据一一绑定.下面要知道: 1)页面提交的数据都是字符串 2)JavaBean中的属性如:Integer age ...
- mybatis 自定义转换规则_Mybatis使用小技巧-自定义类型转换器
一般情况下,mybatis自带的类型转换器已经足够用了,但是需求永无止境,自定义类型转换器还是学一下吧,指不定哪天会用上. 举个没啥用的示例 javabean如下: public class User ...
- Mybatis中的类型转换器
无论是mybati是向数据库中存储数据还是将数据读取出来都需要涉及类型转换器. Mybatis再带的类型转换器:[部分] 自定义类型处理器 自定义类型转换器的解决方案: 重写已经有的类型转换器. 新建 ...
- 玩转Mybatis中的类型转换器TypeHandler
点击蓝色"程序猿DD"关注我 回复"资源"获取独家整理的学习资料! 抛开使用场景谈技术都是耍流氓 1. 场景 日常java开发中经常有这种需求,用0或者1这些代 ...
最新文章
- Jvm面试题及答案 100道(持续更新)
- cac会议投稿难度大吗_注册化工师考试难度大吗?
- UVA 1151	Buy or Build MST(最小生成树)
- 深度学习总结:GAN,原理,算法描述,pytoch实现
- vue 创建项目的命令
- 实例15:python
- package.json和bower的参数解释
- 【数据结构与算法基础】队列、栈、递归
- transact-sql_如何使用Transact-SQL创建,配置和删除SQL Server链接服务器
- 搞不明白为什么大家都在学习 k8s
- java相关的国际化步骤_Java语言资源国际化步骤
- 文件浏览器及数码相框 -2.3.2-freetype_arm-1
- java mavenpom_java-使用pom-packaging Maven项目作为依赖项
- ThinkSNS电商系统,带你玩转社群经济
- BZOJ 1208 HNOI 2004 宠物收养所 splay
- 【FPGA】DS18B20温度显示
- 2022阿里巴巴全球数学竞赛 第4题 虎虎生威(盲盒问题、集卡问题)解决思路
- 华为官方模拟器eNSP_B500高速网盘下载——带CE系统
- Python语言程序设计基础 第二版(嵩天著)课后答案第四章
- BNUZ程协技术部2020寒假任务简单版(后端)
热门文章
- ubuntu安装过程中提示: the path is not vaild path to the gcc binary等gcc路径不对和kernel不存在?
- Learning to Track at 100 FPS with Deep Regression Networks全文翻译
- 键盘按键名称及HID扫描码及VK虚拟键码对照表
- 计算机组装与系统安装实验目的,计算机原理与系统组装实验
- oracle数据删了怎么恢复吗,oracle误删数据恢复方法总结
- 4G LTE浪潮何时席卷全球?
- 阿里云推高校YY计划助推大学生创业潮
- 3年开发了5个私人项目:自动化办公、网站、机器人、小程序...免费开源,拿走不谢~
- 20170105资金净流入排行榜
- Mac下浏览器超实用快捷键