一、技术回顾
1、多线程、线程安全、多线程通讯、java并发包、线程池、
线程池配置多少合适、信号量、锁机制。
2、javase核心只是:反射机制、自定义注解。
3、网络通讯核心:socket、tcp与udp、nio、aio、bio、粘包
netty通讯。
4、jvm核心:垃圾回收算法、新生代和老年代、并行回收、
串行回收、实战调优。
5、javaweb核心:dns解析过程、防止重复提交(token+验证码)、
企业黑名单和白名单系统。
6、重定向与转发原理、跨域解决方案(jsonp(不支持post),nginx搭建网关、
hettpclient转发、SpringCloud zuul搭建网关)、xss攻击、http协议
7、linux节本命令
8、mysql性能优化。读写分离、分库分表、mycat使用、主从复制、慢查询、索引。
9、spring事务:传播行为
10、springioc、生命周期
11、springBoot、SpringMvc、SpringCloud
12、nginx、redis
13、消息中间件(异步、防止阻塞、补偿机制、解决幂等)
activityMQ、RocketMQ、keepalived
14、分布式JOB、XXL-JOB
15、dubbo、dubbox、zookeeper.
二、项目系统架构
网站演变流程(单点系统传统系统)
SpringCloud + SpringBoot (http+Json) 格式来进行传输
三、项目知识点使用技术
注册中心使用Eureka
服务负载均衡使用ribbon
Zuul作为网关
持久层使用mybatis
数据库使用mysql
缓存使用redis
消息中间件使用ActiveMQ
定时任务系统使用xxl-job
四、项目搭建准备
开始要做的准备:
1、设置编码格式:UTF-8
2、设置好maven环境等。
五、搭建项目
首先创建leeue-shop-parent这个父类工程。
创建工具类
创建注册中心 leeue-shop-eureka
application.yml
server:
port: 8761
eureka:
instance:
hostname: localhost
client:
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
启动起来打包放到了云服务器上。
再创建leeue-shop-api 子项目,是专门暴露接口给其他项目来调用的。
在leeue-shop-member实现类中的application.yml文件
server:
port: 8762
# context-path: /member
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
spring:
application:
name: member
五、对ResponseBase进行封装
对返回结果集进行封装 ResponseBase
package com.leeue.base;
/**
* @classDesc: 功能描述:(返回结果集进行封装)
* @author:<a href="leeue@foxmail.com">李月</a>
* @Version:v1.0
* @createTime:2018年12月17日 上午10:07:01
*/
public class ResponseBase {
private Integer rtnCode;
private String msg;
private Object data;
public ResponseBase() {
}
public ResponseBase(Integer rtnCode, String msg, Object data) {
super();
this.rtnCode = rtnCode;
this.msg = msg;
this.data = data;
}
public Integer getRtnCode() {
return rtnCode;
}
public void setRtnCode(Integer rtnCode) {
this.rtnCode = rtnCode;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
对返回结果集再次封装 BaseApiService
package com.leeue.base;
import org.springframework.stereotype.Component;
import com.leeue.constants.Constants;
/**
* @classDesc: 功能描述:(对ResponseBase再进行封装一次)
* @author:<a href="leeue@foxmail.com">李月</a>
* @Version:v1.0
* @createTime:2018年12月17日 上午10:15:16
*/
@Component
public class BaseApiService {
/**
* 通用封装
*
* @param code
* @param msg
* @param data
* @return
*/
public ResponseBase setResult(Integer code, String msg, Object data) {
return new ResponseBase(code, msg, data);
}
/**
* 只返回结果是成功的,没有data值
* @return
*/
public ResponseBase setResultSuccess() {
return setResult(Constants.HTTP_RES_CODE_200, Constants.HTTP_RES_CODE_200_VALUE, null);
}
/**
* 只返回结果是成功的,可以传data值
* @return
*/
public ResponseBase setResultSuccess(Object data) {
return setResult(Constants.HTTP_RES_CODE_200, Constants.HTTP_RES_CODE_200_VALUE, data);
}
/**
* 只返回结果错误,要传msg值
* @return
*/
public ResponseBase setResultError(String msg) {
return setResult(Constants.HTTP_RES_CODE_500, msg, null);
}
}
以后用到的结果集都进行继承的方式来做。
测试
六、封装redis
package com.leeue.base;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
/**
* @classDesc: 功能描述:(封装redis)
* @author:<a href="leeue@foxmail.com">李月</a>
* @Version:v1.0
* @createTime:2018年12月17日 下午1:50:52
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
@Component
public class BaseRedisService {
@Autowired
private StringRedisTemplate stringRedisTemplate;
public void setString(String key, Object data, Long timeout) {
if (data instanceof String) {
String value = (String) data;
stringRedisTemplate.opsForValue().set(key, value);
}
if (timeout != null) {
stringRedisTemplate.expire(key, timeout, TimeUnit.SECONDS);
}
}
public Object getString(String key) {
return stringRedisTemplate.opsForValue().get(key);
}
public void delKey(String key) {
stringRedisTemplate.delete(key);
}
}
lombok安装方法如下:
lombok安装方式
七、集成日志统一管理 AOP
package com.leeue.base;
import java.util.Arrays;
import javax.servlet.http.HttpServletRequest;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
@Aspect
// 申明是个spring管理的bean
@Component
@Slf4j
public class LogAspectServiceApi {
private JSONObject jsonObject = new JSONObject();
// 申明一个切点 里面是 execution表达式
@Pointcut("execution(public * com.leeue.api.service.*.*(..))")
private void controllerAspect() {
}
// 请求method前打印内容
@Before(value = "controllerAspect()")
public void methodBefore(JoinPoint joinPoint) {
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder
.getRequestAttributes();
HttpServletRequest request = requestAttributes.getRequest();
log.info("===============请求内容===============");
try {
// 打印请求内容
log.info("请求地址:" + request.getRequestURL().toString());
log.info("请求方式:" + request.getMethod());
log.info("请求类方法:" + joinPoint.getSignature());
log.info("请求类方法参数:" + Arrays.toString(joinPoint.getArgs()));
} catch (Exception e) {
log.error("###LogAspectServiceApi.class methodBefore() ### ERROR:", e);
}
log.info("===============请求内容===============");
}
// 在方法执行完结后打印返回内容
@AfterReturning(returning = "o", pointcut = "controllerAspect()")
public void methodAfterReturing(Object o) {
log.info("--------------返回内容----------------");
try {
log.info("Response内容:" + jsonObject.toJSONString(o));
} catch (Exception e) {
log.error("###LogAspectServiceApi.class methodAfterReturing() ### ERROR:", e);
}
log.info("--------------返回内容----------------");
}
}