目录
4、spring boot 结合 mybitas后如何打印sql语句
6、Spring 提供的 url-页面 的现成的方法-无需业务逻辑处理
8、Spring Boot devtool 环境配置、自动构建
9、 SpringBoot 自动将 Date 类型参数 转化为指定类型到前端
14、SpringBoot Idea 2020 Maven 地址改不了
15、使用默认统一版本管理 spring-boot-starter-parent
16、启动类所在module引入 的 Starter spring-boot-starter-web,普通module引入 spring-boot-starter
spring-boot-start(Spring 基本功能,注入等)
spring-boot-start-web(web服务,端口配置,启动等)
@SpringBootApplication 和 @EnableAutoConfiguration、@ComponentScan、@MapperScan
25、SpringBoot 整合 Servlet、Filter、Listener
31、Springboot Controller 请求入参为实体+postMan测试
-1、调试三板斧-定位问题或扫除问题
Maven-reimport
clean install
ctrl+a 刷控制台
0、项目更换环境 删除 .mvn 文件试试
比如更换了IDE 版本,会有一些奇奇怪怪的问题,删除 .mvn 从新点击maven 项目更新按钮即可
1、Spring boot 如何允许跨域访问
第一种办法,使用Springboot的解决方案
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
*全局级别
@Configuration
public class MyWebMvcConfig implements WebMvcConfigurer{
@Override
public void addCorsMappings(CorsRegistry registry){
registry.addMapping("/a/**")
.allowedHeaders("*")//默认允许所有的请求头信息
.allowedMethods("*")//默认支持GET\POST\HEAD
.maxAges(1800)//DELETE、PUT 探测请求 options 验证有效期
.allowedOrigins("http://localhost:8081");
}
}
* 方法级别
@RestController
public class TestController{
@PostMapping("/a")
@CrossOrigin(value="http://localhost:8081",maxAge=1800,allowedHeaders="*")
public String testMathod(String name){
return "receive:"+name;
}
}
第二种办法使用过滤器:
测试中遇到的问题,需要前段跨域访问,使用过滤器设置
extends OncePerRequestFilter
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.setHeader("Content-Type", "application/json");
response.setHeader("Access-Control-Allow-Origin", "*");//允许所以域名访问,*需要换位制定来源,务必注意这里
response.setHeader("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS");//允许的访问方式
response.setHeader("Access-Control-Allow-Headers", "x-requested-with,content-type,auth_token");
response.setHeader("Access-Control-Request-Headers", "x-requested-with,content-type,Accept,自定义header");
response.setHeader("Access-Control-Request-Method", "GET,POST,PUT,DELETE,OPTIONS");
filterChain.doFilter(request, response);
}
2、Spring boot发布到tomcat
正常打包,war,启动,访问的时候需要项目的名字,需要注意的是,Spring boot 天然不支持tomcat 6了,虽然想点别的办法也可以,但是避免麻烦直接使用tomcat8吧
3、Spring boot 测试启动在项目外围
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication(scanBasePackages = "com.bestcxx.stu.blog.*")
@MapperScan("com.bestcxx.stu.blog.broker.repository.mysql")
public class StarterApplication {
public static void main(String[] args) {
SpringApplication.run(StarterApplication.class, args);
}
}
4、spring boot 结合 mybitas后如何打印sql语句
application.yml 文件中配置即可,但是这种模式打印日志会比较多,其实是可以制定打印日志的方法类的, ALT+/会提示,指定到 Mapper类所在包路径即可,#是注释掉
logging:
level:
#root: DEBUG
cn.test.dao: DEBUG
5、spring boot 整合 mock
用于回滚
@Rollback(true)
extends AbstractTransactionalJUnit4SpringContextTests
maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
spring boot 1.4 之前,在测试类上方
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = TestApplication.class) //使用TestApplication作为spring容器加载类
@ActiveProfiles("test") //这边test指配置文件指向spring-test.yml
@Rollback(false) //单元测试配置数据库默认会事务会退 此时强制事务提交
spring boot 1.4之后,在测试类上方
@RunWith(SpringRunner.class)
@SpringBootTest
@WebAppConfiguration
@Rollback(false) //单元测试配置数据库默认会事务会退 此时强制事务提交
余下部分-从新包好了1.4后,类上方的配置
@RunWith(SpringRunner.class)
@SpringBootTest
@WebAppConfiguration
@Rollback(false) //单元测试配置数据库默认会事务会退 此时强制事务提交
public class NameControllerTest extends AbstractTransactionalJUnit4SpringContextTests{
private MockMvc mockMvc;
@Autowired
protected WebApplicationContext wac;
// 该方法在每个方法执行之前都会执行一遍
@Before
public void setUp() throws Exception {
//mockMvc = MockMvcBuilders.standaloneSetup(new NameController()).build();
mockMvc = MockMvcBuilders.webAppContextSetup(wac).build(); //初始化MockMvc对象
}
@Test
public void testAddDeliverAddress() throws UnsupportedEncodingException, Exception {
String responseString = mockMvc.perform(post("/path/") // 请求的url,请求的方法是post
.contentType(MediaType.APPLICATION_JSON) // 数据的格式
.param("a", "a") // 添加参数
.param("phone", "15000000000") // 添加参数
).andExpect(status().isOk()) // 返回的状态是200
.andDo(print()) // 打印出请求和相应的内容
.andReturn().getResponse().getContentAsString(); // 将相应的数据转换为字符串
System.out.println("--------返回的json = " + responseString);
}
}
Spring MVC MOCk:
http://www.cnblogs.com/lyy-2016/p/6122144.html
Maven
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${springframework.version}</version>
</dependency>
测试类
package com.bestcxx.stu.springmvc.controller;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import junit.framework.TestCase;
@DirtiesContext
@WebAppConfiguration//单元测试的时候真实的开启一个web服务
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:spring/springmvc-servlet.xml"})
//@TransactionConfiguration(transactionManager = "defaultTransactionManager",defaultRollback=false)//事务管理
@Rollback(true)
public class HomeControllerTest extends AbstractTransactionalJUnit4SpringContextTests{
@Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
@Before
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); //构造MockMvc
}
@Test
public void testShouHomePage() throws Exception{
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.get("/home"))
.andExpect(MockMvcResultMatchers.view().name("home"))
.andExpect(MockMvcResultMatchers.status().is(MockHttpServletResponse.SC_OK))
.andDo(MockMvcResultHandlers.print())
.andReturn();
TestCase.assertNotNull(result.getModelAndView().getModel().get("user"));
}
}
控制台打印结果:
MockHttpServletRequest:
HTTP Method = GET
Request URI = /home
Parameters = {}
Headers = {}
Handler:
Type = com.bestcxx.stu.springmvc.controller.HomeController
Method = public java.lang.String com.bestcxx.stu.springmvc.controller.HomeController.shouHomePage(java.util.Map<java.lang.String, java.lang.String>)
Async:
Async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = home
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 200
Error message = null
Headers = {}
Content type = null
Body =
Forwarded URL = /WEB-INF/views/home.jsp
Redirected URL = null
Cookies = []
INFO | Scheduler org.springframework.scheduling.quartz.SchedulerFactoryBean#0_$_NON_CLUSTERED paused.
INFO | Scheduler org.springframework.scheduling.quartz.SchedulerFactoryBean#0_$_NON_CLUSTERED shutting down.
INFO | Scheduler org.springframework.scheduling.quartz.SchedulerFactoryBean#0_$_NON_CLUSTERED paused.
INFO | Scheduler org.springframework.scheduling.quartz.SchedulerFactoryBean#0_$_NON_CLUSTERED shutdown complete.
INFO | {dataSource-1} closed
6、Spring 提供的 url-页面 的现成的方法-无需业务逻辑处理
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
/**
* 本类用于处理 不处理数据直接通过url 跳转到 页面的方法
* 默认访问 /login 指向 login.html 页面
* @author wj
*
*/
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter{
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login");
}
}
7、Spring validate 检测实体
Maven 依赖
<!-- validation 校验 开始 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.4.1.Final</version>
</dependency>
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>2.2.4</version>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>javax.el</artifactId>
<version>2.2.4</version>
</dependency>
<!-- validation 校验 结束 -->
Controller层
@ResponseBody
@RequestMapping(value="/model",method={RequestMethod.GET,RequestMethod.POST})
public HashMap<String,Object> model(@Valid @ModelAttribute("usermodel") UserModel usermodel,BindingResult bindingResult){
System.out.println("有userName吗:"+usermodel.getUserName());
HashMap<String,Object> map=new HashMap<String,Object>();
if(bindingResult.hasErrors()){
List<ObjectError> ls=bindingResult.getAllErrors();
for (int i = 0; i < ls.size(); i++) {
System.out.println("error:"+ls.get(i));
map.put("result", "WRONG");
map.put("msg",ls.get(i).getDefaultMessage());
return map;
}
}
map.put("result", "OK");
return map;
}
dto层-UserModel
字符串 @NotBlank 排除空字符串和“”
@NotEmpty 允许空字符串,不允许为“”
整形 @NotNull
public class UserModel implements Serializable{
private static final long serialVersionUID = -2443619924488167195L;
/**使用 notblank 是不允许空字符串的*/
@Size(min=5,message="userName 长度不能小于5")
@NotBlank(message="userName 不允许为空,或者空字符串")
private String userName;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
测试类-mock
package com.bestcxx.stu.springmvc.controller;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
@DirtiesContext
@RunWith(SpringRunner.class) //@RunWith(SpringJUnit4ClassRunner.class) 也是可以的
@WebAppConfiguration //单元测试的时候真实的开启一个web服务
@ContextConfiguration(locations={"classpath:spring/springmvc-servlet.xml"})
//@TransactionConfiguration(transactionManager = "defaultTransactionManager",defaultRollback=false)//事务管理
@Rollback(true)
public class ParameterControllerTest extends AbstractTransactionalJUnit4SpringContextTests{
@Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
@Before
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(wac).build(); //构造MockMvc
}
@Test
public void testModel() throws Exception{
MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.post("/parameterController/model") // 请求的url,请求的方法是post
.contentType(MediaType.APPLICATION_JSON) // 数据的格式
.param("name"," " ) // 增加参数
).andExpect(MockMvcResultMatchers.status().isOk()) // 返回的状态是200
.andDo(MockMvcResultHandlers.print()) // 打印出请求和相应的内容
.andReturn(); // 将相应的数据转换为字符串
System.out.println("--------返回的json = " + mvcResult.getResponse().getContentAsString());
}
}
如果是Spring Boot 测试,@SpringBootTest后面也是可以指定文件位置的,也可以默认不指定
@RunWith(SpringRunner.class)
@SpringBootTest
@WebAppConfiguration
@Rollback(true) //单元测试配置数据库默认会事务会退 此时强制事务提交
8、Spring Boot devtool 环境配置、自动构建
(1)增加maven依赖
<!-- spring-boot热部署 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional><!-- optional=true,依赖不会传递,该项目依赖devtools;之后依赖本项目的项目如果想要使用devtools,需要重新引入 -->
<scope>runtime</scope>
</dependency>
配置文件
默认 application.yml
内容:
spring :
profiles :
active : dev
子配置文件 application-dev.yml
(2)eclipse中开启自动构建功能-会降低开发效率哦
Project-Build Automatically
9、 SpringBoot 自动将 Date 类型参数 转化为指定类型到前端
最简单的方法,在 yml 文件中增加配置,实体类是 java.util.Date ,前端会收到一个字符串
spring:
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
第二种方法是在实体的 date 类型的字段上增加一个注解
@com.fasterxml.jackson.annotation.JsonFormat(timezone = "GMT+8", pattern ="yyyy-MM-dd HH:mm:ss")
private java.util.Date createTime;
10、Spring代码中获取yml文件中的配置信息
> 使用全路径
@Value("${weixinAndAli.wechatNotifyUrl}")
> 在 Bean 配置中加载yml 文件的指定内容
比如下面,获取 yml 文件中 spring.datasource 相关的代码
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource dataSource(){
return new DruidDataSource();
}
11、传入单个参数
@RestController
@RequestMapping("/fee")
@Api(value = "描述信息", description = "描述信息")
public class FeeController{
@GetMapping(value = "query")
@ApiOperation(value = "描述信息")
public FeeInfoQueryResponseVO getFeeInfo(@ApiParam @RequestParam(value="merchantNo",required = true)String merchantNo, HttpServletRequest request,
HttpServletResponse response) {
}
12、使用jar包启动
* 最简单的:
java -jar E:/name-0.0.1-SNAPSHOT.jar
* 指定端口
java -jar E:/name-0.0.1-SNAPSHOT.jar --server.port=8080
* 将输入信息打入日志
java -jar E:/name-0.0.1-SNAPSHOT.jar > E:/my.log &
* 允许后段运行
nohup java -jar E:/name-0.0.1-SNAPSHOT.jar
* 完整展示(指定端口、后端运行、日志输入到指定文件)
nohup java -jar E:/name-0.0.1-SNAPSHOT.jar --server.port=8080 > E:/my.log &
* 后台运行方式(会生成 nohub.out 和 log.file 两个文件)
nohup java -jar xxx.jar > log.file 2>&1 &
13、SpringBoot 指定 profile
> 首先方式有很多种
第一种
# yml 文件中指定 spring.profiles.active=test
# 亦可在 main 方法中SpringApplicationBuilder.application().setAdditionalProfiles("test")
# 亦可在启动时 --spring.profiles.active=test
# 如果是maven 启动,可以添加 -P test
第二种:pom 中指定, 为激活项,这里可以添加 build 从而改变默认的 build 目录
<!--配置环境的profile-->
<profiles>
<!--dev默认激活,使用idea Spring Boot 配置启动工程,需要dev的配置-->
<profile>
<id>dev</id>
<properties>
<environment>dev</environment>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>test</id>
<properties>
<environment>test</environment>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<environment>prod</environment>
</properties>
</profile>
</profiles>
14、SpringBoot Idea 2020 Maven 地址改不了
IDEA创建springboot时Maven home directory修改不起作用_一起码代码-CSDN博客
删除 .mvn 文件 ,然后从新修改 maven 文件刷新即可
15、使用默认统一版本管理 spring-boot-starter-parent
spring-boot-starter-parent 是一个特殊的Starter,提供了一些Maven的默认配置,同时还提供了 dependency-management,可以使开发者在引入其他依赖时不必输入版本号,方便依赖管理。
一般我们会把这个依赖作为 parent,例如
org.springgramework.boot
spring-boot-starter-parent
2.0.4.RELEASE
16、启动类所在module引入 的 Starter spring-boot-starter-web,普通module引入 spring-boot-starter
· spring-boot-starter-web 和 spring-boot-starter 区别
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
包含
<groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId>
spring-boot-start(Spring 基本功能,注入等)
org.springframework.boot:spring-boot
org.springframework.boot:spring-boot-autoconfigure
org.springframework.boot:spring-boot-starter-logging
jakarta.annotation:jakarta.annotation-api
org.springframework:spring-core
org.yaml:snakeyaml
spring-boot-start-web(web服务,端口配置,启动等)
org.springframework.boot:spring-boot-starter
org.springframework.boot:spring-boot-starter-json
org.springframework.boo:spring-boot-starter-tomcat
org.springframework:spring-web
org.springframework:spring-webmvc
————————————————————————
parent 直接指定SpringCloud 版本
<dependencyManagement>
<dependencies>
<!--在主工程中使用 dependencyManagement 声明 Spring Cloud 的版本,
这样工程内的 Module 中引入 Spring Cloud 组件依赖时,就不必在声明组件的版本信息
保证 Spring Cloud 各个组件一致性-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR12</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
module 引入 spring-boot-starter-web
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class StarterApplication {
public static void main(String[] args) {
SpringApplication.run(StarterApplication.class, args);
}
}
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.annotation.*;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@ImportResource(locations = "classpath:spring/*.xml")
@ComponentScan(basePackages = {
"a.b.c",
"d.e.f"
})
@EnableTransactionManagement
public class ApplicationLoader {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(ApplicationLoader.class);
application.run(args);
}
}
然后在启动类上增加注解,看下面
@SpringBootApplication 和 @EnableAutoConfiguration、@ComponentScan、@MapperScan
@SpringBootApplication 包含了 @EnableAutoConfiguration, @EnableAutoConfiguration表示开启自动化配置,比如对于Starter spring-boot-starter-web,表示自动进行Spring和Spring MVC的配置。
@SpringBootApplication 还包含了 @ComponentScan 的功能
第一种方式:
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}, scanBasePackages = "a.b.c.*")
第二种方式:
@ComponentScan(basePackages = {
"a.b.c.1",
"a.b.c.2"
})
@MapperScan 扫描Mapper 不用再使用 @Repository 注解了
@SpringBootApplication(scanBasePackages = "com.bestcxx.stu.blog.*")
@MapperScan("com.bestcxx.stu.blog.broker.repository.mysql")
17、Unable to find main class
Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:2.0.7.RELEASE:repackage (default) on project grocery-product-spu-inner-api: Execution default of goal org.springframework.boot:spring-boot-maven-plugin:2.0.7.RELEASE:repackage failed: Unable to find main class
去掉下面的maven plugin 配置即可
org.springframework.bootspring-boot-maven-plugin
18、SpringBoot 引入 xml 配置
* 在 resources 目录下添加xml文件
* 在配置类中增加@ImportResource("classpath:demo-applicationContext.xml")
19、fastjson/Gson
· fastjson
<!-- fastjson-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.78</version>
</dependency>
<!-- fastjson-->
使用:JSON.toJSONString(response1)
·Gson
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.6</version>
</dependency>
import com.google.gson.*;
import lombok.experimental.UtilityClass;
import java.util.ArrayList;
import java.util.List;
/**
* @Title: 工具类
* @Description: Json 转化相关
* @Version: v1.0
* @Date:2022-04-21
* @Updatedby:
*/
@UtilityClass
public class JsonUtils {
private final Gson GSON = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create();
public String toJson(Object obj) {
return GSON.toJson(obj);
}
public <T> T fromJson(String values, Class<T> cls) {
return GSON.fromJson(values, cls);
}
public <T> List<T> fromListJson(String values, Class<T> cls) {
List<T> list = new ArrayList();
JsonArray array = new JsonParser().parse(values).getAsJsonArray();
for (JsonElement jsonElement : array) {
list.add(GSON.fromJson(jsonElement, cls));
}
return list;
}
}
20、全局异常捕获(返回JSON)
import com.alibaba.fastjson.JSON;
import com.bestcxx.stu.blog.broker.BaseEnum;
import com.bestcxx.stu.blog.broker.BaseResponse;
import com.bestcxx.stu.blog.broker.exception.BaseException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@ControllerAdvice
public class GlobalExceptionResolver {
@ExceptionHandler(RuntimeException.class)
public void globalExceptionResolver(RuntimeException e, HttpServletResponse response) throws IOException {
BaseResponse response1 = null;
if(e instanceof BaseException){
response1 = new BaseResponse(BaseEnum.FAIL.getCode(),e.getMessage());
}else if(e instanceof IllegalArgumentException){
response1 = new BaseResponse(BaseEnum.FAIL.getCode(),e.getMessage());
}
response.setContentType("text/html;charset=utf-8");
PrintWriter printWriter = response.getWriter();
printWriter.write(JSON.toJSONString(response1));
printWriter.flush();
printWriter.close();
}
}
21、guava
<!-- google guava 工具包-->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
使用:Preconditions.checkArgument(Objects.nonNull(userInfo),"访问者为空");
22、lombok
<!-- Lombok 插件-需IDE 安装 Lombok 插件配合使用 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
* Idea 需要安装 lombok 插件
代码层面写完整如下
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TestRequest {
private Long id;
}
23、拦截器
以来 spring-boot-starter-web
* 实现 HandlerInterceptor 接口
实际访问顺序为 preHandle->Controller->postHandle->afterCompletion
/**
*实际访问顺序为 preHandle->Controller->postHandle->afterCompletion
*/
public class MyInterceptor implements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler
){
System.out.println("MyInterceptor=>preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler,ModelAndView mdv
){
System.out.println("MyInterceptor=>postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler,Exception ex
){
System.out.println("MyInterceptor=>afterCompletion");
}
}
* 配置 拦截器
@Configuration
public class WebMvcConfig implements WebMvcConfigurer{
@Override
public void addInterceptors(InterceptorRegistry registry){
registry.addInterceptor(new MyInterceptor())//这里引入自定义的拦截器类
.addPathPatterns("/**")//设置需拦截路径
.excludePathPatterns("/hello");//设置需要排除的路径
}
}
24、启动系统任务
打印参数同 main 方法配置 Environment Program arguments
--name=111 --age=222
打印结果
MyApplicationRunner>>[111]
MyApplicationRunner>>[222]
MyCommandLineRunner>>[--name=111, --age=222]
* 顺序
Order 相同 ApplicationRunner先执行,Order 不同,数小的先执行
* ApplicationRunner
@Component
@Order(1)
public class MyApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
args.getOptionNames().forEach(item->{
System.out.println("MyApplicationRunner>>"+args.getOptionValues(item));
});
}
}
* CommandLineRunner
@Component
@Order(1)//order小的先执行
public class MyCommandLineRunner implements CommandLineRunner {
//打印参数同 main 方法配置 Environment Program arguments,参数为数组
public void run(String... args) throws Exception {
System.out.println("MyCommandLineRunner>>"+ Arrays.toString(args));
}
}
25、SpringBoot 整合 Servlet、Filter、Listener
* 第一步:在启动类增加注解 @ServletComponent
* 第二步:编写具体代码
@WebServlet("/my")
public class MyServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp){
doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp){
System.out.println("name>>>"+reg.getParamter("name"));
}
}
@WebFilter("/*")
public class MyFilter implements Filter{
@Override
public void init(FilterConfig filterConfig){
System.out.println(""MyFilter>>>init);
}
@Override
public void doFilter(ServletRequest req,ServletResponse resp,FilterChain chain) {
System.out.println("MyFilter>>>doFilter");
}
@Override
public void destroy(){
System.out.println("MyFilter>>>destroy");
}
}
@WebListener
public class MyListener implements ServletRequestListener{
@Override
public void requestDestroyed(ServletRequestEvent sre){
System.out.println("MyListener>>>requestDestroyed");
}
@Override
public void requestInitialized(ServletRequestEvent sre){
System.out.println("MyListener>>>requestInitialized");
}
}
26、路径映射
可以使用Controller ,对于无需资源加载可以直接跳转的,比如登陆页,可以直接配置
不过前后端分离场景,这个就没必要了
@Configuration
public class WebMvcConfig implements WebMvcConfigurer{
@OVerride
public void addViewControllers(ViewControllerRegistry registry){
registry.addViewController("/login").setViewName("login");
}
}
27、SpringBoot 结合 AOP
* 第一步:增加Maven依赖
<dependency>
<groupId>org.springgramework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
* 第二步:配置切面
@Component
@Aspect
public class LogAgent{
@Pointcut("execution(* com.bestcxx.stu.*.*(..))")
public void aspect(){}
@Before(value="aspect()")
public void before(JoinPoint jp){
String name = jp.getSignature().getName();
System.out.println(name+"方法开始执行...");
}
@After(value="aspect()")
public void after(JoinPoint jp){
String name = jp.getSignature().getName();
System.out.println(name+"方法执行结束...");
}
@AfterReturn(value="aspect()" ,returning = "result")
public void afterReturning(JoinPoint jp,Object result){
String name=jp.getSignature().getName();
System.out.println(name+"方法返回值"+result)
}
@AfterThrowing(value="aspect()",throwing="e")
public void afterThrowing(JointPoint jp,Exception e){
String name = jp.getSignature().getName();
System.out.println(name+"方法抛出异常,异常是:"+e.getMessage());
}
@Around("aspect()")
public Object around(ProceedingJoinPoint pjp) throws Throwable{
return pjp.proceed();
}
}
28、SpringBoot 配置 mybatis
SringBoot 结合 Mybatiis(mysql+druid+generatorConfix.xml)_༺ bestcxx的专栏 ༻-CSDN博客
29、SpringBoot 配置测试
Maven 依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
Java 代码基础类
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class BaseTest {
}
import com.bestcxx.stu.blog.BaseTest;
import com.bestcxx.stu.blog.broker.repository.mysql.dao.ArticleMapper;
import com.bestcxx.stu.blog.broker.repository.mysql.model.Article;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Date;
public class ArticleMapperTest extends BaseTest {
@Autowired
private ArticleMapper articleMapper;
@Test
public void testInsert(){
Article article = new Article();
article.setContent("测试内容");
article.setCreateTime(new Date());
article.setTilte("测试title");
article.setUpdateTime(new Date());
int result = articleMapper.insert(article);
Assert.assertEquals(1,result);
}
}
30、整合 Mybatis
https://blog.csdn.net/bestcxx/article/details/79387763
31、Springboot Controller 请求入参为实体+postMan测试
入参实体
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TestRequest {
private Long id;
}
Controller层
import com.alibaba.fastjson.JSON;
import com.bestcxx.study.demo.brocker.controller.request.TestRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping(value="/test1")
@Slf4j
public class TestController {
/**
* 使用 @RequestBody注解 ,只接收JSON格式数据,即 raw-JSON 'contentType': 'application/json'
* @param request
*/
@PostMapping(value="/test2")
public void test(@RequestBody TestRequest request){
log.info("request={}",JSON.toJSONString(request));
}
/**
* 使用入参没有注解标注的实体,请求需要为 form-data
* @param request
*/
@PostMapping(value="/test3")
public void test3(TestRequest request){
log.info("request={}",JSON.toJSONString(request));
}
}
* postMan @RequestBody 标注入参实体
* postMan 无注解的入参实体
32、SpringBoot 集合 Redis(单机)
· Maven
<!-- Redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<exclusion>
<groupId>io.letture</groupId>
<artifactId>letture-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Redis -->
yml 配置
spring:
#redis 相关
redis:
database: 0
host: 127.0.0.1
port: 6379
password: 123456
jedis:
pool:
# 最大连接数
max-active: 8
# 最大空闲连接数
max-idle: 8
# 最大阻塞等待时间,-1 无限制
max-wait: -1ms
# 最小空闲连接数
min-idle: 0
Redis 服务demo
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
@Service
public class RedisService<T> {
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private StringRedisTemplate stringRedisTemplate;
public void setStr(String key,String value){
ValueOperations<String, String> valueOperations= stringRedisTemplate.opsForValue();
valueOperations.set(key,value);
}
public <T> void setPO(String key,T t){
ValueOperations valueOperations= redisTemplate.opsForValue();
valueOperations.set(key,t);
}
}
33、SpringBoot 配置 Redis缓存
yml配置
cache-names 是分组,可以设置多个,逗号隔开
spring:
#缓存配置
cache:
#redis 中的 key 都有一个前缀,默认前缀名就是 "缓存名::"
cache-names: article
redis:
time-to-live: 1800s
注解说明
@CacheConfig 指定使用哪一个分组,不指定key,key就是入参 @CachePut(key = "#article.id"),@CachePut 会把返参从新设置为缓存@CacheEvict(key = "#id"),会清楚缓存 @Cacheable 缓存存在就用缓存,否则就查询后加入缓存
import com.bestcxx.stu.blog.broker.repository.mysql.dao.ArticleMapper;
import com.bestcxx.stu.blog.broker.repository.mysql.model.Article;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
@CacheConfig(cacheNames="article")
public class ArticleServiceImpl implements ArticleService{
@Autowired
private ArticleMapper articleMapper;
@CachePut(key = "#article.id")
@Transactional(isolation = Isolation.REPEATABLE_READ,propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
@Override
public Article insert(Article article) throws Exception{
int result = articleMapper.insert(article);
if(result != 1){
throw new Exception("保存失败");
}
return article;
}
@Cacheable
@Override
public Article getArticleById(Long id) {
return articleMapper.selectByPrimaryKey(id);
}
@CachePut(key = "#article.id")
@Transactional(isolation = Isolation.REPEATABLE_READ,propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
@Override
public Article update(Article article) throws Exception {
int result = articleMapper.updateByPrimaryKey(article);
if(result != 1){
throw new Exception("更新失败");
}
return article;
}
@CacheEvict(key = "#id")
@Transactional(isolation = Isolation.REPEATABLE_READ,propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
@Override
public void delete(Long id) throws Exception {
int result = articleMapper.deleteByPrimaryKey(id);
if(result != 1){
throw new Exception("删除失败");
}
}
}
34、devTool 的配置
可以用于idea 本地代码修改时自动重启服务
默认 /META_INF/maven、/META-INF/resources、/resources、/static、/public 以及 /template 位置下的资源变化不会触发重启
maven
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
yml
spring:
devtools:
livereload:
enabled: true
restart:
# 默认 resources 修改不会重启
# 不重启目录排除
exclude: src/main/test
# 重启目录增加
additional-paths: src/main/resources/static
# 使用这种模式,修改项目且修改该文件才会触发重启
trigger-file: .triggle-file
idea 配置
1、File-Settings->Build、Execution、Deployment ->Compiler 勾选 Build project automatically
2、搜Action(快捷键为 Ctrl+Shift+Alt+/): Maintenance
Registry->勾选 compile.autonake.allow.when.app.running
35、判空工具包
> 工具方法集合_༺ bestcxx的专栏 ༻-CSDN博客
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.4</version>
</dependency>