首页
关于
Search
1
BT宝塔面板免费使用专业版网站监控报表插件
276 阅读
2
Python批量校验两个文件夹里面的文件MD5
180 阅读
3
MySQL创建索引
110 阅读
4
欢迎使用 Typecho
92 阅读
5
更改宝塔nginx默认的日志格式
92 阅读
默认分类
Java
SpringBoot
MySQL
Linux
登录
/
注册
Search
标签搜索
MySQL
Linux
JAVA
Docker
JavaScript
JDK
Redis
CentOS
SQL
SpringBoot
HTTP
Python
CDN
IP
前端
Micky
累计撰写
57
篇文章
累计收到
1
条评论
今日撰写
0
篇文章
首页
栏目
默认分类
Java
SpringBoot
MySQL
Linux
页面
关于
用户登录
登录
注册
搜索到
5
篇与
SpringBoot
的结果
2023-06-05
使用正则 替换MybatisPlus 自动生成的字段注解
@TableField(value = "sex") @TableField(value = "detailed_address") @TableField(value = "address") 使用正则 在生成的代码中 匹配上面的三条数据@TableField(values=s"(sex|detailed_address|address)")匹配全部@TableField(value = ".*?")解释:( 和 ) 匹配 ( 和 ),而 "(" 和 ")" 只匹配括号字符本身。value = " 匹配 value = " 字符串。.*? 匹配任意字符,非贪婪地尽可能少地匹配字符,直到下一个字符 "。" 匹配字符 "。注:如果要匹配字符串中有换行符的情况,需要加上 Pattern.DOTALL 标志,例如 Pattern.compile("@TableField\(value = ".*?"\)", Pattern.DOTALL)。
2023年06月05日
1 阅读
0 评论
0 点赞
2022-08-31
Java导出Word文档
Maven 加入如下坐标 <!--导出Docx--> <dependency> <groupId>com.deepoove</groupId> <artifactId>poi-tl</artifactId> <version>1.12.0</version> </dependency> <!--导出Docx-->建议使用最新版 https://github.com/Sayi/poi-tl/** * word工具类 * * @author CoderKK */ public class WordUtil { /** * 根据模板填充内容生成word,并下载 * * @param templatePath word模板文件路径 * @param paramMap 替换的参数集合 */ public static void downloadWord(OutputStream out, InputStream templatePath, Map<String, Object> paramMap, Configure config) throws Exception { /* // 生成本地文件 Long time = System.currentTimeMillis(); // 生成的word格式 String formatSuffix = ".docx"; // 拼接后的文件名 String fileName = time + formatSuffix; //设置生成的文件存放路径,可以存放在你想要指定的路径里面 String rootPath = "D:/tmp/" + File.separator + "file/word/"; String filePath = rootPath + fileName; File newFile = new File(filePath); //判断目标文件所在目录是否存在 if (!newFile.getParentFile().exists()) { //如果目标文件所在的目录不存在,则创建父目录 newFile.getParentFile().mkdirs(); } */ // 读取模板templatePath并将paramMap的内容填充进模板,即编辑模板(compile)+渲染数据(render) XWPFTemplate template = XWPFTemplate.compile(templatePath, config).render( paramMap); // 生成本地文件 //out = new FileOutputStream(filePath);//输出路径(下载到指定路径) // 将填充之后的模板写入filePath //将template写到OutputStream中 template.write(out); out.flush(); out.close(); template.close(); } /** * 远程文件url 转为输入流 * @param urlOrPath 远程文件url * @return * @throws Exception */ public static InputStream byteByUrl(String urlOrPath) throws Exception { URL url = new URL(urlOrPath); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); //设置超时间为3秒 conn.setConnectTimeout(3 * 1000); //防止屏蔽程序抓取而返回403错误 //conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)"); //得到输入流 return conn.getInputStream(); } }/** * WordController * @author CoderKK */ @RestController public class WordController { @GetMapping("/word-download") public void word(HttpServletResponse response) throws Exception { response.setContentType("application/octet-stream"); //设置文件名称 response.setHeader("Content-Disposition", "attachment;filename=" + System.currentTimeMillis() + ".docx"); //获取 resources 目录 本地&打Jar包都可用 路径前不需要加/ //InputStream inputStream = getClass().getClassLoader().getResourceAsStream("word/template.docx"); //路径前需要加/ 具体区别请看https://www.cnblogs.com/geek233/p/15817853.html InputStream inputStream = getClass().getResourceAsStream("/word/template.docx"); //获取远程文件 //InputStream inputStream = WordUtil.byteByUrl("https://blog.52ipc.top/word/template.docx"); // 创建用于插入数据的Map 实际开发要放在service层 Map<String, Object> paramMap = new HashMap<>(18); paramMap.put("title", "Hi, Word模板"); paramMap.put("uname", "小蜜蜂~"); List<Map<String,Object>> voList = new ArrayList<>(); for (int i = 0; i < 10; i++) { Map<String,Object> vo = new HashMap<>(); vo.put("areaId" , String.valueOf(i)); vo.put("name" , "北京"+ i); voList.add(vo); } paramMap.put("area", voList); // 循环行表渲染策略 LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy(); // 插件绑定 Configure config = Configure.builder() //area 变量名 //policy 策略 .bind("area", policy) .build(); WordUtil.downloadWord(response.getOutputStream(), inputStream, paramMap, config); } }word模板文件路径如下 模板文件下载链接 https://blog.52ipc.top/word/template.docx模板内容如下图
2022年08月31日
79 阅读
0 评论
0 点赞
2022-08-31
MybatisPlus拦截器打印完整SQL、分页、自动填充处理
MybatisPlus拦截器打印完整SQLMybatisPlus 虽然也自带了一个打印 SQL 的配置,但是不方便查看,也没有时间统计mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl拦截器PrintSqlInterceptor/** * @author CoderKK * @date 2020-09-01 00:13 */ @Slf4j @Intercepts({ @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}), @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})}) public class PrintSqlInterceptor implements Interceptor { @Override public Object intercept(Invocation invocation) throws Throwable { MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0]; Object parameter = null; if (invocation.getArgs().length > 1) { parameter = invocation.getArgs()[1]; } String sqlId = mappedStatement.getId(); BoundSql boundSql = mappedStatement.getBoundSql(parameter); Configuration configuration = mappedStatement.getConfiguration(); long start = System.currentTimeMillis(); Object returnValue = invocation.proceed(); long time = System.currentTimeMillis() - start; showSql(configuration, boundSql, time, sqlId); return returnValue; } private static void showSql(Configuration configuration, BoundSql boundSql, long time, String sqlId) { Object parameterObject = boundSql.getParameterObject(); List<ParameterMapping> parameterMappings = boundSql.getParameterMappings(); //替换空格、换行、tab缩进等 String sql = boundSql.getSql().replaceAll("[\\s]+", " "); if (parameterMappings.size() > 0 && parameterObject != null) { TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry(); if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) { sql = sql.replaceFirst("\\?", getParameterValue(parameterObject)); } else { MetaObject metaObject = configuration.newMetaObject(parameterObject); for (ParameterMapping parameterMapping : parameterMappings) { String propertyName = parameterMapping.getProperty(); if (metaObject.hasGetter(propertyName)) { Object obj = metaObject.getValue(propertyName); sql = sql.replaceFirst("\\?", getParameterValue(obj)); } else if (boundSql.hasAdditionalParameter(propertyName)) { Object obj = boundSql.getAdditionalParameter(propertyName); sql = sql.replaceFirst("\\?", getParameterValue(obj)); } } } } logs(time, sql, sqlId); } private static String getParameterValue(Object obj) { String value; if (obj instanceof String) { value = "'" + obj + "'"; } else if (obj instanceof Date) { DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.CHINA); value = "'" + formatter.format(new Date()) + "'"; } else { if (obj != null) { value = obj.toString(); } else { value = ""; } } return value.replace("$", "\\$"); } private static void logs(long time, String sql, String sqlId) { StringBuilder sb = new StringBuilder() .append(" Time:").append(time) .append(" ms - ID:").append(sqlId) .append(StringPool.NEWLINE).append("Execute SQL:") .append(sql).append(StringPool.NEWLINE); log.info(sb.toString()); } @Override public Object plugin(Object target) { return Plugin.wrap(target, this); } @Override public void setProperties(Properties properties0) { } }MybatisPlus配置 MybatisPlusConfigpackage com.example.demojs.config; import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.example.demojs.common.PrintSqlInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.Properties; @Configuration public class MybatisPlusConfig { /** * mybatis-plus分页插件 */ /* // 旧版 @Bean public PaginationInterceptor paginationInterceptor() { PaginationInterceptor paginationInterceptor = new PaginationInterceptor(); // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求 默认false // paginationInterceptor.setOverflow(false); // 设置最大单页限制数量,默认 500 条,-1 不受限制 // paginationInterceptor.setLimit(500); // 开启 count 的 join 优化,只针对部分 left join paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true)); return paginationInterceptor; } // 新版 @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; } // 如何区分新旧版呢?其实你把这两种代码都复制到你的项目里,哪个类存在就用哪个方法。 // 3.4.0版本对此部分有更新,如果是旧版本升级,会出现分页失效问题,同时idea会提示PaginationInterceptor过时,新版本改用了MybatisPlusInterceptor */ /** *自定义mybatis插件 注入方式一 */ /* @Bean public MybatisPlusInterceptor mybatisInterceptor() { MybatisPlusInterceptor mybatisInterceptor = new MybatisPlusInterceptor(); Properties properties = new Properties(); properties.setProperty("name", name); mybatisInterceptor.setProperties(properties); return mybatisInterceptor; } */ /** *自定义mybatis插件 注入方式二 */ @Bean public ConfigurationCustomizer configurationCustomizer() { return configuration -> { //插件拦截链采用了责任链模式,执行顺序和加入连接链的顺序有关 //MybatisInterceptor mybatisInterceptor = new MybatisInterceptor(); MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor(); //设置参数,比如阈值等,可以在配置文件中配置 Properties properties = new Properties(); //properties.setProperty("name", name); mybatisPlusInterceptor.setProperties(properties); //自定义打印SQL PrintSqlInterceptor printSqlInterceptor = new PrintSqlInterceptor(); configuration.addInterceptor(printSqlInterceptor); }; } /** * mybatis-plus SQL执行效率插件【生产环境可以关闭】 3.3.2版本移除了该功能,3.0.3和3.0.3之前版本支持。 */ /* @Bean public PerformanceInterceptor performanceInterceptor() { return new PerformanceInterceptor(); } */ }打印效果2022-08-29 16:42:03.782 INFO 17476 --- [nio-8080-exec-2] c.e.demojs.common.PrintSqlInterceptor : Time:397 ms - ID:com.example.demojs.dao.UserMapper.insert Execute SQL:INSERT INTO test_user ( id, user_id, phone, birthday, sex ) VALUES ( 1564171509361389569, 'abc', '13988776664', 2022-08-29T16:41:59.514, 1 )自动填充插件/** * @author CoderKK * @date 2020/9/6 15:21 * @desc 自动填充处理器类 */ @Component public class MyMetaObjectHandler implements MetaObjectHandler { /** * 插入时的填充策略 * * @param metaObject */ @Override public void insertFill(MetaObject metaObject) { this.setFieldValByName("createTime", LocalDateTime.now(), metaObject); this.setFieldValByName("updateTime", LocalDateTime.now(), metaObject); } /** * 更新时的填充策略 * * @param metaObject */ @Override public void updateFill(MetaObject metaObject) { this.setFieldValByName("updateTime", LocalDateTime.now(), metaObject); } } 实体类记得加注解 @TableField(value = "create_time", fill = FieldFill.INSERT) @JsonFormat(pattern = "yyyy-MM-dd HH:mm", timezone = "GMT+8") private LocalDateTime createTime; @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE) @JsonFormat(pattern = "yyyy-MM-dd HH:mm", timezone = "GMT+8") private LocalDateTime updateTime; 分页插件注入分页插件后,如何使用呢?mapper写法:// 这是mapper自己提供的方法,参数是wrapper 适用于单表查 <P extends IPage<T>> P selectPage(P page, @Param("ew") Wrapper<T> queryWrapper); // 自定义sql,适用于多表联查 IPage<UserVO> queryUserList(Page<UserVO> page, @Param("dto") ConditionDTO conditionDTO);**
2022年08月31日
58 阅读
0 评论
0 点赞
2021-11-05
实用!一键生成数据库文档
数据库文档图一、数据库支持[x] MySQL[x] MariaDB[x] TIDB[x] Oracle[x] SqlServer[x] PostgreSQL[x] Cache DB二、配置1、pom文件引入screw核心包,HikariCP数据库连接池,HikariCP号称性能最出色的数据库连接池。 <!-- screw核心 --> <dependency> <groupId>cn.smallbun.screw</groupId> <artifactId>screw-core</artifactId> <version>1.0.3</version> </dependency> <!-- HikariCP --> <dependency> <groupId>com.zaxxer</groupId> <artifactId>HikariCP</artifactId> <version>3.4.5</version> </dependency> <!--mysql driver--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.20</version> </dependency>2、配置数据源配置数据源,设置 useInformationSchema 可以获取tables注释信息。spring.datasource.url=jdbc:mysql://45.93.1.5:3306/fire?useUnicode=true&characterEncoding=UTF-8&useSSL=false spring.datasource.username=root spring.datasource.password=123456 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.xa.properties.useInformationSchema=true3、screw 核心配置screw有两种执行方式,第一种是pom文件配置,另一种是代码执行。 <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> <groupId>cn.smallbun.screw</groupId> <artifactId>screw-maven-plugin</artifactId> <version>1.0.3</version> <dependencies> <!-- HikariCP --> <dependency> <groupId>com.zaxxer</groupId> <artifactId>HikariCP</artifactId> <version>3.4.5</version> </dependency> <!--mysql driver--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.20</version> </dependency> </dependencies> <configuration> <!--username--> <username>root</username> <!--password--> <password>123456</password> <!--driver--> <driverClassName>com.mysql.cj.jdbc.Driver</driverClassName> <!--jdbc url--> <jdbcUrl>jdbc:mysql://41.92.6.5:3306/fire</jdbcUrl> <!--生成文件类型--> <fileType>HTML</fileType> <!--打开文件输出目录--> <openOutputDir>false</openOutputDir> <!--生成模板--> <produceType>freemarker</produceType> <!--文档名称 为空时:将采用[数据库名称-描述-版本号]作为文档名称--> <!--<docName>测试文档名称</docName>--> <!--描述--> <description>数据库文档生成</description> <!--版本--> <version>${project.version}</version> <!--标题--> <title>fire数据库文档</title> </configuration> <executions> <execution> <phase>compile</phase> <goals> <goal>run</goal> </goals> </execution> </executions> </plugin> </plugins> </build>配置完以后在 maven project->screw 双击执行ok。在这里插入图片描述代码生成方式也非常简单。@SpringBootTest public class ScrewApplicationTests { @Autowired ApplicationContext applicationContext; @Test void contextLoads() { DataSource dataSourceMysql = applicationContext.getBean(DataSource.class); // 生成文件配置 EngineConfig engineConfig = EngineConfig.builder() // 生成文件路径,自己mac本地的地址,这里需要自己更换下路径 .fileOutputDir("D:/") // 打开目录 .openOutputDir(false) // 文件类型 .fileType(EngineFileType.HTML) // 生成模板实现 .produceType(EngineTemplateType.freemarker).build(); // 生成文档配置(包含以下自定义版本号、描述等配置连接) Configuration config = Configuration.builder() .version("1.0.3") .description("生成文档信息描述") .dataSource(dataSourceMysql) .engineConfig(engineConfig) .produceConfig(getProcessConfig()) .build(); // 执行生成 new DocumentationExecute(config).execute(); } /** * 配置想要生成的表+ 配置想要忽略的表 * * @return 生成表配置 */ public static ProcessConfig getProcessConfig() { // 忽略表名 List<String> ignoreTableName = Arrays.asList("a", "test_group"); // 忽略表前缀,如忽略a开头的数据库表 List<String> ignorePrefix = Arrays.asList("a", "t"); // 忽略表后缀 List<String> ignoreSuffix = Arrays.asList("_test", "czb_"); return ProcessConfig.builder() //根据名称指定表生成 .designatedTableName(Arrays.asList("fire_user")) //根据表前缀生成 .designatedTablePrefix(new ArrayList<>()) //根据表后缀生成 .designatedTableSuffix(new ArrayList<>()) //忽略表名 .ignoreTableName(ignoreTableName) //忽略表前缀 .ignoreTablePrefix(ignorePrefix) //忽略表后缀 .ignoreTableSuffix(ignoreSuffix).build(); } }4、文档格式screw 有 HTML、DOC、MD 三种格式的文档。代码中的修改.fileType(EngineFileType.HTML)或者pom文件<fileType>MD</fileType>DOC文档样式work文档HTML文档样式在这里插入图片描述MD文档样式在这里插入图片描述
2021年11月05日
56 阅读
0 评论
0 点赞
2021-10-21
在Spring Boot中使用Cookies
本文大纲读取HTTP Cookie设置HTTP Cookie读取所有Cookie[]为Cookie设置过期时间Https与CookieHttpOnly Cookie删除CookieHTTP Cookie(也称为Web cookie,浏览器cookie)是服务器在用户浏览器中存储的小部分数据。服务器端应用程序在返回浏览器请求响应的时候设置cookie,浏览器存储cookie,并将它们在下一个请求一起发送的时候自动带回服务器端应用程序。Cookies提供了一种在服务器和浏览器之间交换信息的方法,以管理会话(登录,购物车,游戏得分),记住用户首选项(主题,隐私策略接受)以及跟踪整个站点的用户行为。Cookies在一定程度上解放了服务器端的压力,因为将一部分数据放在浏览器端存储,所以这部分数据不能是涉及应用安全的数据。在本文中,我们将学习如何在Spring Boot应用程序中读取、设置和删除HTTP cookie。二、读取HTTP CookieSpring框架提供@CookieValue注释来获取HTTP cookie的值,此注解可直接用在控制器方法参数中。 @GetMapping("/") public String readCookie(@CookieValue(value = "username", defaultValue = "Atta") String username) { return "Hey! My username is " + username; }在上述代码段中,请注意defaultValue = "Atta"。如果没有设置默认值,并且没有找到名称为username的Cookie,Spring将抛出java.lang.IllegalStateException异常。三、设置HTTP Cookie要在Spring Boot中设置cookie,我们可以使用HttpServletResponse类的方法addCookie()。您需要做的就是创建一个新的Cookie对象并将其添加到响应中。@GetMapping("/change-username") public String setCookie(HttpServletResponse response) { // 创建一个 cookie对象 Cookie cookie = new Cookie("username", "Jovan"); //将cookie对象加入response响应 response.addCookie(cookie); return "Username is changed!"; }四、读取所有Cookie[]除了使用@CookieValue注解,我们还可以使用HttpServletRequest类作为控制器方法参数来读取所有cookie。此类提供了getCookies()方法,该方法以数组形式返回浏览器发送的所有cookie。@GetMapping("/all-cookies") public String readAllCookies(HttpServletRequest request) { Cookie[] cookies = request.getCookies(); if (cookies != null) { return Arrays.stream(cookies) .map(c -> c.getName() + "=" + c.getValue()) .collect(Collectors.joining(", ")); } return "No cookies"; }五、为Cookie设置过期时间如果没有为cookie指定过期时间,则其生命周期将持续到Session过期为止。这样的cookie称为会话cookie。会话cookie保持活动状态,直到用户关闭其浏览器或清除其cookie。但是您可以覆盖此默认行为,并使用类的setMaxAge()方法设置cookie的过期时间。// 创建一个 cookie对象 Cookie cookie = new Cookie("username", "Jovan"); cookie.setMaxAge(7 * 24 * 60 * 60); // 7天过期 //将cookie对象加入response响应 response.addCookie(cookie);现在,usernameCookie不会因为Seesion结束到期,而是会在接下来的7天保持有效。传递给setMaxAge()方法的到期时间以秒为单位。到期日期和时间是相对于设置cookie的客户端而不是服务器而言的。六、Https与Cookie我们需要了解一个概念:什么的安全的Cookies?安全的cookie是仅可以通过加密的HTTPS连接发送到服务器的cookie。无法通过未加密的HTTP连接将cookie发送到服务器。也就是说,如果设置了setSecure(true),该Cookie将无法在Http连接中传输,只能是Https连接中传输。// 创建一个 cookie对象 Cookie cookie = new Cookie("username", "Jovan"); cookie.setSecure(true); //Https 安全cookie //将cookie对象加入response响应 response.addCookie(cookie);七、HttpOnly CookieHttpOnly cookie用于防止跨站点脚本(XSS)攻击,也就是说设置了Http Only的Cookie不能通过JavaScript的Document.cookieAPI访问,仅能在服务端由服务器程序访问。// 创建一个 cookie对象 Cookie cookie = new Cookie("username", "Jovan"); cookie.setHttpOnly(true); //不能被js访问的Cookie //将cookie对象加入response响应 response.addCookie(cookie);八、删除Cookie要删除Cookie,需要将Max-Age设置为0,并且将Cookie的值设置为null。不要将Max-Age指令值设置为-1负数。否则,浏览器会将其视为会话cookie。// 将Cookie的值设置为null Cookie cookie = new Cookie("username", null); //将`Max-Age`设置为0 cookie.setMaxAge(0); response.addCookie(cookie);概括Cookie 提供了一种在服务器和浏览器之间交换信息以管理会话(登录、购物车、游戏分数)、记住用户偏好(主题、隐私政策接受)以及跟踪用户在整个站点上的行为的方法。Spring Boot 提供了一种简单的方法来读取、写入和删除 HTTP cookie。@CookieValue注释将 cookie 的值映射到方法参数。当 cookie 不可用时,您应该设置默认值以避免运行时异常。HttpServletResponse类可用于在浏览器中设置新的 cookie。您只需要创建一个Cookie类的实例并将其添加到响应中。要读取所有 cookie,您可以使用HttpServletRequest'sgetCookies()方法返回一个Cookie.Max-Age 指令指定 cookie 应到期的日期和时间。如果您在 cookie 中存储敏感信息,请确保设置Secure和HttpOnly标记以避免 XSS 攻击。设置Path=/使当前域的 cookie 可在任何地方访问。要删除 cookie,请将 设置Max-Age为0并传递用于设置它的所有属性。
2021年10月21日
20 阅读
0 评论
0 点赞