Spring [boot] 使用技巧集合-不断积累

目录

-1、调试三板斧-定位问题或扫除问题

0、项目更换环境 删除 .mvn 文件试试

1、Spring  boot 如何允许跨域访问

2、Spring boot发布到tomcat

3、Spring boot 测试启动在项目外围

4、spring boot 结合 mybitas后如何打印sql语句

5、spring boot 整合 mock

6、Spring 提供的 url-页面 的现成的方法-无需业务逻辑处理

7、Spring validate 检测实体

8、Spring Boot  devtool 环境配置、自动构建

9、 SpringBoot 自动将 Date 类型参数 转化为指定类型到前端

10、Spring代码中获取yml文件中的配置信息

11、传入单个参数

12、使用jar包启动

13、SpringBoot 指定 profile

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

17、Unable to find main class

18、SpringBoot 引入 xml 配置

19、fastjson/Gson

20、全局异常捕获(返回JSON)

21、guava

22、lombok

23、拦截器

24、启动系统任务

25、SpringBoot 整合 Servlet、Filter、Listener

26、路径映射

27、SpringBoot 结合 AOP

28、SpringBoot 配置 mybatis

29、SpringBoot 配置测试

30、整合 Mybatis

31、Springboot Controller 请求入参为实体+postMan测试

32、SpringBoot 集合 Redis(单机)

33、SpringBoot 配置 Redis缓存

34、devTool 的配置

35、判空工具包

36、日志


-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>

36、日志



SpringBoot的日志_威少总冠军的博客-CSDN博客_springboot 日志

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值