首页
归档
留言
友链
广告合作
壁纸
更多
美女主播
Search
1
博瑞GE车机升级/降级
5,649 阅读
2
Mac打印机设置黑白打印
5,043 阅读
3
修改elementUI中el-table树形结构图标
4,946 阅读
4
Mac客户端添加腾讯企业邮箱方法
4,705 阅读
5
intelliJ Idea 2022.2.X破解
4,459 阅读
后端开发
HarmonyOS Next
Web前端
微信开发
开发辅助
App开发
数据库
随笔日记
登录
/
注册
Search
标签搜索
Spring Boot
Java
Vue
Mac
Spring Cloud
MyBatis
WordPress
MacOS
asp.net
Element UI
Nacos
MySQL
.Net
Spring Cloud Alibaba
Mybatis-Plus
Typecho
jQuery
Java Script
IntelliJ IDEA
微信小程序
Laughing
累计撰写
629
篇文章
累计收到
1,421
条评论
首页
栏目
后端开发
HarmonyOS Next
Web前端
微信开发
开发辅助
App开发
数据库
随笔日记
页面
归档
留言
友链
广告合作
壁纸
美女主播
搜索到
629
篇与
的结果
2021-04-22
微信小程序自定义不一样的tabBar
实现过程其中扫码买单,这个按钮效果,微信自带的tabBar是无法实现的,其后尝试了下custom-tab-bar 也是无法实现。没办法了,既然微信的tabBar无法实现。那就自己弄个真-自定义tabBar来实现好了。各位看官莫慌,下面就把解决方案放上来。首先先来讲下解决方案的思路,然后再把代码送上。思路:微信的tabBar无法实现,那么就放弃微信的tabBar,改用Component 来实现。把微信自带的tabBar隐藏起来,用Component 做成伪tabBar并应该到页面上。把app.json下的 tabBar 给干掉。这样在首页就不会有tabBar显示了。写Component 伪tabBar并应该到页面上。代码app.json删除 tabBar自定义component<!--Componet/tabBar/tabBar.wxml--> <view class="tabBar"> <view class="cont"> <block wx:for="{{tabBar}}" wx:for-item="item" wx:key="tabBar"> <view class="item {{item.switchQr?'switchQr':''}}" catchtap="{{!item.switchQr?'goToTab':'switchQr'}}" data-url="{{item.pagePath}}" data-index="{{index}}"> <image class="ico" src="{{idx === index ? item.selectedIconPath : item.iconPath}}"></image> <view class="txt {{idx === index ? 'selectedColor' : ''}}">{{item.text}} </view> </view> </block> </view> </view>// Componet/tabBar/tabBar.js Component({ /** * 组件的属性列表 */ properties: { idx: { type: Number, value: 0 }, }, /** * 组件的初始数据 */ data: { tabBar: [{ "pagePath": "../../pages/index/index", "text": "首页", "switchQr": false, "iconPath": "/image/home.svg", "selectedIconPath": "/image/home_sel.svg", }, { "pagePath": "", "text": "扫码买单", "switchQr": true, "iconPath": "/image/saoma.svg", }, { "pagePath": "../../pages/user/user", "text": "我的", "switchQr": false, "iconPath": "/image/mine.svg", "selectedIconPath": "/image/mine_sel.svg", }, ] }, /** * 组件的方法列表 */ methods: { goToTab: function (e) { //如果点击当前页面则不进行跳转 if (this.data.idx == e.currentTarget.dataset.index) { return false } wx.navigateTo({ url: e.currentTarget.dataset.url }) }, // 扫码 switchQr() { // console.log('扫码') }, } })/* Componet/tabBar/tabBar.wxss */ .tabBar { width: 100%; position: fixed; bottom: 0; font-size: 20rpx; color: #8A8A8A; background: #fff; /* border-top: 2rpx solid #eee; */ box-shadow: 0rpx 1rpx 6rpx rgba(0,0,0,0.3); } .cont { margin-top: 10rpx; padding: 0; z-index: 0; height: calc(100rpx + env(safe-area-inset-bottom) / 2); padding-bottom: calc(env(safe-area-inset-bottom) / 2); display: flex; } .cont .item { font-size: 24rpx; position: relative; flex: 1; text-align: center; padding: 0; display: block; height: auto; line-height: 1; margin: 0; background-color: inherit; overflow: initial; justify-content: center; align-items: center; } .cont .item .ico { width: 46rpx; height: 46rpx; margin: auto } .cont .item .txt{ margin-top: 8rpx; color: #333; } .cont .switchQr .ico { position: absolute; width: 106rpx !important; z-index: 2; height: 106rpx !important; border-radius: 50%; font-size: 50rpx; top: -50rpx; left: 0; right: 0; margin: auto; padding: 0; } .cont .switchQr .txt{ margin-top: 56rpx; } .cont .item .selectedColor{ color: #ff4e4e; }使用在index/user的页面上应用。要在index.json/user.json文件引用component"usingComponents": { "tabBar":"/Componet/tabBar/tabBar" },在页面的引用component <!-- index.wxml --> <tabBar idx="0"></tabBar> <!--user.wxml --> <tabBar idx="2"></tabBar>
2021年04月22日
1,458 阅读
0 评论
24 点赞
2021-04-22
mybatis-plus基于p6spy执行 SQL 分析打印
书接上文,MyBatis-Plus简易使用教程该功能依赖 p6spy 组件,完美的输出打印 SQL 及执行时长 3.1.0 以上版本。添加p6spy依赖<!--输出打印sql--> <dependency> <groupId>p6spy</groupId> <artifactId>p6spy</artifactId> <version>3.8.7</version> </dependency>配置数据库驱动spring: datasource: url: jdbc:p6spy:mysql://localhost:3306/mybatisplus username: root password: 123456 driver-class-name: com.p6spy.engine.spy.P6SpyDriver配置p6spy在resources文件夹下增加spy.properties文件,内容如下#3.2.1以上使用 modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory #3.2.1以下使用或者不配置 #modulelist=com.p6spy.engine.logging.P6LogFactory,com.p6spy.engine.outage.P6OutageFactory # 自定义日志打印 logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger #日志输出到控制台 appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger # 使用日志系统记录 sql #appender=com.p6spy.engine.spy.appender.Slf4JLogger # 设置 p6spy driver 代理 deregisterdrivers=true # 取消JDBC URL前缀 useprefix=true # 配置记录 Log 例外,可去掉的结果集有error,info,batch,debug,statement,commit,rollback,result,resultset. excludecategories=info,debug,result,commit,resultset # 日期格式 dateformat=yyyy-MM-dd HH:mm:ss # 实际驱动可多个 #driverlist=org.h2.Driver # 是否开启慢SQL记录 outagedetection=true # 慢SQL记录标准 2 秒 outagedetectioninterval=2测试重启应用,在控制台可以查看执行的sql信息
2021年04月22日
1,529 阅读
0 评论
0 点赞
2021-04-22
mybatis-plus基于行级别的多租户实现
什么是多租户多租户技术或称多重租赁技术,简称SaaS,是一种软件架构技术,是实现如何在多用户环境下(多用户一般是面向企业用户)共用相同的系统或程序组件,并且可确保各用户间数据的隔离性。简单讲:在一台服务器上运行单个应用实例,它为多个租户(客户)提供服务。从定义中我们可以理解:多租户是一种架构,目的是为了让多用户环境下使用同一套程序,且保证用户间数据隔离。那么重点就很浅显易懂了,多租户的重点就是同一套程序下实现多用户数据的隔离。多租户架构以及数据隔离方案方案一:独立数据库即一个租户一个数据库,这种方案的用户数据隔离级别最高,安全性最好,但成本较高。优点:为不同的租户提供独立的数据库,有助于简化数据模型的扩展设计,满足不同租户的独特需求;如果出现故障,恢复数据比较简单。缺点:增多了数据库的安装数量,随之带来维护成本和购置成本的增加。方案二:共享数据库,独立 Schema也就是说 共同使用一个数据库 使用表进行数据隔离多个或所有租户共享Database,但是每个租户一个Schema(也可叫做一个user)。底层库比如是:DB2、ORACLE等,一个数据库下可以有多个SCHEMA。优点:为安全性要求较高的租户提供了一定程度的逻辑数据隔离,并不是完全隔离;每个数据库可支持更多的租户数量。缺点:如果出现故障,数据恢复比较困难,因为恢复数据库将牵涉到其他租户的数据;方案三:共享数据库,共享 Schema,共享数据表也就是说 共同使用一个数据库一个表 使用字段进行数据隔离即租户共享同一个Database、同一个Schema,但在表中增加TenantID多租户的数据字段。这是共享程度最高、隔离级别最低的模式。简单来讲,即每插入一条数据时都需要有一个客户的标识。这样才能在同一张表中区分出不同客户的数据,这也是我们系统目前用到的(tenant_id)优点:三种方案比较,第三种方案的维护和购置成本最低,允许每个数据库支持的租户数量最多。缺点:隔离级别最低,安全性最低,需要在设计开发时加大对安全的开发量;数据备份和恢复最困难,需要逐表逐条备份和还原。基于行级别的隔离本文基于方案三:共享数据库,共享 Schema,共享数据表进行说明。关于MyBatis-Plus的基础配置,可以参考MyBatis-Plus简易使用教程使用表结构create table user ( id bigint auto_increment comment '主键ID' primary key, name varchar(30) null comment '姓名', age int null comment '年龄', email varchar(50) null comment '邮箱', del_flag char default 'N' null, tenant_id bigint null comment '租户' );预置数据INSERT INTO user (id, name, age, email, del_flag, tenant_id) VALUES (1, 'Jone', 18, 'test1@baomidou.com', 'Y', 1); INSERT INTO user (id, name, age, email, del_flag, tenant_id) VALUES (2, 'Jack', 20, 'test2@baomidou.com', 'N', 2); INSERT INTO user (id, name, age, email, del_flag, tenant_id) VALUES (3, 'Tom', 28, 'test3@baomidou.com', 'N', 1); INSERT INTO user (id, name, age, email, del_flag, tenant_id) VALUES (4, 'Sandy', 21, 'test4@baomidou.com', 'N', 2); INSERT INTO user (id, name, age, email, del_flag, tenant_id) VALUES (5, 'Billie', 24, 'test5@baomidou.com', 'N', 1);mybatis-plus配置在mybatis-plus配置类中,定义拦截器,并加入租户相关拦截器TenantLineInnerInterceptor@Configuration public class MybatisPlusConfig { // 最新版 @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); TenantLineHandler tenantLineHandler = new TenantLineHandler() { @Override public Expression getTenantId() { return new LongValue(1); } @Override public String getTenantIdColumn() { return "tenant_id"; } @Override public boolean ignoreTable(String tableName) { return false; } }; interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(tenantLineHandler)); return interceptor; } @Bean public ConfigurationCustomizer configurationCustomizer() { return configuration -> configuration.setUseDeprecatedExecutor(false); } }测试1.基于mybatis-plus的CRUD操作@GetMapping("list") public List<User> list(){ return userService.list(); }2.自定义sql测试UserMapper.java/** * 租户的查询 * @return */ List<User> selectUserTenant();UserMapper.xml<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="cc.lisen.mybatisplussample.mapper.UserMapper"> <resultMap id="BaseResultMap" type="cc.lisen.mybatisplussample.domain.User"> <!--@Table `user`--> <id column="id" jdbcType="BIGINT" property="id"/> <result column="name" jdbcType="VARCHAR" property="name"/> <result column="age" jdbcType="INTEGER" property="age"/> <result column="email" jdbcType="VARCHAR" property="email"/> </resultMap> <sql id="Base_Column_List"> id, `name`, age, email </sql> <select id="selectUserList" resultMap="BaseResultMap"> select <include refid="Base_Column_List"/> from user </select> <select id="selectUserTenant" resultMap="BaseResultMap"> select <include refid="Base_Column_List"/> from user </select> </mapper>@GetMapping(value = "listTenant") public List<User> listTenant() { return userService.selectUserTenant(); }3.增加数据@GetMapping("add") public Boolean addUser() { User user = new User(); user.setName("张三"); user.setAge(30); return userService.save(user); }
2021年04月22日
1,637 阅读
0 评论
0 点赞
2021-04-22
MyBatis-Plus逻辑删除
逻辑删除::: tip 说明:只对自动注入的sql起效:插入: 不作限制查找: 追加where条件过滤掉已删除数据,且使用 wrapper.entity 生成的where条件会忽略该字段更新: 追加where条件防止更新到已删除数据,且使用 wrapper.entity 生成的where条件会忽略该字段删除: 转变为 更新例如:删除: update user set deleted=1 where id = 1 and deleted=0查找: select id,name,deleted from user where deleted=0字段类型支持说明:支持所有数据类型(推荐使用 Integer,Boolean,LocalDateTime)如果数据库字段使用datetime,逻辑未删除值和已删除值支持配置为字符串null,另一个值支持配置为函数来获取值如now()附录:逻辑删除是为了方便数据恢复和保护数据本身价值等等的一种方案,但实际就是删除。如果你需要频繁查出来看就不应使用逻辑删除,而是以一个状态去表示。使用方法:步骤1: MySql表结构create table if not exists user ( id bigint not null comment '主键ID' primary key, name varchar(30) null comment '姓名', age int null comment '年龄', email varchar(50) null comment '邮箱', del_flag char default 'N' null );步骤2: 预置数据INSERT INTO user (id, name, age, email, del_flag) VALUES (1, 'Jone', 18, 'test1@baomidou.com', 'Y'); INSERT INTO user (id, name, age, email, del_flag) VALUES (2, 'Jack', 20, 'test2@baomidou.com', 'N'); INSERT INTO user (id, name, age, email, del_flag) VALUES (3, 'Tom', 28, 'test3@baomidou.com', 'N'); INSERT INTO user (id, name, age, email, del_flag) VALUES (4, 'Sandy', 21, 'test4@baomidou.com', 'N'); INSERT INTO user (id, name, age, email, del_flag) VALUES (5, 'Billie', 24, 'test5@baomidou.com', 'N');步骤3: 配置com.baomidou.mybatisplus.core.config.GlobalConfig.DbConfig例: application.ymlmybatis-plus: global-config: db-config: logic-delete-field: del_flag # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2) logic-delete-value: 'Y' # 逻辑已删除值(默认为 1) logic-not-delete-value: 'N' # 逻辑未删除值(默认为 0)步骤4: 实体类字段上加上@TableLogic注解@Data @TableName(value = "`user`") public class User implements Serializable { /** * 主键ID */ @TableId(value = "id", type = IdType.AUTO) private Long id; /** * 姓名 */ @TableField(value = "`name`") private String name; /** * 年龄 */ @TableField(value = "age") private Integer age; /** * 邮箱 */ @TableField(value = "email") private String email; /** * 逻辑删除字段 */ @TableField(value = "del_flag") @TableLogic private String delFlag; private static final long serialVersionUID = 1L; public static final String COL_ID = "id"; public static final String COL_NAME = "name"; public static final String COL_AGE = "age"; public static final String COL_EMAIL = "email"; }步骤4: 测试@GetMapping("logicdelete/{id}") public Boolean logicdelete(@PathVariable("id") Long id){ return userService.removeById(id); }常见问题:1. 如何 insert ?字段在数据库定义默认值(推荐)insert 前自己 set 值使用自动填充功能2. 删除接口自动填充功能失效使用 update 方法并: UpdateWrapper.set(column, value)(推荐)使用 update 方法并: UpdateWrapper.setSql("column=value")使用Sql注入器注入com.baomidou.mybatisplus.extension.injector.methods.LogicDeleteByIdWithFill并使用(推荐)
2021年04月22日
2,819 阅读
0 评论
1 点赞
2021-04-22
MyBatis-Plus简易使用教程
添加依赖添加MyBatis-plus依赖 <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.2</version> </dependency>配置初始化数据库演示SQL脚本如下CREATE TABLE user ( id BIGINT(20) NOT NULL COMMENT '主键ID', name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名', age INT(11) NULL DEFAULT NULL COMMENT '年龄', email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱', PRIMARY KEY (id) )INSERT INTO user (id, name, age, email) VALUES (1, 'Jone', 18, 'test1@baomidou.com'), (2, 'Jack', 20, 'test2@baomidou.com'), (3, 'Tom', 28, 'test3@baomidou.com'), (4, 'Sandy', 21, 'test4@baomidou.com'), (5, 'Billie', 24, 'test5@baomidou.com');配置数据库连接在 application.yml 配置文件中添加 MySql 数据库的相关配置。spring: datasource: url: jdbc:mysql://localhost:3306/mybatisplus username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver在 Spring Boot 启动类中添加 @MapperScan 注解,扫描 Mapper 文件夹@SpringBootApplication @MapperScan("cc.lisen.mybatisplussample.mapper") public class MyBatisPlusSampleApplication { public static void main(String[] args) { SpringApplication.run(MyBatisPlusSampleApplication.class, args); } }快速开始编写实体类 User.java@Data @TableName(value = "`user`") public class User implements Serializable { /** * 主键ID */ @TableId(value = "id", type = IdType.AUTO) private Long id; /** * 姓名 */ @TableField(value = "`name`") private String name; /** * 年龄 */ @TableField(value = "age") private Integer age; /** * 邮箱 */ @TableField(value = "email") private String email; private static final long serialVersionUID = 1L; public static final String COL_ID = "id"; public static final String COL_NAME = "name"; public static final String COL_AGE = "age"; public static final String COL_EMAIL = "email"; }编写mapper类UserMapper.javapublic interface UserMapper extends BaseMapper<User> { }编写service类IUserService.javapublic interface IUserService extends IService<User>{ }编写impl类UserServiceImpl.java@Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService { }编写controller类UserController.java@RestController @RequestMapping("user") public class UserController { @Resource private IUserService userService; @GetMapping("list") public List<User> list(){ return userService.list(); } }MyBatis-Plus常见注解@TableName描述:表名注解属性类型必须指定默认值描述valueString否""表名schemaString否""schemakeepGlobalPrefixboolean否false是否保持使用全局的 tablePrefix 的值(如果设置了全局 tablePrefix 且自行设置了 value 的值)resultMapString否""xml 中 resultMap 的 idautoResultMapboolean否false是否自动构建 resultMap 并使用(如果设置 resultMap 则不会进行 resultMap 的自动构建并注入)excludePropertyString[]否{}需要排除的属性名(@since 3.3.1)@TableId描述:主键注解属性类型必须指定默认值描述valueString否""主键字段名typeEnum否IdType.NONE主键类型IdType值描述AUTO数据库ID自增NONE无状态,该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT)INPUTinsert前自行set主键值ASSIGN_ID分配ID(主键类型为Number(Long和Integer)或String)(since 3.3.0),使用接口IdentifierGenerator的方法nextId(默认实现类为DefaultIdentifierGenerator雪花算法)ASSIGN_UUID分配UUID,主键类型为String(since 3.3.0),使用接口IdentifierGenerator的方法nextUUID(默认default方法)ID_WORKER分布式全局唯一ID 长整型类型(please use ASSIGN_ID)UUID32位UUID字符串(please use ASSIGN_UUID)ID_WORKER_STR分布式全局唯一ID 字符串类型(please use ASSIGN_ID)@TableField描述:字段注解(非主键)属性类型必须指定默认值描述valueString否""数据库字段名elString否""映射为原生 #{ ... } 逻辑,相当于写在 xml 里的 #{ ... } 部分existboolean否true是否为数据库表字段@TableLogic描述:表字段逻辑处理注解(逻辑删除)属性类型必须指定默认值描述valueString否""逻辑未删除值delvalString否""逻辑删除值CRUD接口Service CRUD 接口说明:通用 Service CRUD 封装IService接口,进一步封装 CRUD 采用 get 查询单行 remove 删除 list 查询集合 page 分页 前缀命名方式区分 Mapper 层避免混淆,泛型 T 为任意实体对象建议如果存在自定义通用 Service 方法的可能,请创建自己的 IBaseService 继承 Mybatis-Plus 提供的基类对象 Wrapper 为 条件构造器Save// 插入一条记录(选择字段,策略插入) boolean save(T entity); // 插入(批量) boolean saveBatch(Collection<T> entityList); // 插入(批量) boolean saveBatch(Collection<T> entityList, int batchSize);参数说明类型参数名描述Tentity实体对象CollectionentityList实体对象集合intbatchSize插入批次数量SaveOrUpdate// TableId 注解存在更新记录,否插入一条记录 boolean saveOrUpdate(T entity); // 根据updateWrapper尝试更新,否继续执行saveOrUpdate(T)方法 boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper); // 批量修改插入 boolean saveOrUpdateBatch(Collection<T> entityList); // 批量修改插入 boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize);参数说明类型参数名描述Tentity实体对象WrapperupdateWrapper实体对象封装操作类 UpdateWrapperCollectionentityList实体对象集合intbatchSize插入批次数量Remove// 根据 entity 条件,删除记录 boolean remove(Wrapper<T> queryWrapper); // 根据 ID 删除 boolean removeById(Serializable id); // 根据 columnMap 条件,删除记录 boolean removeByMap(Map<String, Object> columnMap); // 删除(根据ID 批量删除) boolean removeByIds(Collection<? extends Serializable> idList);参数说明类型参数名描述WrapperqueryWrapper实体包装类 QueryWrapperSerializableid主键IDMap<String, Object>columnMap表字段 map 对象Collection<? extends Serializable>idList主键ID列表Update// 根据 UpdateWrapper 条件,更新记录 需要设置sqlset boolean update(Wrapper<T> updateWrapper); // 根据 whereEntity 条件,更新记录 boolean update(T entity, Wrapper<T> updateWrapper); // 根据 ID 选择修改 boolean updateById(T entity); // 根据ID 批量更新 boolean updateBatchById(Collection<T> entityList); // 根据ID 批量更新 boolean updateBatchById(Collection<T> entityList, int batchSize);参数说明类型参数名描述WrapperupdateWrapper实体对象封装操作类 UpdateWrapperTentity实体对象CollectionentityList实体对象集合intbatchSize更新批次数量Get// 根据 ID 查询 T getById(Serializable id); // 根据 Wrapper,查询一条记录。结果集,如果是多个会抛出异常,随机取一条加上限制条件 wrapper.last("LIMIT 1") T getOne(Wrapper<T> queryWrapper); // 根据 Wrapper,查询一条记录 T getOne(Wrapper<T> queryWrapper, boolean throwEx); // 根据 Wrapper,查询一条记录 Map<String, Object> getMap(Wrapper<T> queryWrapper); // 根据 Wrapper,查询一条记录 <V> V getObj(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);参数说明类型参数名描述Serializableid主键IDWrapperqueryWrapper实体对象封装操作类 QueryWrapperbooleanthrowEx有多个 result 是否抛出异常Tentity实体对象Function<? super Object, V>mapper转换函数List// 查询所有 List<T> list(); // 查询列表 List<T> list(Wrapper<T> queryWrapper); // 查询(根据ID 批量查询) Collection<T> listByIds(Collection<? extends Serializable> idList); // 查询(根据 columnMap 条件) Collection<T> listByMap(Map<String, Object> columnMap); // 查询所有列表 List<Map<String, Object>> listMaps(); // 查询列表 List<Map<String, Object>> listMaps(Wrapper<T> queryWrapper); // 查询全部记录 List<Object> listObjs(); // 查询全部记录 <V> List<V> listObjs(Function<? super Object, V> mapper); // 根据 Wrapper 条件,查询全部记录 List<Object> listObjs(Wrapper<T> queryWrapper); // 根据 Wrapper 条件,查询全部记录 <V> List<V> listObjs(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);参数说明类型参数名描述WrapperqueryWrapper实体对象封装操作类 QueryWrapperCollection<? extends Serializable>idList主键ID列表Map<?String, Object>columnMap表字段 map 对象Function<? super Object, V>mapper转换函数Page// 无条件分页查询 IPage<T> page(IPage<T> page); // 条件分页查询 IPage<T> page(IPage<T> page, Wrapper<T> queryWrapper); // 无条件分页查询 IPage<Map<String, Object>> pageMaps(IPage<T> page); // 条件分页查询 IPage<Map<String, Object>> pageMaps(IPage<T> page, Wrapper<T> queryWrapper);参数说明类型参数名描述IPagepage翻页对象WrapperqueryWrapper实体对象封装操作类 QueryWrapperCount// 查询总记录数 int count(); // 根据 Wrapper 条件,查询总记录数 int count(Wrapper<T> queryWrapper);参数说明类型参数名描述WrapperqueryWrapper实体对象封装操作类 QueryWrapperChainquery// 链式查询 普通 QueryChainWrapper<T> query(); // 链式查询 lambda 式。注意:不支持 Kotlin LambdaQueryChainWrapper<T> lambdaQuery(); // 示例: query().eq("column", value).one(); lambdaQuery().eq(Entity::getId, value).list();update// 链式更改 普通 UpdateChainWrapper<T> update(); // 链式更改 lambda 式。注意:不支持 Kotlin LambdaUpdateChainWrapper<T> lambdaUpdate(); // 示例: update().eq("column", value).remove(); lambdaUpdate().eq(Entity::getId, value).update(entity);Mapper CRUD 接口说明:通用 CRUD 封装BaseMapper接口,为 Mybatis-Plus 启动时自动解析实体表关系映射转换为 Mybatis 内部对象注入容器泛型 T 为任意实体对象参数 Serializable 为任意类型主键 Mybatis-Plus 不推荐使用复合主键约定每一张表都有自己的唯一 id 主键对象 Wrapper 为 条件构造器Insert// 插入一条记录 int insert(T entity);参数说明类型参数名描述Tentity实体对象Delete// 根据 entity 条件,删除记录 int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper); // 删除(根据ID 批量删除) int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList); // 根据 ID 删除 int deleteById(Serializable id); // 根据 columnMap 条件,删除记录 int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);参数说明类型参数名描述Wrapperwrapper实体对象封装操作类(可以为 null)Collection<? extends Serializable>idList主键ID列表(不能为 null 以及 empty)Serializableid主键IDMap<String, Object>columnMap表字段 map 对象Update// 根据 whereEntity 条件,更新记录 int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper); // 根据 ID 修改 int updateById(@Param(Constants.ENTITY) T entity);参数说明类型参数名描述Tentity实体对象 (set 条件值,可为 null)WrapperupdateWrapper实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)Select// 根据 ID 查询 T selectById(Serializable id); // 根据 entity 条件,查询一条记录 T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper); // 查询(根据ID 批量查询) List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList); // 根据 entity 条件,查询全部记录 List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper); // 查询(根据 columnMap 条件) List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap); // 根据 Wrapper 条件,查询全部记录 List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper); // 根据 Wrapper 条件,查询全部记录。注意: 只返回第一个字段的值 List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper); // 根据 entity 条件,查询全部记录(并翻页) IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper); // 根据 Wrapper 条件,查询全部记录(并翻页) IPage<Map<String, Object>> selectMapsPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper); // 根据 Wrapper 条件,查询总记录数 Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);参数说明类型参数名描述Serializableid主键IDWrapperqueryWrapper实体对象封装操作类(可以为 null)Collection<? extends Serializable>idList主键ID列表(不能为 null 以及 empty)Map<String, Object>columnMap表字段 map 对象IPagepage分页查询条件(可以为 RowBounds.DEFAULT)mapper 层 选装件说明:选装件位于 com.baomidou.mybatisplus.extension.injector.methods 包下 需要配合Sql 注入器使用,案例(opens new window)使用详细见AlwaysUpdateSomeColumnByIdint alwaysUpdateSomeColumnById(T entity);insertBatchSomeColumnint insertBatchSomeColumn(List<T> entityList);deleteByIdWithFillint deleteByIdWithFill(T entity);条件构造器说明:以下出现的第一个入参boolean condition表示该条件是否加入最后生成的sql中,例如:query.like(StringUtils.isNotBlank(name), Entity::getName, name) .eq(age!=null && age >= 0, Entity::getAge, age)以下代码块内的多个方法均为从上往下补全个别boolean类型的入参,默认为true以下出现的泛型Param均为Wrapper的子类实例(均具有AbstractWrapper的所有方法)以下方法在入参中出现的R为泛型,在普通wrapper中是String,在LambdaWrapper中是函数(例:Entity::getId,Entity为实体类,getId为字段id的getMethod)以下方法入参中的R column均表示数据库字段,当R具体类型为String时则为数据库字段名(字段名是数据库关键字的自己用转义符包裹!)。而不是实体类数据字段名!,另当R具体类型为SFunction时项目runtime不支持eclipse自家的编译器。以下举例均为使用普通wrapper,入参为Map和List的均以json形式表现!使用中如果入参的Map或者List为空,则不会加入最后生成的sql中!!!警告:不支持以及不赞成在 RPC 调用中把 Wrapper 进行传输wrapper 很重传输 wrapper 可以类比为你的 controller 用 map 接收值(开发一时爽,维护火葬场)正确的 RPC 调用姿势是写一个 DTO 进行传输,被调用方再根据 DTO 执行相应的操作AbstractWrapper说明:QueryWrapper(LambdaQueryWrapper) 和 UpdateWrapper(LambdaUpdateWrapper) 的父类,用于生成 sql 的 where 条件, entity 属性也用于生成 sql 的 where 条件。注意: entity 生成的 where 条件与 使用各个 api 生成的 where 条件没有任何关联行为allEqallEq(Map<R, V> params) allEq(Map<R, V> params, boolean null2IsNull) allEq(boolean condition, Map<R, V> params, boolean null2IsNull)全部eq或个别isNull个别参数说明:params : key为数据库字段名,value为字段值null2IsNull : 为true则在map的value为null时调用 isNull方法,为false时则忽略value为null的例1: allEq({id:1,name:"老王",age:null})--->id = 1 and name = '老王' and age is null例2: allEq({id:1,name:"老王",age:null}, false)--->id = 1 and name = '老王'allEq(BiPredicate<R, V> filter, Map<R, V> params) allEq(BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull) allEq(boolean condition, BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull) 个别参数说明:filter : 过滤函数,是否允许字段传入比对条件中params 与 null2IsNull : 同上例1: allEq((k,v) -> k.indexOf("a") >= 0, {id:1,name:"老王",age:null})--->name = '老王' and age is null例2: allEq((k,v) -> k.indexOf("a") >= 0, {id:1,name:"老王",age:null}, false)--->name = '老王'eqeq(R column, Object val) eq(boolean condition, R column, Object val)等于 =例: eq("name", "老王")--->name = '老王'nene(R column, Object val) ne(boolean condition, R column, Object val)不等于 <>例: ne("name", "老王")--->name <> '老王'gtgt(R column, Object val) gt(boolean condition, R column, Object val)大于 >例: gt("age", 18)--->age > 18gege(R column, Object val) ge(boolean condition, R column, Object val)大于等于 >=例: ge("age", 18)--->age >= 18ltlt(R column, Object val) lt(boolean condition, R column, Object val)小于 <例: lt("age", 18)--->age < 18lele(R column, Object val) le(boolean condition, R column, Object val)小于等于 <=例: le("age", 18)--->age <= 18betweenbetween(R column, Object val1, Object val2) between(boolean condition, R column, Object val1, Object val2)BETWEEN 值1 AND 值2例: between("age", 18, 30)--->age between 18 and 30notBetweennotBetween(R column, Object val1, Object val2) notBetween(boolean condition, R column, Object val1, Object val2)NOT BETWEEN 值1 AND 值2例: notBetween("age", 18, 30)--->age not between 18 and 30likelike(R column, Object val) like(boolean condition, R column, Object val)LIKE '%值%'例: like("name", "王")--->name like '%王%'notLikenotLike(R column, Object val) notLike(boolean condition, R column, Object val)NOT LIKE '%值%'例: notLike("name", "王")--->name not like '%王%'likeLeftlikeLeft(R column, Object val) likeLeft(boolean condition, R column, Object val)LIKE '%值'例: likeLeft("name", "王")--->name like '%王'likeRightlikeRight(R column, Object val) likeRight(boolean condition, R column, Object val)LIKE '值%'例: likeRight("name", "王")--->name like '王%'isNullisNull(R column) isNull(boolean condition, R column)字段 IS NULL例: isNull("name")--->name is nullisNotNullisNotNull(R column) isNotNull(boolean condition, R column)字段 IS NOT NULL例: isNotNull("name")--->name is not nullinin(R column, Collection<?> value) in(boolean condition, R column, Collection<?> value)字段 IN (value.get(0), value.get(1), ...)例: in("age",{1,2,3})--->age in (1,2,3)in(R column, Object... values) in(boolean condition, R column, Object... values)字段 IN (v0, v1, ...)例: in("age", 1, 2, 3)--->age in (1,2,3)notInnotIn(R column, Collection<?> value) notIn(boolean condition, R column, Collection<?> value)字段 NOT IN (value.get(0), value.get(1), ...)例: notIn("age",{1,2,3})--->age not in (1,2,3)notIn(R column, Object... values) notIn(boolean condition, R column, Object... values)字段 NOT IN (v0, v1, ...)例: notIn("age", 1, 2, 3)--->age not in (1,2,3)inSqlinSql(R column, String inValue) inSql(boolean condition, R column, String inValue)字段 IN ( sql语句 )例: inSql("age", "1,2,3,4,5,6")--->age in (1,2,3,4,5,6)例: inSql("id", "select id from table where id < 3")--->id in (select id from table where id < 3)notInSqlnotInSql(R column, String inValue) notInSql(boolean condition, R column, String inValue)字段 NOT IN ( sql语句 )例: notInSql("age", "1,2,3,4,5,6")--->age not in (1,2,3,4,5,6)例: notInSql("id", "select id from table where id < 3")--->id not in (select id from table where id < 3)groupBygroupBy(R... columns) groupBy(boolean condition, R... columns)分组:GROUP BY 字段, ...例: groupBy("id", "name")--->group by id,nameorderByAscorderByAsc(R... columns) orderByAsc(boolean condition, R... columns)排序:ORDER BY 字段, ... ASC例: orderByAsc("id", "name")--->order by id ASC,name ASCorderByDescorderByDesc(R... columns) orderByDesc(boolean condition, R... columns)排序:ORDER BY 字段, ... DESC例: orderByDesc("id", "name")--->order by id DESC,name DESCorderByorderBy(boolean condition, boolean isAsc, R... columns)排序:ORDER BY 字段, ...例: orderBy(true, true, "id", "name")--->order by id ASC,name ASChavinghaving(String sqlHaving, Object... params) having(boolean condition, String sqlHaving, Object... params)HAVING ( sql语句 )例: having("sum(age) > 10")--->having sum(age) > 10例: having("sum(age) > {0}", 11)--->having sum(age) > 11funcfunc(Consumer<Children> consumer) func(boolean condition, Consumer<Children> consumer)func 方法(主要方便在出现if...else下调用不同方法能不断链)例: func(i -> if(true) {i.eq("id", 1)} else {i.ne("id", 1)})oror() or(boolean condition)拼接 OR注意事项:主动调用or表示紧接着下一个方法不是用and连接!(不调用or则默认为使用and连接)例: eq("id",1).or().eq("name","老王")--->id = 1 or name = '老王'or(Consumer<Param> consumer) or(boolean condition, Consumer<Param> consumer)OR 嵌套例: or(i -> i.eq("name", "李白").ne("status", "活着"))--->or (name = '李白' and status <> '活着')andand(Consumer<Param> consumer) and(boolean condition, Consumer<Param> consumer)AND 嵌套例: and(i -> i.eq("name", "李白").ne("status", "活着"))--->and (name = '李白' and status <> '活着')nestednested(Consumer<Param> consumer) nested(boolean condition, Consumer<Param> consumer)正常嵌套 不带 AND 或者 OR例: nested(i -> i.eq("name", "李白").ne("status", "活着"))--->(name = '李白' and status <> '活着')applyapply(String applySql, Object... params) apply(boolean condition, String applySql, Object... params)拼接 sql注意事项:该方法可用于数据库函数 动态入参的params对应前面applySql内部的{index}部分.这样是不会有sql注入风险的,反之会有!例: apply("id = 1")--->id = 1例: apply("date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")--->date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")例: apply("date_format(dateColumn,'%Y-%m-%d') = {0}", "2008-08-08")--->date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")lastlast(String lastSql) last(boolean condition, String lastSql)无视优化规则直接拼接到 sql 的最后注意事项:只能调用一次,多次调用以最后一次为准 有sql注入的风险,请谨慎使用例: last("limit 1")existsexists(String existsSql) exists(boolean condition, String existsSql)拼接 EXISTS ( sql语句 )例: exists("select id from table where age = 1")--->exists (select id from table where age = 1)notExistsnotExists(String notExistsSql) notExists(boolean condition, String notExistsSql)拼接 NOT EXISTS ( sql语句 )例: notExists("select id from table where age = 1")--->not exists (select id from table where age = 1)QueryWrapper说明:继承自 AbstractWrapper ,自身的内部属性 entity 也用于生成 where 条件及 LambdaQueryWrapper, 可以通过 new QueryWrapper().lambda() 方法获取selectselect(String... sqlSelect) select(Predicate<TableFieldInfo> predicate) select(Class<T> entityClass, Predicate<TableFieldInfo> predicate)设置查询字段说明:以上方法分为两类.第二类方法为:过滤查询字段(主键除外),入参不包含 class 的调用前需要wrapper内的entity属性有值! 这两类方法重复调用以最后一次为准例: select("id", "name", "age")例: select(i -> i.getProperty().startsWith("test"))UpdateWrapper说明:继承自 AbstractWrapper ,自身的内部属性 entity 也用于生成 where 条件及 LambdaUpdateWrapper, 可以通过 new UpdateWrapper().lambda() 方法获取!setset(String column, Object val) set(boolean condition, String column, Object val)SQL SET 字段例: set("name", "老李头")例: set("name", "")--->数据库字段值变为空字符串例: set("name", null)--->数据库字段值变为nullsetSqlsetSql(String sql)设置 SET 部分 SQL例: setSql("name = '老李头'")lambda获取 LambdaWrapper在QueryWrapper中是获取LambdaQueryWrapper在UpdateWrapper中是获取LambdaUpdateWrapper使用 Wrapper 自定义SQL注意事项:需要mybatis-plus版本 >= 3.0.7 param 参数名要么叫ew,要么加上注解@Param(Constants.WRAPPER) 使用${ew.customSqlSegment} 不支持 Wrapper 内的entity生成where语句用注解@Select("select * from mysql_data ${ew.customSqlSegment}") List<MysqlData> getAll(@Param(Constants.WRAPPER) Wrapper wrapper);用XMLList<MysqlData> getAll(Wrapper ew); <select id="getAll" resultType="MysqlData"> SELECT * FROM mysql_data ${ew.customSqlSegment} </select>链式调用 lambda 式// 区分: // 链式调用 普通 UpdateChainWrapper<T> update(); // 链式调用 lambda 式。注意:不支持 Kotlin LambdaUpdateChainWrapper<T> lambdaUpdate(); // 等价示例: query().eq("id", value).one(); lambdaQuery().eq(Entity::getId, value).one(); // 等价示例: update().eq("id", value).remove(); lambdaUpdate().eq(Entity::getId, value).remove();分页插件配置依赖 <!-- 添加MyBatis-plus依赖--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.1</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus</artifactId> <version>3.4.1</version> </dependency>增加配置文件@Configuration public class MybatisPlusConfig { // 最新版 @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; } @Bean public ConfigurationCustomizer configurationCustomizer() { return configuration -> configuration.setUseDeprecatedExecutor(false); } }编写mapper类@Mapper public interface UserMapper extends BaseMapper<User> { /** * 分页查询 * * @param page 分页对象,xml中可以从里面进行取值,传递参数 Page 即自动分页,必须放在第一位(你可以继承Page实现自己的分页对象) * @return */ Page<User> selectUserList(IPage<User> page); }xml编写Sql<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="cc.lisen.mybatisplussample.mapper.UserMapper"> <resultMap id="BaseResultMap" type="cc.lisen.mybatisplussample.domain.User"> <!--@Table `user`--> <id column="id" jdbcType="BIGINT" property="id"/> <result column="name" jdbcType="VARCHAR" property="name"/> <result column="age" jdbcType="INTEGER" property="age"/> <result column="email" jdbcType="VARCHAR" property="email"/> </resultMap> <sql id="Base_Column_List"> id, `name`, age, email </sql> <select id="selectUserList" resultMap="BaseResultMap"> select <include refid="Base_Column_List"/> from user </select> </mapper>编写service类public interface IUserService extends IService<User>{ /** * 分页查询 * * @param page 分页对象,xml中可以从里面进行取值,传递参数 Page 即自动分页,必须放在第一位(你可以继承Page实现自己的分页对象) * @return */ Page<User> selectUserList(IPage<User> page); }编写impl类@Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService { @Resource UserMapper userMapper; /** * 分页查询 * * @param page 分页对象,xml中可以从里面进行取值,传递参数 Page 即自动分页,必须放在第一位(你可以继承Page实现自己的分页对象) * @return */ @Override public Page<User> selectUserList(IPage<User> page) { return userMapper.selectUserList(page); } }编写controller类@RestController @RequestMapping("user") public class UserController { @Resource private IUserService userService; @GetMapping("list") public List<User> list(){ return userService.list(); } @GetMapping("list1") public List<User> list1(){ QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.eq("id",1).or().eq("name","Tom"); return userService.list(queryWrapper); } @GetMapping("page") public Page<User> page(){ IPage<User> userPage = new Page<>(1,3); return userService.selectUserList(userPage); } }
2021年04月22日
1,265 阅读
0 评论
1 点赞
2021-04-17
酷我音乐车机版_v5.0.0.7_破解VIP版_共存版
专门为汽车所制作的一款音乐播放器,可以直接选择你的车型然后进行更改设置,另外拥有独特的蝰蛇音效,例如3d美音,不一样的环绕立体的声场,让在车上感受更嗨的氛围。 在超长距离行车的过程中可以很好的用音乐舒缓身心,激发活力。流畅的操作,合理的交互设计,更体现酷我以用户体验为中心的设计理念。 海量歌曲等你来听,全网歌曲同步更新。 还拥有个性换肤,超炫语音搜索及精准音频指纹识别等独特功能! 可以手动添加本地歌曲或专辑,酷我检测到曲库中有相同歌曲的无损版本,会自动用无损版本代替本地版本。 集成foobar的wasapi设备切换,独家改良成开关交互,使操作更方便。版本特点{lamp/}解锁vip会员收费歌曲在线任意听解锁版权专属歌曲在线任意听解锁已下架歌曲在线任务听解锁单曲购买歌曲在线听解锁vip会员标准、无损等任意下载解锁版权专属不可以下载/可以下载解锁不允许下载歌曲可以下载解锁专属单曲收费歌曲可下载解锁主播界面直接进入解锁汽车音效任意用解锁主题皮肤任意用修改播放本地歌曲默认图风格去启动音、去水印、去登录提示去永检测升级提示弹窗链接:https://pan.baidu.com/s/17998OuieowMWVBHNQkBkIQ 提取码:3esz
2021年04月17日
3,457 阅读
1 评论
2 点赞
2021-04-15
通过手机热点解决Gradle下载太慢
网上也搜了很多解决办法,但是基本都没啥效果,包括替换阿里云的镜像。只要把笔记本的无线网, 连接上手机热点即可,那个速度飞快~~!!!2021.4.15亲测很好用, 每次我都是用这招解决的!不知道为什么,但是我猜应该是手机网络不存在翻墙的因素吧。嘿嘿~~姑且不管什么原理,只要能解决问题的办法,就是好办法!!!
2021年04月15日
1,179 阅读
4 评论
25 点赞
2021-04-06
百度地图标记色块
<!DOCTYPE html> <html> <head> <meta name="viewport" content="initial-scale=1.0, user-scalable=no" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Hello, World</title> <style type="text/css"> html{height:100%} body{height:100%;margin:0px;padding:0px} #container{height:100%} </style> <script type="text/javascript" src="https://api.map.baidu.com/api?v=1.0&type=webgl&ak=OzWSumAeRHXvCB0aVy1NiIywdsxMhIGZ"> </script> </head> <body> <div id="container"></div> <script type="text/javascript"> var map = new BMapGL.Map("container"); // 创建地图实例 var point = new BMapGL.Point(117.164254,36.661088); // 创建点坐标 map.centerAndZoom(point, 18); map.enableScrollWheelZoom(true); //开启鼠标滚轮缩放 // 初始化地图,设置中心点坐标和地图级别 map.setMapType(BMAP_EARTH_MAP); // 设置地图类型为地球模式 var polygon = new BMapGL.Polygon([ new BMapGL.Point(117.163848,36.660984), new BMapGL.Point(117.164566,36.66126), new BMapGL.Point(117.164634,36.661155), new BMapGL.Point(117.163919,36.660876) ], {strokeColor:"blue", strokeWeight:2, strokeOpacity:1,fillColor:"red"}); map.addOverlay(polygon); </script> </body> </html>坐标点越多形状越精确。
2021年04月06日
1,207 阅读
0 评论
1 点赞
2021-03-16
Spring Boot 封装微信小程序工具类
/** * Description: 微信小程序工具类 * * @author : laughing * DateTime: 2021-03-16 11:10 */ @Slf4j public class WeChatUtils { public static String httpRequest(String requestUrl, String requestMethod, String output) { try { URL url = new URL(requestUrl); HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); connection.setDoOutput(true); connection.setDoInput(true); connection.setUseCaches(false); connection.setRequestMethod(requestMethod); if (null != output) { OutputStream outputStream = connection.getOutputStream(); outputStream.write(output.getBytes(StandardCharsets.UTF_8)); outputStream.close(); } // 从输入流读取返回内容 InputStream inputStream = connection.getInputStream(); InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); String str; StringBuilder buffer = new StringBuilder(); while ((str = bufferedReader.readLine()) != null) { buffer.append(str); } bufferedReader.close(); inputStreamReader.close(); inputStream.close(); connection.disconnect(); return buffer.toString(); } catch (Exception e) { e.printStackTrace(); } return ""; } public static String decryptData(String encryptDataB64, String sessionKeyB64, String ivB64) { log.info("encryptDataB64:" + encryptDataB64); log.info("sessionKeyB64:" + sessionKeyB64); log.info("ivB64:" + ivB64); return new String( decryptOfDiyIv( Base64.decode(encryptDataB64), Base64.decode(sessionKeyB64), Base64.decode(ivB64) ) ); } private static final String KEY_ALGORITHM = "AES"; private static final String ALGORITHM_STR = "AES/CBC/PKCS7Padding"; private static Key key; private static Cipher cipher; private static void init(byte[] keyBytes) { // 如果密钥不足16位,那么就补足. 这个if 中的内容很重要 int base = 16; if (keyBytes.length % base != 0) { int groups = keyBytes.length / base + 1; byte[] temp = new byte[groups * base]; Arrays.fill(temp, (byte) 0); System.arraycopy(keyBytes, 0, temp, 0, keyBytes.length); keyBytes = temp; } // 初始化 Security.addProvider(new BouncyCastleProvider()); // 转化成JAVA的密钥格式 key = new SecretKeySpec(keyBytes, KEY_ALGORITHM); try { // 初始化cipher cipher = Cipher.getInstance(ALGORITHM_STR, "BC"); } catch (Exception e) { e.printStackTrace(); } } /** * 解密方法 * * @param encryptedData 要解密的字符串 * @param keyBytes 解密密钥 * @param ivs 自定义对称解密算法初始向量 iv * @return 解密后的字节数组 */ private static byte[] decryptOfDiyIv(byte[] encryptedData, byte[] keyBytes, byte[] ivs) { byte[] encryptedText = null; init(keyBytes); try { cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(ivs)); encryptedText = cipher.doFinal(encryptedData); } catch (Exception e) { e.printStackTrace(); } return encryptedText; } /** * 向指定 URL 发送POST方法的请求 * * @param url 发送请求的 URL * @param json 请求参数,请求参数应该是 json 的形式。 * @return 所代表远程资源的响应结果 */ public static String httpPost(String url, JSONObject json) { PrintWriter out = null; BufferedReader in = null; String result = ""; try { URL realUrl = new URL(url); // 打开和URL之间的连接 URLConnection conn = realUrl.openConnection(); // 设置通用的请求属性 conn.setRequestProperty("accept", "*/*"); conn.setRequestProperty("connection", "Keep-Alive"); conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); // 发送POST请求必须设置如下两行 conn.setDoOutput(true); conn.setDoInput(true); // 获取URLConnection对象对应的输出流 out = new PrintWriter(conn.getOutputStream()); // 发送请求参数 out.print(json); // flush输出流的缓冲 out.flush(); // 定义BufferedReader输入流来读取URL的响应 in = new BufferedReader( new InputStreamReader(conn.getInputStream())); String line; while ((line = in.readLine()) != null) { result=result.concat(line); } } catch (Exception e) { System.out.println("发送 POST 请求出现异常!" + e); e.printStackTrace(); } //使用finally块来关闭输出流、输入流 finally { try { if (out != null) { out.close(); } if (in != null) { in.close(); } } catch (IOException ex) { ex.printStackTrace(); } } return result; }
2021年03月16日
934 阅读
0 评论
0 点赞
2021-02-21
Vue子组件的索引
在Vue中,当子组件较多时,通过this.$children来一一遍历我们需要的一个组件是比较困难的,尤其是组件动态渲染时,他们的序列是不固定的。Vue提供了子组件索引的方法,用特殊的属性ref为子组件指定一个索引的名字。<html> <head> <title>Vue学习</title> <script src="vue.js"></script> </head> <body> <div id="app"> <component-a ref="compA"></component-a> <button @click="handleMessage">获取组件A的内容</button> {{message}} </div> <script type="text/javascript"> Vue.component("component-a", { data: function () { return { message: '这是组件A的message' } }, template:'<div></div>' }) var app = new Vue({ el: '#app', data: { message: '' }, methods: { handleMessage: function () { this.message = this.$refs.compA.message } } }) </script> </body> </html>
2021年02月21日
1,103 阅读
0 评论
1 点赞
2021-02-21
Vue中文输入法实时更新数据值
使用v-model是,如果是用中文输入法输入中文,一般在没有选定词组前,也就是在拼音阶段,Vue是不会更新数据的,当敲下汉字时才会触发更新,如果希望总是实时更新,可以用@input来替代v-model。<html> <head> <title>Vue学习</title> <script src="vue.js"></script> </head> <body> <div id="app"> <input type="text" v-model="message" placeholder="请输入"> <input type="text" placeholder="实时更新" @input="handleInput"> <p> {{message}} </p> </div> <script type="text/javascript"> var app = new Vue({ el: '#app', data: { message: '' }, methods:{ handleInput:function(e){ this.message=e.target.value } } }) </script> </body> </html>
2021年02月21日
991 阅读
0 评论
0 点赞
2021-01-09
android EditText禁止键盘输入
最近在做项目,遇到一个需求,有一个文本框(EditText)存储重量信息,重量信息来源于蓝牙电子秤,所以禁止用户手工输入。如下图,回收物重量,能正常点击并出现光标,但是不会弹出软键盘实现定义一个常量类/** * Description: 反射方法名 * * @author : laughing * DateTime: 2021-01-07 13:11 */ public class ReflectMethodConstants { public static String SET_SHOW_SOFT_INPUT_ON_FOCUS = "setShowSoftInputOnFocus"; public static String SET_SOFT_INPUT_SHOWN_ON_FOCUS = "setSoftInputShownOnFocus"; }反射设置控件 //禁止弹出软键盘 Class<EditText> cls = EditText.class; Method method; try { method = cls.getMethod(ReflectMethodConstants.SET_SHOW_SOFT_INPUT_ON_FOCUS, boolean.class); method.setAccessible(true); method.invoke(viewHolder.textViewWeight, false); } catch (Exception ignored) { } try { method = cls.getMethod(ReflectMethodConstants.SET_SOFT_INPUT_SHOWN_ON_FOCUS, boolean.class); method.setAccessible(true); method.invoke(viewHolder.textViewWeight, false); } catch (Exception ignored) { } //禁止键盘输入 viewHolder.textViewWeight.setFilters(new InputFilter[]{ (source, start, end, dest, dStart, dEnd) -> { if (source.length() > 1) { return source; } return ""; } });
2021年01月09日
1,465 阅读
1 评论
3 点赞
1
...
29
30
31
...
53