1. 20230609学习记录
目标:
- 跨域解决方案
- 使用vo对象和spring缓存
- linux安装jdk
- linux部署jar包
1.1. 跨域解决方案
1.1.1. 使用注解@CrossOrigin() 可修饰类和方法
@CrossOrigin(origins = "*") //任何请求源请求的都不会被浏览器阻挡
@RequestMapping("/hello")
@ResponseBody
public String hello(@RequestParam(name = "name", defaultValue = "unknown user") String name) {
return "Hello " + name;
}
1.1.2. 手动设置响应头 可以在请求的controller中写,也可以使用过滤器在其中设置响应头
response.addHeader("Access-Control-Allow-Origin", "*");
response.addHeader("Access-Control-Max-Age", "10");
response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT");
response.setHeader("Access-Control-Allow-Credentials", "true");
1.1.3. 创建实现WebMvcConfigurer的类,实现addCorsMappings方法
方法类 | 方法名称 | 必填 | 请求头字段 | 说明 |
---|---|---|---|---|
CorsRegistry | addMapping | 是 | 无, 非Cors属性, 属于SpringBoot配置 | 配置支持跨域的路径 |
CorsRegistration | allowedOrigins | 是 | Access-Control-Allow-Origin | 配置允许的源 |
CorsRegistration | allowedMethods | 是 | Access-Control-Allow-Methods | 配置支持跨域请求的方法, 如:GET、POST,一次性返回 |
CorsRegistration | maxAge | 否 | Access-Control-Max-Age | 配置预检请求的有效时间 |
CorsRegistration | allowCredentials | 否 | Access-Control-Allow-Credentials | 配置是否允许发送Cookie, 用于 凭证请求 |
CorsRegistration | allowedHeaders | 否 | Access-Control-Request-Headers | 配置允许的自定义请求头, 用于 预检请求 |
CorsRegistration | exposedHeaders | 否 | Access-Control-Expose-Headers | 配置响应的头信息, 在其中可以设置其他的头信息 |
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") // 匹配所有接口
.allowedOrigins("*") // 支持所有路径的跨域
.allowedMethods("GET", "POST", "PUT", "DELETE") // 支持方法
.allowedHeaders("*"); //允许添加的头信息
}
}
1.2. 实体类中逻辑外键对应的数据封装问题
当前有三张表
book_table
表中有type_id、publisher_id字段与book_type
、publisher
建立逻辑外键查询book时前端页面如何将book 的bookType书籍类型 publisher出版社名称 一同显示
原操作
使用
join多表联查
,让我们的entity
也兼职vo
的作用
在实体类中添加所需前端所需展示的字段属性:创建Book实体类时,添加BookType,Publisher类型的属性,或者添加bookTypeName,publisherName属性。
然后使用join连接表的sql查询,将book_type
和publisher
的查询结果映射到Book实体类中冗余的属性中。
通过DTO传给前端后,前端可以直接使用。
优化操作
1.2.1. vo对象和map模拟缓存
独立出vo对象,join的联表查询改为各自的单表查询,使用Map存储查询结果,将所有结果拿取所需封装为VO对象。
创建VO类,BookVo
public class BookVo {
private Book book;
//前端需要展示书籍类型名字,此处也可以直接定义类型名字的属性
private BookType bookType;
//前端需要展示书籍出版社名字,此处也可以直接定义出版社名字的属性
private Publisher publisher;
}
service层,创建map集合,存放 id=对象
键值对,存储书籍类型和出版社;
map集合可以通过book对象中的逻辑外键属性bookTypeId、publisherId,直接能map.get()得到对应的对象,便于拿取数据
//map集合当作缓存所有BookType的容器
private static Map<Long,BookType> bookTypeMap = new HashMap<>();
//查询所有BookType,放进map集合中
private void getBookTypeMap(){
List<BookType> bookTypes = bookTypeService.findAll();
bookTypes.forEach(bt -> bookTypeMap.put(bt.getId(),bt));
}
//map集合当作缓存所有Publisher的容器
private static Map<Long,Publisher> publisherMap = new HashMap<>();
//查询所有BookType,放进map集合中
private void getPublisherMap(){
List<Publisher> publishers = publisherService.findAll();
publishers.forEach(p -> publisherMap.put(p.getId(),p));
}
查询方法中将emtity封装为vo
//准备数据,获取存储书籍类型和出版社的集合
getBookTypeMap();
getPublisherMap();
//查询所有书籍
List<Book> books = bookDao.selectList(null);
//创建vo对象集合
List<BookVo> bookVos = new ArrayList<>(50);
//遍历书本集合,封装vo对象
books.forEach(b -> bookVos.add(new BookVo(b,bookTypeMap.get(b.getBookTypeId()),publisherMap.get(b.getPublisherId()))));
return bookVos;
1.2.2. 使用SpringBoot的缓存
缓存,暂存数据,减少对数据库的直接操作,让查询的速度更快
缓存的使用场景:对改动不频繁的数据进行缓存;短时间内对数据库大量操作的情况,先进行对缓存数据的操作
以上的map优化使用SpringBoot的缓存来存储BookType和Publisher
1.2.2.1. SpringBoot缓存注解解析
1.2.2.1.1. @EnableCaching
在启动类上添加该注解,使能缓存功能
1.2.2.1.2. @Cacheable
-
是一个方法注解也是个类注解
-
当标记在一个方法上时表示该方法是支持缓存的,当标记在一个类上时则表示该类所有的方法都是支持缓存的。
-
什么时候缓存:方法被调用后并且condition值成立,才将返回值缓存起来
-
主要的三个属性
属性 | 含义 |
---|---|
value/cacheNames=“xxx” | 指定缓存组件的名字,即将标识了返回结果放在名为xxx的缓存中;是个数组,可以指定多个缓存 |
key | 缓存是按照键值对存储的,key就是指定键;没指定默认使用方法被调用时传过来的参数,没有参数会自动生成;指定时,使用 SpEL表达式的方式来编写;当方法再次被调用时,key值相等就从缓存拿取结果,不再执行方法。 |
condition | 条件判断属性,condition中的SpEL表达式成立时才进行缓存;默认为空 |
在BookTypeService中的findAll方法上添加注解,将查询所有的返回值存入"allBookTypes"的缓存中
@Cacheable(cacheNames = "allBookTypes")
@Override
public List<BookType> findAll() {
return bookTypeDao.selectList(null);
}
一个支持缓存的方法在当前类内部被调用时是不会触发缓存功能的
1.2.2.1.3. @CachePut
属性和@Cacheable
基本一致
@CachePut
也可以声明一个方法支持缓存功能。与@Cacheable不同的是使用@CachePut标注的方法在执行前不会去检查缓存中是否存在之前执行过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中。常标注于修改的方法上
使用场景例子:
一个根据id查询的方法,标注@Cacheable(value="abc",key="#id")
存在abc
这个缓存中,键为方法参数:id
一个根据id修改的方法,标注@CachePut(value="a",key="#user.id")
将返回结果存在abc
这个缓存中键为user的id
的值中,或者覆盖整个值
当第一次查询了id=1的用户,用户数据存在了缓存中,第二次查询直接在缓存中获取;
然后修改了id=1的用户信息,修改后的数据存在了abc这个缓存中键为user的id的值中,此时就是即更新数据库也更新了缓存;
此时再查询id=1的用户,直接从缓存中拿取,并且取出的是修改后的数据,这样就能防止缓存中拿取的数据是旧数据
1.2.2.1.4. @CacheEvict
属性和@Cacheable
基本一致
清楚缓存中的数据
value指定哪个缓存,key指定缓存中的哪个键值对,两者可以定位缓存中唯一的值
其中一个不同的属性:allEntries属性
boolean类型,为true时,忽略指定的key,清楚指定缓存的所有数据
参考:
http://t.csdn.cn/VKbNe
https://www.cnblogs.com/fashflying/p/6908028.html
1.3. Linux安装JDK
1.3.1. 删除原有的jdk
-
rpm -qa| grep java
查看安装着的和java相关的包
-
rpm -e --nodeps 包名
删除包
1.3.2. 将linux版本的jdk文件上传到/usr/local/software 目录下
software 为自己创建的目录
1.3.3. 解压jdk文件
tar -zxvf jdk包名
1.3.4. 配置java环境
-
进入/etc/profile 文件
vim /etc/profile
vim编辑器打开文件在文件最后进行编辑
-
JAVA_HOME JDK安装路径
JAVA_HOME=/usr/local/software/jdk1.8.0_341
- CLASSPATH lib路径
CLASSPATH=.:$JAVA_HOME/lib
- PATH bin路径
PATH=$JAVA_HOME/bin:$PATH
-
export JAVA_HOME CLASSPATH PATH
-
退出vim,将配置生效
source /etc/profile
-
查看是否配置成功
java -version
成功
1.4. 在linux中部署项目jar包
1.4.1. 打包项目
先clean一下再package,打包好的jar包在target文件下
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Xip1c8cl-1686361412592)(./assets/image-20230609191520979.png)]
1.4.2. 上传jar包到linux
上传到software目录下
1.4.3. 启动jar包
java -jar 文件包名
1.4.4. 前端页面访问
正常显示数据,部署成功
如果无法访问,打开linux中项目设置的端口号
#开启指定端口
firewall-cmd --zone=public --add-port=端口号/tcp --permanent
#开启指定端口后必须重启防火墙
systemctl restart firewalld.service
#查看已开放端口
firewall-cmd --list-ports