一、苍穹外卖
苍穹外卖
前端工程基于nginx,后端基于maven进行项目构建
sky-pojo中包的作用
名称 | 说明 |
---|---|
Entity | 实体,通常和数据库中的表对应 |
DTO | 数据传输对象,通常用于程序中各层之间传递数据(后端接受的前端传来的数据被转成DTO对象) |
VO | 视图对象,为前端展示数据提供的对象 (返回前端的数据封装为VO对象) |
POJO | 普通Java对象,只有属性和对应的getter和setter |
nginx
前端请求地址:http://localhost/api/employee/login
后端接口地址:http://localhost:8080/admin/employee/login
正向代理
正向代理
代理的为客户端,服务器不知道真实客户的信息。例如:翻墙软件。
反向代理
代理的为服务器端。对于客户来说不知道服务器的信息。例如: nginx
通过在nginx.conf中配置
server{listen 80;server_name localhost;# 处理特定请求,含有/api/的进行处理location /api/{proxy_pass http://localhost:8080/admin/; #反向代理}
}
访问http://localhost/api/employee/login
,nginx会转到http://localhost:8080/admin/
,所以最后的请求地址为http://localhost:8080/admin/employee/login
负载均衡
upstream webservers{server 192.168.100.128:8080;server 192.168.100.129:8080;
}
Swagger
在线生成接口文档
knife4j是为Java MVC框架集成Swagger生成Api文档的增强解决方案
-
导入 knife4j 的maven坐标
在pom.xml中添加依赖
<dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-spring-boot-starter</artifactId> </dependency>
-
在配置类中加入 knife4j 相关配置
WebMvcConfiguration.java
/*** 通过knife4j生成接口文档* @return */@Beanpublic Docket docket() {ApiInfo apiInfo = new ApiInfoBuilder().title("苍穹外卖项目接口文档").version("2.0").description("苍穹外卖项目接口文档").build();Docket docket = new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo).select().apis(RequestHandlerSelectors.basePackage("com.sky.controller")).paths(PathSelectors.any()).build();return docket;}
-
设置静态资源映射,否则接口文档页面无法访问
WebMvcConfiguration.java
/*** 设置静态资源映射* @param registry */ protected void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/");registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/"); }
接口文档访问路径为 http://ip:port/doc.html
—> http://localhost:8080/doc.html
4. 常用注解
注解 | 说明 |
---|---|
@Api(tags=“”) | 用在类上,例如Controller,表示对类的说明 |
@ApiModel(description=“”) | 用在类上,例如entity、DTO、VO |
@ApiModelProperty(“”) | 用在属性上,描述属性信息 |
@ApiOperation(value=“”) | 用在方法上,例如Controller的方法,说明方法的用途、作用 |
JWT
ThreadLocal
ThreadLocal为每个线程提供单独一份存储空间,具有线程隔离的效果,只有在线程内才能获取到对应的值,线程外则不能访问。
常用方法:
- public void set(T value) 设置当前线程的线程局部变量的值
- public T get() 返回当前线程所对应的线程局部变量的值
- public void remove() 移除当前线程的线程局部变量
封装的ThreadLocal操作的工具类
package com.sky.context;public class BaseContext {public static ThreadLocal<Long> threadLocal = new ThreadLocal<>();public static void setCurrentId(Long id) {threadLocal.set(id);}public static Long getCurrentId() {return threadLocal.get();}public static void removeCurrentId() {threadLocal.remove();}}
分页查询
使用 mybatis 的分页插件 PageHelper 来简化分页代码的开发。底层基于 mybatis 的拦截器实现。
<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>${pagehelper}</version>
</dependency>
PageHelper.startPage(employeePageQueryDTO.getPage(), employeePageQueryDTO.getPageSize());
使用OSS进行文件上传
Object Storage Service(OSS,对象存储服务)
Redis
- 基于内存存储,读写性能高
- 适合存储热点数据(热点商品、资讯、新闻)
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
启动
在cmd中
D:\JavaFile\Redis-x64-3.2.100>redis-server.exe redis.windows.conf
停止
ctrl+c
连接服务
D:\JavaFile\Redis-x64-3.2.100>redis-cli.exe -h localhost -p 6379ex
使用Spring Data Redis来简化 Redis 操作。
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
配置类
package com.sky.config;import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;@Configuration
@Slf4j
public class RedisConfiguration {@Beanpublic RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory){log.info("开始创建redis模板对象...");RedisTemplate redisTemplate = new RedisTemplate();//设置redis的连接工厂对象redisTemplate.setConnectionFactory(redisConnectionFactory);//设置redis key的序列化器//默认的key序列化器为JdkSerializationRedisSerializerredisTemplate.setKeySerializer(new StringRedisSerializer());return redisTemplate;}
}
Spring Cache
Spring Cache 是一个框架,实现了基于注解的缓存功能,只需要简单地加一个注解,就能实现缓存功能。
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId> <version>2.7.3</version>
</dependency>
注解 | 说明 |
---|---|
@EnableCaching | 开启缓存注解功能,通常加在启动类上 |
@Cacheable | 在方法执行前先查询缓存中是否有数据,如果有数据,则直接返回缓存数据;如果没有缓存数据,调用方法并将方法返回值放到缓存中 |
@CachePut | 将方法的返回值放到缓存中 |
@CacheEvict | 将一条或多条数据从缓存中删除 |
HttpClient(未整理)
提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。
作用
- 发送HTTP请求
- 接收响应数据
应用场景
扫描支付、查看地图、获取验证码、查看天气等功能
<dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.13</version>
</dependency>
Spring Task
Spring Task 是Spring框架提供的任务调度工具,可以按照约定的时间自动执行某个代码逻辑。
添加注解 @EnableScheduling 开启任务调度
@SpringBootApplication
@EnableTransactionManagement //开启注解方式的事务管理
@Slf4j
@EnableCaching //开启缓存注解
@EnableScheduling// 开启任务调度
public class SkyApplication {public static void main(String[] args) {SpringApplication.run(SkyApplication.class, args);log.info("server started");}
}
实现订单状态定时处理功能
package com.sky.task;import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;import java.util.Date;/*** 自定义定时任务类*/
@Component
@Slf4j
public class MyTask {/*** 定时任务 每隔5秒触发一次*/@Scheduled(cron = "0/5 * * * * ?")public void executeTask(){log.info("定时任务开始执行:{}",new Date());}
}
WebSocket(未整理)
WebSocket 是基于 TCP 的一种新的网络协议。它实现了浏览器与服务器全双工通信——浏览器和服务器只需要完成一次握手,两者之间就可以创建持久性的连接, 并进行双向数据传输。
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
Apache Echarts,Apache POI(未整理)
基于 Javascript 的数据可视化图表库
配置解析
application配置
驼峰命名
mybatis:configuration:#开启驼峰命名map-underscore-to-camel-case: true
拦截器Interceptor
内容见JavaWeb Day12-13
定义拦截器
//自定义拦截器
@Component
public class LoginCheckInterceptor implements HandlerInterceptor {//目标资源方法执行前执行。 返回true:放行 返回false:不放行@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("preHandle .... ");return true; //true表示放行}//目标资源方法执行后执行@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("postHandle ... ");}//视图渲染完毕后执行,最后执行@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("afterCompletion .... ");}
}
注册配置拦截器
@Configuration
public class WebConfig implements WebMvcConfigurer {//自定义的拦截器对象@Autowiredprivate LoginCheckInterceptor loginCheckInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {//注册自定义拦截器对象registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/**");//设置拦截器拦截的请求路径( /** 表示拦截所有请求)}
}
过滤器Filter和拦截器Interceptor的执行时间
-
当我们打开浏览器来访问部署在web服务器当中的web应用时,此时我们所定义的过滤器会拦截到这次请求。拦截到这次请求之后,它会先执行放行前的逻辑,然后再执行放行操作。而由于我们当前是基于springboot开发的,所以放行之后是进入到了spring的环境当中,也就是要来访问我们所定义的controller当中的接口方法。
-
Tomcat并不识别所编写的Controller程序,但是它识别Servlet程序,所以在Spring的Web环境中提供了一个非常核心的Servlet:DispatcherServlet(前端控制器),所有请求都会先进行到DispatcherServlet,再将请求转给Controller。
-
当我们定义了拦截器后,会在执行Controller的方法之前,请求被拦截器拦截住。执行
preHandle()
方法,这个方法执行完成后需要返回一个布尔类型的值,如果返回true,就表示放行本次操作,才会继续访问controller中的方法;如果返回false,则不会放行(controller中的方法也不会执行)。 -
在controller当中的方法执行完毕之后,再回过来执行
postHandle()
这个方法以及afterCompletion()
方法,然后再返回给DispatcherServlet,最终再来执行过滤器当中放行后的这一部分逻辑的逻辑。执行完毕之后,最终给浏览器响应数据。
全局异常处理器
//@RestControllerAdvice = @ControllerAdvice + @ResponseBody
//处理异常的方法返回值会转换为json后再响应给前端
@RestControllerAdvice
public class GlobalExceptionHandler {//处理异常@ExceptionHandler(Exception.class) //指定能够处理的异常类型public Result ex(Exception e){e.printStackTrace();//打印堆栈中的异常信息//捕获到异常之后,响应一个标准的Resultreturn Result.error("对不起,操作失败,请联系管理员");}
}