《基于SpringCloud微服务架构广告系统设计与实现》笔记
1-1 课程导学
什么是广告系统?
2-1 广告系统概览
2-2 广告系统架构
2-3 准备工作与系统目录结构
2-3 准备工作与系统目录结构
第3章 广告系统骨架开发
3-1 Maven基础知识
3-2 Maven 相关特性
3-3 广告系统主工程
...建立项目结构...
Maven有三种类型的仓库:
本地仓库:工程里依赖的jar包,maven会主动下载到本地目录的.m2。
中央仓库:由maven社区提供,包含有大量的常用库。
远程仓库:对开发者提供的,开发者把自己编写的包放在这个仓库,工程就可以指定远程仓库去下载。
3-4 单节点 Eureka Server 的开发
3-5 Eureka Server 的部署
分别启动单节点和多节点的Eureka Server
单节点配置文件:
多节点(三个节点的Eureka server):
由于父工程会管理所有子工程,因此在父工程打包:
启动第一个服务:
类似的,分别启动server2和3。
3-6 微服务架构及网关组件介绍
三种类型的过滤器可以分别用来实现不同的功能。
Pre filters:请求被路由之前调用,可以利用这种过滤器实现身份认证、在集群中选择请求的微服务记录调试信息等等。
Routing filters:这种过滤器将请求路由到微服务,即用于构造发送给微服务的请求。使用Apache的HttpClient或者Netflix的Ribbon请求微服务。
Post filters:这种过滤器在路由到微服务以后执行,可以为响应添加Http的header、收集统计信息和指标、将响应从微服务发送给客户端等等。
Error filters:当请求发生了错误去执行的过滤器。
Custom filters:自定义的过滤器。例如我们可以定义一种静态类型的过滤器,直接在Zuul中响应,而不在微服务中响应。如果请求的是一个静态文件,可以不需要经过路由到微服务,直接在Custom filters返回给客户端。
3-7 网关启动程序的开发
3-8 自定义网关过滤器的开发
实现两个自定义过滤器完成一个访问日志的功能。
PreRequestFilter.java
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;
@Slf4j @Component public class PreRequestFilter extends ZuulFilter { @Override public String filterType() { return FilterConstants.PRE_TYPE; } @Override public int filterOrder() { return 0; } @Override public boolean shouldFilter() { return true; } @Override public Object run() throws ZuulException { RequestContext ctx = RequestContext.getCurrentContext(); ctx.set("startTime", System.currentTimeMillis()); return null; } }
AccessLogFilter.java
import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.context.RequestContext; import com.netflix.zuul.exception.ZuulException; import lombok.extern.slf4j.Slf4j; import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants; import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest; @Slf4j @Component public class AccessLogFilter extends ZuulFilter { @Override public String filterType() { return FilterConstants.POST_TYPE; } @Override public int filterOrder() { return FilterConstants.SEND_RESPONSE_FILTER_ORDER - 1; } @Override public boolean shouldFilter() { return true; } @Override public Object run() throws ZuulException { RequestContext context = RequestContext.getCurrentContext(); HttpServletRequest request = context.getRequest(); Long startTime = (Long) context.get("startTime"); String uri = request.getRequestURI(); long duration = System.currentTimeMillis() - startTime; log.info("uri: " + uri + ", duration: " + duration / 100 + "ms"); return null; } }
第4章 微服务通用模块开发
4-1 关于通用模块功能的介绍
4-2 统一响应处理的开发
CommonResponseDataAdvice.java
import com.imooc.ad.annotation.IgnoreResponseAdvice; import com.imooc.ad.vo.CommonResponse; import org.springframework.core.MethodParameter; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpResponse; import org.springframework.lang.Nullable; import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; @RestControllerAdvice public class CommonResponseDataAdvice implements ResponseBodyAdvice<Object> { @Override @SuppressWarnings("all") public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) { if (methodParameter.getDeclaringClass().isAnnotationPresent( IgnoreResponseAdvice.class )) { return false; } if (methodParameter.getMethod().isAnnotationPresent( IgnoreResponseAdvice.class )) { return false; } return true; } @Nullable @Override @SuppressWarnings("all") public Object beforeBodyWrite(@Nullable Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) { CommonResponse<Object> response = new CommonResponse<>(0, ""); if (null == o) { return response; } else if (o instanceof CommonResponse) { response = (CommonResponse<Object>) o; } else { response.setData(o); } return response; } }
4-3 统一异常处理的开发
自定义AdException类。
GlobalExceptionAdvice.java
import com.imooc.ad.exception.AdException; import com.imooc.ad.vo.CommonResponse; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import javax.servlet.http.HttpServletRequest; @RestControllerAdvice public class GlobalExceptionAdvice { @ExceptionHandler(value = AdException.class) public CommonResponse<String> handlerAdException(HttpServletRequest req, AdException ex) { CommonResponse<String> response = new CommonResponse<>(-1, "business error"); response.setData(ex.getMessage()); return response; } }
4-4 统一配置的开发
定义http消息转换器(将Java对象转换为http的输出流)。
WebConfiguration.java
import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import java.util.List; @Configuration public class WebConfiguration implements WebMvcConfigurer { @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { converters.clear(); converters.add(new MappingJackson2HttpMessageConverter()); } }
第5章 广告投放系统的开发
5-1 Spring IOC和MVC基础知识
5-2 SpringBoot 常用功能特性介绍
启动的方法还有两种:
定时任务:
5-3 广告投放系统数据表设计
第7章 广告检索系统 - 广告数据索引的设计与实现
7-1 广告数据索引设计介绍
7-2 广告数据索引维护介绍
7-3 推广计划索引对象定义与服务实现
IndexAware.java
package com.imooc.ad.index; public interface IndexAware<K, V> { V get(K key); void add(K key, V value); void update(K key, V value); void delete(K key, V value); }
索引对象 AdPlanObject.java
package com.imooc.ad.index.adplan; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.util.Date; @Data @NoArgsConstructor @AllArgsConstructor public class AdPlanObject { private Long planId; private Long userId; private Integer planStatus; private Date startDate; private Date endDate; public void update(AdPlanObject newObject) { if (null != newObject.getPlanId()) { this.planId = newObject.getPlanId(); } if (null != newObject.getUserId()) { this.userId = newObject.getUserId(); } if (null != newObject.getPlanStatus()) { this.planStatus = newObject.getPlanStatus(); } if (null != newObject.getStartDate()) { this.startDate = newObject.getStartDate(); } if (null != newObject.getEndDate()) { this.endDate = newObject.getEndDate(); } } }