2 搭建前端环境
2.1 npm(yarn也可以)管理环境
2.2 存在问题
1.后端有多个端口,前端该怎么访问不同的端口呢?
nginx做转发
2.跨域问题(后面使用gateway网关解决跨域问题,此处可以跳过)
只有协议、ip、端口号有任一不同,就叫做跨域;存在跨域问题在Controller上加上@CrossOrigin注解便可以解决问题。
比如前端医院设置从8201端口访问,但是数据字典从8202访问,数据字典的controller中就应该加上@CrossOrigin注解,以便启用CORS(默认情况下,@CrossOrigin允许在@RequestMapping注解中指定的所有源和HTTP方法)
@Api(tags = "数据字典接口")
@RestController
@RequestMapping("/admin/cmn/dict")
@CrossOrigin
public class DictController {
}
如果正在使用Spring Security,请确保在Spring安全级别启用CORS,并允许它利用Spring MVC级别定义的配置。
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and()...
}
}
除了细粒度、基于注释的配置之外,您还可能需要定义一些全局CORS配置。这类似于使用筛选器,但可以声明为Spring MVC并结合细粒度@CrossOrigin配置。默认情况下,所有origins and GET, HEAD and POST methods是允许的。
- JavaConfig使整个应用程序的CORS简化为:
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
}
- 如果使用的是Spring Boot,建议将WebMvcConfigurer bean声明如下:
@Configuration
public class MyConfiguration {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
};
}
}
你可以轻松地更改任何属性,以及仅将此CORS配置应用到特定的路径模式:
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://domain2.com")
.allowedMethods("PUT", "DELETE")
.allowedHeaders("header1", "header2", "header3")
.exposedHeaders("header1", "header2")
.allowCredentials(false).maxAge(3600);
}
基于过滤器的CORS支持,作为上述其他方法的替代,Spring框架还提供了CorsFilter。在这种情况下,不用使用@CrossOrigin或WebMvcConfigurer#addCorsMappings(CorsRegistry),,例如,可以在Spring Boot应用程序中声明如下的过滤器:
@Configuration
public class MyConfiguration {
@Bean
public FilterRegistrationBean corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("http://domain1.com");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
bean.setOrder(0);
return bean;
}
}
3.对象复制问题
BeanUtils.copyProperties(dist,res)
3 缓存问题
Spring cache+Redis缓存数据(数据字典,首页数据)
3.1 使用redis作为缓存
3.1.1 添加相关依赖到service-uitl模块pom中
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- spring2.X集成redis所需common-pool2-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.6.0</version>
</dependency>
3.1.2 在service-util添加配置类
固定写法,直接复制粘贴,只需看懂即可。
package com.tjj.common.config;
@Configuration
@EnableCaching
public class RedisConfig {
/**
* 自定义key规则
* @return
*/
@Bean
public KeyGenerator keyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object target, Method method, Object... params) {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(method.getName());
for (Object obj : params) {
sb.append(obj.toString());
}
return sb.toString();
}
};
}
/**
* 设置RedisTemplate规则
* @param redisConnectionFactory
* @return
*/
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
//解决查询缓存转换异常的问题
ObjectMapper om = new ObjectMapper();
// 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
//序列号key value
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
/**
* 设置CacheManager缓存规则
* @param factory
* @return
*/
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
//解决查询缓存转换异常的问题
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
// 配置序列化(解决乱码的问题),过期时间600秒
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofSeconds(600))
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
.disableCachingNullValues();
RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
return cacheManager;
}
}
3.1.3 在具体服务中添加redis配置
在application.properties中添加redis配置
#Redis配置
spring.redis.host=47.111.149.199
spring.redis.port=6379
spring.redis.password=redis147896325
spring.redis.database= 0
spring.redis.timeout=1800000
spring.redis.lettuce.pool.max-active=20
spring.redis.lettuce.pool.max-wait=-1
#最大阻塞等待时间(负数表示没限制)
spring.redis.lettuce.pool.max-idle=5
spring.redis.lettuce.pool.min-idle=0
3.2 使用Spring Cache
使用SpringCache分为很简单的三步:加依赖,开启缓存,加缓存注解。
3.2.1 SpringCache常用缓存标签
@Cacheable
注解表示这个方法有了缓存功能,方法的返回值就会被缓存下来,下一次调用该方法之前会去检查缓存中是否有值,如果有值就直接返回,不再调用此方法了。如果缓存中没有值才会调用此方法,并将结果缓存起来。一般用于查询方法上
@Cacheable(value = "user",key = "#userId")
public UserInfo queryById(Long userId) {
//从数据库查询
UserInfo user = new UserInfo();
user.setId(userId);
user.setNickname("john");
return user;
}
@CachePut
不提供查询功能,加了@CachePut注解的方法会把此方法的返回值put到缓存里缓存起来,以便使其他地方使用,一般用于新增方法上
@CacheEvict
使用了@CacheEvict直接的方法会清空指定的缓存,一般用在更新或者删除方法上
@CacheEvict(value = "user",key = "#userId")
public void update(Long userId) {
//修改用户
UserInfo user = new UserInfo();
user.setId(userId);
user.setNickname("john");
}
@Caching
Java代码中同一个方法只能配置一个相同的注解配置,若想操作多个缓存可以使用@Caching
想要使用此注解需要在启动类上加上@EnableCaching
@SpringBootApplication
@EnableCaching //开启缓存
public class DemoApplication{
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
4 nginx做转发
现在前端要访问后端不同的端口,此时就可以用nginx做转发(以后使用gateway网关,不再使用nginx)
server{
listen 9001;
server name localhost;
location ~/hosp/{
proxy pass http://localhost:8201;
}
location ~/cmn/{
proxy pass http://localhost:8202;
}
}
nginx对外的端口号是9001,主机名称为localhost,设定了两个规则,第一个规则是:当路径中包含/hosp/时,此时访问的路径转发到8201端口号,即http://localhost:8201。第二个规则是:当路径中包含/cmn/时,此时访问的路径转发到8202端口号,即http://localhost:8202。
此时前端访问的端口就不再是8201或者是8202了,此时应该统一为了9001,只需要一个地址便可。