前后端分离项目博客
我觉得用注解更加简便,相比各种继承
前端工程在后台运行
使用命令
Start-Process -FilePath "npm" -ArgumentList "run dev" -NoNewWindow -PassThru
原本命令为npm run dev
进程序号会打印出来
查询进程
Get-Process
想要删除使用id号
Stop-Process -Id 11896
按时间查看进程
Get-Process | Sort-Object StartTime
redis后台运行
Start-Process -FilePath "redis-server" -WindowStyle Hidden
记录进程号(该进程号为cmd进程号,非运行的nodejs工程进程号)
在启动进程时记录其进程ID,可以使用 Start-Process
命令的 -PassThru
参数。这将返回一个包含进程信息的对象,你可以从该对象中获取进程ID,并将其记录到文件或变量中。
示例:启动进程并记录进程ID
powershell复制代码# 启动进程并返回进程对象
$process = Start-Process -FilePath "npm" -ArgumentList "run dev" -NoNewWindow -PassThru
# 输出进程ID和进程名称
$process.Id
$process.ProcessName
# 保存进程ID到文件
$process.Id > "process_id.txt"
示例:从文件读取进程ID并终止进程
- 启动进程并记录进程ID
``` powershell复制代码# 启动进程并返回进程对象 $process = Start-Process -FilePath "npm" -ArgumentList "run dev" -NoNewWindow -PassThru
# 输出进程ID和进程名称 $process.Id $process.ProcessName
# 保存进程ID到文件 $process.Id > "process_id.txt" ```
- 读取进程ID并终止进程
``` powershell复制代码# 读取进程ID $processId = Get-Content "process_id.txt"
# 终止进程 Stop-Process -Id $processId
# 可选:删除记录的文件 Remove-Item "process_id.txt" ```
综合脚本示例
启动进程并记录进程ID:
powershell复制代码# 启动进程并返回进程对象
$process = Start-Process -FilePath "npm" -ArgumentList "run dev" -NoNewWindow -PassThru
# 输出进程ID和进程名称
Write-Output "Process ID: $($process.Id)"
Write-Output "Process Name: $($process.ProcessName)"
# 保存进程ID到文件
$process.Id | Out-File -FilePath "process_id.txt"
读取进程ID并终止进程:
powershell复制代码# 读取进程ID
$processId = Get-Content "process_id.txt"
# 终止进程
Stop-Process -Id $processId
# 可选:删除记录的文件
Remove-Item "process_id.txt"
通过这种方式,你可以在启动进程时记录其进程ID,并在需要时使用该ID来管理进程。
不扎实的东西
集合,反射,stream流
这段代码的作用是从一个文章列表中提取所有的分类ID,并将这些ID存储到一个Set<Long>
集合中。具体解释如下:
Set<Long> categoryIds = articleList.stream()
.map(article -> article.getCategoryId())
.collect(Collectors.toSet());
articleList.stream()
: 将文章列表转换成一个流(Stream)。.map(article -> article.getCategoryId())
: 将流中的每篇文章映射(转换)为它的分类ID。.collect(Collectors.toSet())
: 将映射后的分类ID收集到一个Set
集合中,以去除重复的ID。
这样做的结果是categoryIds
集合中包含了所有不重复的文章分类ID。
LambdaQueryWrapper&QueryWrapper
这是我之前没接触到的东西耶,当初认为mybatis的xml配置已经封圣了
MyBatis Plus 中的 getById()
方法是 IService
接口提供的静态方法,用于根据实体对象的的主键值从数据库中检索单个实体对象。
一个前端工程的部署搞死了我
Stream流
categories = categories.stream()
.filter(category -> SystemConstants.Category_STATUS_NORMAL.equals(category.getStatus()))
.collect(Collectors.toList());
Q:stream流中Map方法的作用是什么
A:
- 将原始 Stream 中的每个元素都映射转换为另一个元素,从而得到一个新的 Stream。
- 转换前后的元素类型可以不同。
- map()方法不会修改原始 Stream 中的元素,而是创建一个新的 Stream,其中包含了原始 Stream 中每个元素经过转换后的结果。
Q:Stream中的.collect()传参Collectors.toList()和Collectors.toSet()有什么区别
A:Stream中的.collect()
方法用于将Stream中的元素收集到集合中。Collectors.toList()
和Collectors.toSet()
是两个常用的Collector
实现,用于将Stream收集到List
和Set
中,分别。
区别
- 返回结果类型不同:
Collectors.toList()
返回一个List
类型的集合,该集合中的元素保持原有的顺序。Collectors.toSet()
返回一个Set
类型的集合,该集合中的元素是唯一的,并且不保证顺序。- 内存占用不同:
Collectors.toList()
通常比Collectors.toSet()
占用更多的内存,因为List
需要额外存储元素的顺序信息。Collectors.toSet()
通常比Collectors.toList()
占用更少的内存,因为Set
不需要存储元素的顺序信息。- 性能不同:
Collectors.toList()
通常比Collectors.toSet()
效率更高,因为List
的插入操作通常比Set
的插入操作更快速。Collectors.toSet()
在需要去重的情况下比Collectors.toList()
更有效,因为Set
可以自动去除重复的元素。
选择指南
- 需要保留元素的顺序: 使用
Collectors.toList()
. - 需要去除重复的元素: 使用
Collectors.toSet()
. - 需要更高的性能: 使用
Collectors.toList()
. - 需要更少的内存占用: 使用
Collectors.toSet()
.
以下是一些使用示例:
// 将Stream中的元素收集到List中
List<String> names = Arrays.asList("Alice", "Bob", "Charlie").stream().collect(Collectors.toList());
// 将Stream中的元素收集到Set中
Set<Integer> numbers = Arrays.asList(1, 2, 3, 1, 2, 3).stream().collect(Collectors.toSet());
跨域问题
package com.irreplace.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @author Me
* @version 1.0
* @date 2024/7/17 16:18
* @Description:解决跨域问题
*/
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
// 设置允许跨域的路径
registry.addMapping("/**")
// 设置允许跨域请求的域名
.allowedOriginPatterns("*")
// 是否允许cookie
.allowCredentials(true)
// 设置允许的请求方式
.allowedMethods("GET", "POST", "DELETE", "PUT")
// 设置允许的header属性
.allowedHeaders("*")
// 跨域允许时间
.maxAge(3600);
}
}
Bean拷贝封装成工具类
这啥啊我完全看不懂气死了啊
package com.irreplace.utils;
import org.springframework.beans.BeanUtils;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author Me
* @version 1.0
* @date 2024/7/17 22:18
* @Description:封装成前端需要的字段,工具类
*/
public class BeanCopyUtils {
private BeanCopyUtils() {
}
public static <V> V copyBean(Object source,Class<V> clazz) {
//创建目标对象
V result = null;
try {
result = clazz.newInstance();
//实现属性copy
BeanUtils.copyProperties(source, result);
} catch (Exception e) {
e.printStackTrace();
}
//返回结果
return result;
}
public static <O,V> List<V> copyBeanList(List<O> list, Class<V> clazz){
return list.stream()
.map(o -> copyBean(o, clazz))
.collect(Collectors.toList());
}
}
EasyCode模板配置
包的宏定义,mapper出问题?
yml配置mybatis逻辑删除
这段配置是用于配置 MyBatis-Plus 的全局配置,特别是数据库配置部分。具体解释如下:
mybatis-plus:
global-config:
db-config:
logic-delete-field: delFlag
logic-delete-value: 1
logic-not-delete-value: 0
id-type: auto
mybatis-plus
: MyBatis-Plus 的配置根节点。global-config
: 全局配置。db-config
: 数据库配置。
具体字段解释:
logic-delete-field: delFlag
-
指定逻辑删除的字段名。在数据库表中,这个字段用于标记记录是否被逻辑删除。比如,当
delFlag
为 1 时表示记录被删除,当为 0 时表示记录未被删除。 -
logic-delete-value: 1
-
表示逻辑删除时,该字段的值。这里表示如果
delFlag
字段的值为 1,则该记录被逻辑删除。 -
logic-not-delete-value: 0
-
表示逻辑未删除时,该字段的值。这里表示如果
delFlag
字段的值为 0,则该记录未被逻辑删除。 -
id-type: auto
- 指定主键生成策略为自动增长(自增主键)。这意味着在插入新记录时,主键值会自动生成。
总结:这段配置主要用于设置 MyBatis-Plus 中关于逻辑删除和主键生成的全局配置,方便在操作数据库时对逻辑删除字段进行统一管理,并自动处理主键的生成。
解析CategoryServiceImpl.getCategoryList()
总体代码
/**
* @author Me
* @version 1.0
* @date 2024/7/18 12:19
* @Description:分类
*/
@Service
@Slf4j
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper,Category> implements CategoryService {
@Autowired
private ArticleService articleService;
@Override
public ResponseResult getCategoryList() {
//先查询文章,返回正常显示的文章
LambdaQueryWrapper<Article> lambdaWrapper = new LambdaQueryWrapper<>();
lambdaWrapper.eq(Article::getStatus, SystemConstants.ARTICLE_STATUS_NORMAL);
List<Article> articleList = articleService.list(lambdaWrapper);
//筛选出正常显示的文章id号,并且去除重复
Set<Long> collectIds = articleList.stream()
.map(article -> article.getCategoryId())
.collect(Collectors.toSet());
//查询分类表,stream过滤出状态为正常的文章分类
List<Category> categories = listByIds(collectIds);
categories = categories.stream()
.filter(category -> SystemConstants.Category_STATUS_NORMAL.equals(category.getStatus()))
.collect(Collectors.toList());
//封装vo
List<CategoryVo> categoryVos = BeanCopyUtils.copyBeanList(categories, CategoryVo.class);
//log.info(categoryVos.toString());
return ResponseResult.successResult(categoryVos);
}
}
LambdaQueryWrapper使用
这段代码是使用 MyBatis-Plus 构建查询条件并查询文章列表。具体解释如下:
//先查文章表,状态为已发布文章
LambdaQueryWrapper<Article> articleWrapper = new LambdaQueryWrapper<>();
articleWrapper.eq(Article::getStatus, SystemConstants.ARTICLE_STATUS_NORMAL);
List<Article> articleList = articleService.list(articleWrapper);
LambdaQueryWrapper<Article> articleWrapper = new LambdaQueryWrapper<>();
-
创建一个
LambdaQueryWrapper
对象,用于构建查询条件。LambdaQueryWrapper
是 MyBatis-Plus 提供的一个工具类,用于以 lambda 表达式的方式构建查询条件。 -
articleWrapper.eq(Article::getStatus, SystemConstants.ARTICLE_STATUS_NORMAL);
- 使用
eq
方法构建查询条件,表示查询status
字段等于SystemConstants.ARTICLE_STATUS_NORMAL
的记录。 Article::getStatus
是 lambda 表达式,表示Article
类中的getStatus
方法,即查询status
字段。-
SystemConstants.ARTICLE_STATUS_NORMAL
是一个常量,表示正常状态的文章。 -
List<Article> articleList = articleService.list(articleWrapper);
- 使用
articleService
的list
方法根据构建的查询条件articleWrapper
查询符合条件的文章列表,并将结果存储在articleList
中。
总结:这段代码的作用是查询状态为正常(ARTICLE_STATUS_NORMAL
)的文章列表,并将查询结果存储在 articleList
中。
两处stream流使用
//筛选出正常显示的文章id号,并且去除重复
Set<Long> collectIds = articleList.stream()
.map(article -> article.getCategoryId())
.collect(Collectors.toSet());
//查询分类表,stream过滤出状态为正常的文章分类
List<Category> categories = listByIds(collectIds);
categories = categories.stream()
.filter(category -> SystemConstants.Category_STATUS_NORMAL.equals(category.getStatus()))
.collect(Collectors.toList());
Stream 是 Java 8 引入的一种新的抽象序列,用于处理集合数据的方法。它提供了一种高效且易于理解的方式来对集合进行操作和处理。以下是一些常用的 Stream 方法:
- forEach:
- 对流中的每个元素执行指定的操作。
java
stream.forEach(element -> System.out.println(element));
- map:
- 将流中的每个元素通过指定的函数映射成另一个元素。
java
Stream<String> upperCaseStream = stream.map(String::toUpperCase);
- filter:
- 根据指定的条件过滤流中的元素。
java
Stream<String> filteredStream = stream.filter(s -> s.length() > 5);
- collect:
- 将流中的元素收集到一个集合或者其他数据结构中。
java
List<String> collectedList = stream.collect(Collectors.toList());
- reduce:
- 将流中的元素通过指定的二元操作符进行归约操作,得到一个最终的结果。
java
Optional<String> reducedString = stream.reduce((s1, s2) -> s1 + ", " + s2);
- findFirst 和 findAny:
findFirst
返回流中的第一个元素;findAny
返回流中的任意一个元素(在并行流中有用)。
java
Optional<String> firstElement = stream.findFirst();
Optional<String> anyElement = stream.findAny();
- count:
- 返回流中元素的数量。
java
long count = stream.count();
- skip 和 limit:
skip
跳过流中的前几个元素;limit
限制流中元素的数量。
java
Stream<String> skippedStream = stream.skip(2);
Stream<String> limitedStream = stream.limit(5);
- sorted:
- 对流中的元素进行排序。
java
Stream<String> sortedStream = stream.sorted();
-
distinct:
- 去除流中重复的元素。
java Stream<String> distinctStream = stream.distinct();
-
allMatch, anyMatch, noneMatch:
allMatch
检查流中的所有元素是否都满足指定条件;anyMatch
检查流中是否至少有一个元素满足指定条件;noneMatch
检查流中是否所有元素都不满足指定条件。
java boolean allMatched = stream.allMatch(s -> s.length() > 3); boolean anyMatched = stream.anyMatch(s -> s.startsWith("A")); boolean noneMatched = stream.noneMatch(s -> s.isEmpty());
这些是 Java 中 Stream 类中常用的一些方法。每个方法都提供了不同的功能,可以根据具体的需求来选择合适的方法来操作和处理流中的数据。
分页查询
MyBatis-Plus 拦截器
配置和注册一个 MyBatis-Plus 拦截器,用于在 MyBatis 执行 SQL 时自动拦截并实现分页功能
package com.irreplace.config;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author Me
* @version 1.0
* @date 2024/7/18 14:36
* @Description:配置和注册一个 MyBatis-Plus 拦截器,用于在 MyBatis 执行 SQL 时自动拦截并实现分页功能。
*/
@Configuration
public class MybatisPlusConfig {
/**
* 3.4.0之后版本
*
* @return
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor mybatisPlusInterceptor = new
MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(new
PaginationInnerInterceptor());
return mybatisPlusInterceptor;
}
}
文章详情分类
从路径中获取请求参数记得添加注解
登陆
自定义登陆接口
注入AuthenticationManager
前台Blog的SecurityConfig.configure
@Override
protected void configure(HttpSecurity http) throws Exception {
http
//关闭csrf
.csrf().disable()
//不通过Session获取SecurityContext
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
// 对于登录接口 允许匿名访问
.antMatchers("/login").anonymous()
// 除上面外的所有请求全部不需要认证即可访问
.anyRequest().permitAll();
http.logout().disable();
//允许跨域
http.cors();
}
这段代码是 Spring Security 配置的一部分,用于配置 Spring Security 的安全策略。它主要做了以下几件事情:
1. 关闭 CSRF 保护
CSRF(Cross-Site Request Forgery)是一种跨站请求伪造攻击,攻击者可以利用用户的已登录身份来执行一些未经授权的操作。Spring Security 默认启用 CSRF 保护,可以帮助防止此类攻击。但是,在某些情况下,您可能需要关闭 CSRF 保护。例如,如果您使用的是 REST API,则可能需要关闭 CSRF 保护,以便允许跨域请求。
2. 禁用 Session 创建
Spring Security 默认使用 Session 来存储 SecurityContext,SecurityContext 包含有关当前用户的安全信息。但是,如果您使用的是无状态应用程序,则不需要 Session。在这种情况下,您可以禁用 Session 创建。
3. 配置授权规则
授权规则定义了哪些用户可以访问哪些资源。在这段代码中,有两个授权规则:
- 对于
/login
接口,允许匿名访问。这意味着任何用户都可以访问此接口,而无需登录。 - 对于除
/login
接口之外的所有请求,都不需要认证即可访问。这意味着任何用户都可以访问这些请求,无论他们是否登录。
4. 禁用注销功能
默认情况下,Spring Security 提供注销功能,允许用户退出登录。但是,如果您不需要注销功能,可以禁用它。
5. 启用跨域支持
跨域是指来自不同域的 Web 应用程序之间的通信。默认情况下,浏览器会限制跨域请求。Spring Security 提供跨域支持,可以帮助您允许跨域请求。
总而言之,这段代码配置了以下安全策略:
- 关闭 CSRF 保护
- 禁用 Session 创建
- 对于
/login
接口,允许匿名访问 - 对于除
/login
接口之外的所有请求,都不需要认证即可访问 - 禁用注销功能
- 启用跨域支持
登录校验过滤器实现
记得要在httpconfig加入该过滤器http.addFilterbefore()?!!!
分页查询
Page<Comment> commentPage = new Page<>(pageNum,pageSize);
page(commentPage,commentLambdaQueryWrapper);
这就完成了?但我真的搞不懂