从零开始创建微服务-跨域、缓存-day2

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,只需要一个地址便可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值