SpringBoot学习笔记
目录
文件目录结构
-
⽬录讲解
- src/main/java:存放代码
- src/main/resources
- static: 存放静态⽂件,⽐如 css、js、image, (访问⽅式 http://localhost:8080/js/main.js)
- templates:存放静态⻚⾯jsp,html,tpl
- config:存放配置⽂件,application.properties
- resources:
- src/main/java:存放代码
-
同个⽂件的加载顺序,静态资源⽂件 Spring Boot 默认会挨个从
-
META/resources >
-
resources >
-
static >
-
public
⾥⾯找是否存在相应的资源,如果有则直接返回,不在默认加载的⽬录,则找不到
-
-
默认配置
spring.resources.static-locations = classpath:/METAINF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/
启动类的位置
- 三种形式
- 当启动类和controller在同⼀类中时,在该类上添加注解@Controller即可;
- 当启动类和controller分开时,启动类要放在根⽬录下,启动类上只需要注解@SpringBootApplication;
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PVxRjjLW-1597395411413)(D:\java\SpringBoot\笔记\resources\image-20200805104753938.png)]
- 当启动类和controller分开时,如果启动类在⾮根⽬录下,需要在启动类中增加注解
- @ComponentScan,并配置需要扫描的包名,如(basePackages = )
- @ComponentScan(basePackages ={“net.xdclass.controller”,“net.xdclass.service”})
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rZq38sc1-1597395411416)(D:\java\SpringBoot\笔记\resources\image-20200805105339374.png)]
SpringBoot利用插件打包
-
Jar⽅式打包启动
-
官⽅推荐,⼯作中最常⽤
-
步骤:pom⽂件新增maven插件
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> 需要指定打包为jar包 如果没有加,则执⾏jar包 ,报错如下 java -jar spring-boot-demo-0.0.1-SNAPSHOT.jar no main manifest attribute, in spring-boot-demo-0.0.1-SNAPSHOT.jar
-
再在控制台执行 mvn:install 即可
-
用Json返回给前端
其实就是业务层Controller
需要定义一个类,使用@Restcontroller注解标识控制层且返回Json(自动序列化为json)
注解@RequestMapping(“url”)配置一级路径,处理任何请求方法
在对应的方法上使用@RequestMapping(“url”)配置耳机路径,处理任何请求方法
为了规范Json返回,一般使用一个包装吧返回数据包装起来
Spring Boot 配置文件注入
⽅式⼀
1、Controller上⾯配置 @PropertySource({“classpath:resource.properties”})
2、取得配置文件的值
@Value("${test.name}")
private String name;
⽅式⼆:实体类配置⽂件
1、添加 @Component 注解;
2、使⽤ @PropertySource 注解指定配置⽂件位置;
3、使⽤ @ConfigurationProperties 注解,设置相关属性;
@Configuration // 指定为配置类 会被Spring进行扫描
@PropertySource(value = "classpath:pay.properties") // 配置配置配置文件
public class WXConfig {
@Value("${wxpay.appid}")
private String payAppid;
4、必须 通过注⼊IOC对象Resource 进来 , 才能在类中使⽤获取的配置⽂件值。
@Autowired
private ServerSettings serverSettings;
测试
@RunWith(SpringRunner.class) 底层⽤junit SpringJUnit4ClassRunner 即是用Spring的Junit框架进行单元测试
@SpringBootTest(classes={DemoProj2Application.class}) 标记启动类 用于启动整个springboot⼯程
若按照规范把Spring Boot 的启动类放在项目根目录的话就不需要配置classes
@AutoConfigureMockMvc 使用MockMVC模拟HTTP请求
@Test
public void testVideListApi() throws Exception {
// 构造HTTP GET 请求
MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.get("/api/v1/pub/video/list"))
.andExpect(MockMvcResultMatchers.status().isOk()).andReturn();// 判断是不是HTTP 200 状态码 并且返回
System.out.println(mvcResult.getResponse().getStatus());
System.out.println(mvcResult.getResponse().getContentAsString());
}
自定义全局异常
编写一个类,标识它是异常处理类,指定针对异常的处理方法,在方法内返回约定的错误码并封装成JSON
@RestControllerAdvice // 标记是异常处理器
public class ExpHandler {
@ExceptionHandler(value = Exception.class)// 指定处理异常的种类 这里是最大的异常类
JsonData handlerException(Exception e, HttpServletRequest request){
return JsonData.buildError("服务端异常", -2);
}
}
过滤器
新建类继承Filter接口,在类上使用注解标记拦截器并指定拦截路径
doFilter进行校验,然后调用filterChain.doFilter(servletRequest,servletResponse) 方法放行
@WebFilter(urlPatterns = "/api/v1/pri/*",filterName = "login")
// 标识拦截器,正则指定拦截路径=所有 /pri 的都拦下
public class LoginFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
filterChain.doFilter(servletRequest,servletResponse);
}
}
前后端场景下登陆状态码
注意要使用ObjectMapper序列化为json数据。
注意要设置responde返回类型为json
resp.setContentType("application/json"); // 设置返回内容类型
监听器
创建监听器只需要实现对应的接口并在类上使用@WebListener注解标识监听器
-
应用上下文监听器:实现ServletContextListener接口
- 监听应用的启动以及销毁
- 可以用于应用初始化的时候进行一些配置文件的初始化的操作
-
会话监听器
- 监听每一个会话
-
请求监听器
- 监听每一个请求
- 可以在请求发生的时候记录日志的操作
@WebListener // 标识监听器
public class ApplicationListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("context listener init ===============");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("context listener destroy ===============");
}
}
拦截器
拦截器:和过滤器⽤途基本类似,拦截器的功能更强大
使⽤步骤
-
新建拦截配置类实现WebMvcConfigurer接口,并使用@Configuration注解
-
重写addInterceptors方法,用于注册拦截器
-
新建拦截类,实现编写拦截器业务代码,需要实现HandlerInterceptor接口
- preHandle:拦截之前执行,登录校验等操作一般在这里
- 返回ture则放行
- postHandle:拦截之后执行
- afterCompletion:postHandle之后执行
- preHandle:拦截之前执行,登录校验等操作一般在这里
-
注册拦截器,在拦截器配置类的addInterceptors方法内,注册拦截器并指定拦截路径
registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/api/v1/pri/**"); // 注册拦截器 并指定拦截路径 // 拦截器结尾必须** // 若拦截某一层目录则配置/*/
- 多个拦截器对同一路径进行拦截的执行顺序:按照注册的顺序执行,先注册,先拦截
定时任务
使用SpringBoot自带定时任务框架实现定时任务
SpringBoot使⽤注解⽅式开启定时任务
-
启动类⾥⾯ @EnableScheduling开启定时任务,⾃动扫描
-
定时任务业务类 加注解 @Component被容器扫描
-
定时执⾏的⽅法加上注解 @Scheduled(fixedRate=2000) 定期(2000ms)执⾏⼀次
若使用注解@Scheduled(fixedDelay = 1000) 则为在上一次结束后间隔时间(1000ms)执行
使用cron表达式指定间隔执行时间 @Scheduled(cron = “*/3 */1 * * * *”) https://tool.lu/crontab/
异步任务
开启异步任务
-
启动类⾥⾯使⽤@EnableAsync注解开启功能,⾃动扫描
-
定义异步任务类并使⽤@Component标记组件被容器扫描
-
使用注解@Async
若注解在类上则标识该类下的全部方法异步进行
若注解在单个方法上则标识该方法异步进行
控制层使用asyncTask.方法名()执行方法
使用Future取得异步任务返回值
**设置返回:**方法的返回值设置为Future,方法返回对象需要使用AsyncResult(“task 5”)包裹
// 使用Future返回异步任务执行完成的结果
@Component
@Async // 标识异步任务
// 加到类上:这个类异步
public class AsyncTask {
public Future task4(){
System.out.println("task4");
try{
Thread.sleep(4000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
// AsyncResult用于包装结果 指定返回类型以及取值
return new AsyncResult<User>(new User(1,"Matsuri","123"));
}
public Future task5(){
System.out.println("task5");
try{
Thread.sleep(4000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
return new AsyncResult<String>("task 5");
}
取得返回值:
- 执行异步方法,获得方法的执行对象Future类型
- 判断异步任务结束 future.idDone()
- 获取返回值future.get()
@GetMapping("future")
public JsonData testFuture(){
long begin = System.currentTimeMillis();
Future future4 = asyncTask.task4();
Future future5 = asyncTask.task5();
User user = null;
// 使用死循环获取异步任务返回结果
for (;;){
// 判断异步任务完成
if (future4.isDone()&&future5.isDone()){
try{
// 获取异步任务的结果
user = (User) future4.get();
System.out.println(user.toString());
String string = (String) future5.get();
System.out.println(string);
}catch (Exception e){
e.printStackTrace();
}finally {
break;
}
}
}
long end = System.currentTimeMillis();
// 将结果封装进map
Map<String,Object> map = new HashMap<>();
map.put("time",end - begin);
map.put("user",user);
return JsonData.buildSuccess(map);
}
e.printStackTrace();
}finally {
break;
}
}
}
long end = System.currentTimeMillis();
// 将结果封装进map
Map<String,Object> map = new HashMap<>();
map.put("time",end - begin);
map.put("user",user);
return JsonData.buildSuccess(map);
}
---