SpringBoot 入门

SpringBoot

Banner

在线生成地址

// 在springboot项目 resources 目录下新建 banner.txt 文件
// 将结果拷贝
    #     #          #         #                      #   #   #        #        #
    ##   ###         ##  ########                     ##  ##  ##       ###########          ##
    ##   ##          ##       ##                      ##  ##  ##       ##  ##  ##          ####
   ##   ##    #     ##       ##                       ##  ##  ##       ##########          ####
   #    ########    ## #    #                         ##  ##  ## #     ##  ##  ##          ####
  ###  ## #  ##   #######   ##                      ###############    ##########          ####
  ### #   ## #      ## ##   ## #                      ##  ##  ##       #   ##  #           ####
 # ##   # ##        ## ##########                     ##  ##  ##         ##  ##             ##
   ##   #####      ## ##    ##        ##              ##  ##  ##        ##    ###           ##
   ##  ##### #     ## ##    ##       ####             ##  ##  ##       ####   # ####        ##
   ##  ## ## ##     ###     ##       ####             ##  ######     ##  ##   ## ##
   ## ##  ##  ##     ###    ##        ##              ##  #   #          ##   ##            ##
   ###    ##  #     ## ##   ##         #              ##                 ##   ##           ####
   ##     ##       ##  ## # ##        #               ##        #       ##    ##            ##
   ##   ####       #   #   ###       #               #############      #     ##
   #      #       #         #                         #                #      #

运行后
在这里插入图片描述

// 修改启动类可操作显示/关闭banner
SpringApplicationBuilder builder = new SpringApplicationBuilder(D1Application.class);
        builder.bannerMode(Banner.Mode.LOG).run(args); // 关闭/显示 banner

编码

<!--pom.xml-->
<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
</properties>
# yaml 配置
#解决返回乱码问题
server:
	servlet:
		encoding:
			charset: UTF-8
			force: true
			enabled: true

配置https

// jdk 安装目录 /bin 打开cmd
	   -alias 别名
    -keypass 指定生成密钥的密码
    -keyalg 指定密钥使用的加密算法(如 RSA)
    -keysize 密钥大小
    -validity 过期时间,单位天
    -keystore 指定存储密钥的密钥库的生成路径、名称
    -storepass 指定访问密钥库的密码


keytool -genkeypair -alias tomcat_https -keypass 123456 -keyalg RSA -keysize 1024 -validity 365 -keystore d:/tomcat_https.keystore -storepass 123456

// 生成的文件放在 resources 目录下
# 配置
#https默认端口:443,http默认端口:80
server:
	port: 4439
	http-port: 8082
	#开启https,配置跟证书一一对应
	ssl:
		enabled: true
		#指定证书
		key-store: classpath:tomcat_https.keystore
		key-store-type: JKS
		#密码
		key-store-password: 123456

可能有报错,maven执行clear再运行

// 配置http重指向https
@Configuration
public class SSLUtils {
    @Bean
    TomcatServletWebServerFactory tomcatServletWebServerFactory(){
        TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory(){
            @Override
            protected void postProcessContext(Context context){
                SecurityConstraint constraint = new SecurityConstraint();
                constraint.setUserConstraint("CONFIDENTIAL");
                SecurityCollection collection = new SecurityCollection();
                collection.addPattern("/*");
                constraint.addCollection(collection);
                context.addConstraint(constraint);
            }
        };
        factory.addAdditionalTomcatConnectors(createTomcatConnertor());
        return factory;
    }
    private Connector createTomcatConnertor(){
        Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
        connector.setScheme("http0");
        connector.setPort(8082);
        connector.setSecure(false);
        connector.setRedirectPort(4439);
        return connector;
    }
}

区分开发/生产环境

# application.yaml
spring:
  profiles:
  	# 区分开发 / 生产
    active: dev  # prod
  application:
	# 应用名称
    name: d1
#https默认端口:443,http默认端口:80
server:
  # http/https 端口
  port: 4439
  http-port: 8082
  #开启https,配置跟证书一一对应
  ssl:
    enabled: true
    #指定证书
    key-store: classpath:tomcat_https.keystore.old
    key-store-type: JKS
    #密码
    key-store-password: 123456
  servlet:
    # utf-8 配置
    encoding:
      charset: UTF-8
      force: true
      enabled: true
book: # 自定义配置
  name: 测试
  author: 999



# application-dev.yaml
server:
  servlet:
    # 请求前缀
    context-path: /dev-api



# application-prod.yaml
server:
  servlet:
    # 请求前缀
    context-path: /prod-api

自定义配置读取

@Component
@ConfigurationProperties(prefix = "book")
public class BookConfig {
    private String name;
    private String author;
	// get,set,tostring
}


// 使用
@Autowired
BookConfig bookConfig;

整合 Thymeleaf

<!--pom.xml中-->
 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
spring:
  # thymeleaf 配置
  thymeleaf:
    # 是否开启缓存,开发时可设置为false,默认true
    cache: true
    # 检查模板是否存在,默认true
    check-template: true
    # 检查模板位置是否存在,默认true
    check-template-location: true
    # 模板文件编码
    encoding: UTF-8
    # 模板位置
    prefix: classpath:/templates/
    # Content-Type 配置
    servlet:
      content-type: text/html
    # 模板文件后缀
    suffix: .html
// 新建 User
public class User {
    private Integer id;
    private String username;
    private String password;
	// get,set
}
 // Controller
  @GetMapping("/users")
    public ModelAndView users(){
        List<User> users = new ArrayList<>();
        User u = new User(1,"搜索","123455");
        User u1 = new User(2,"刚刚","321123");
        User u2 = new User(3,"哈哈","555551");
        users.add(u);
        users.add(u1);
        users.add(u2);
        ModelAndView mv = new ModelAndView();
        mv.addObject("users",users);
        mv.setViewName("users");
        return mv;
    }
<!--resources/templates/users.html   新建文件--> 
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div>
    <div th:each="user:${users}">
        <span th:text="${user.id}"></span>
        <span th:text="${user.username}"></span>
        <span th:text="${user.password}"></span>
    </div>
</div>
</body>
</html>

整合 FreeMarker

<!--pom.xml中-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>
spring:
  freemarker:
    # HttpServletRequest 的属性是否可以覆盖 controller 中的 model 的同明项
    allow-request-override: false
    # HttpSession 的属性是否可以覆盖 controller 中的 model 的同明项
    allow-session-override: false
    # 是否开启缓存,开发时可设置为false,默认true
    cache: false
    # 模板文件编码
    charset: UTF-8
    # 检查模板位置是否存在,默认true
    check-template-location: true
    # Content-Type 配置
    content-type: text/html
    # HttpServletRequest 的属性是否添加到 model
    expose-request-attributes: false
    # HttpSession 的属性是否添加到 model
    expose-session-attributes: false
    # 模板文件后缀
    suffix: .ftl
    # 模板位置
    template-loader-path: classpath:/templates/
 // Controller 同上
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div>
    <#if users ??&& (users?size>0)>
        <#list users as user>

            <span>${user.id}</span>
            <span>${user.username}</span>
            <span>${user.password}</span>

        </#list>

    </#if>
</div>
</body>
</html>

整合 Web 开发

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

返回JSON

1.这个依赖默认加入了 json 处理器
在方法上加注解 @ResponseBody 或 在类上使用 @ResponseController
@ResponseController 等同于 @ResponseBody @Controller
2. 自定义json处理器
Gson
fastjson

静态访问

  1. 在 resources/static 新建文件夹下面放静态文件
  2. 自定义静态文件策略
spring:
  mvc:
    static-path-pattern: /static/**
  resources:
    static-locations: classpath:/static/

单文件上传

# yaml 配置
spring:
  servlet:
    multipart:
      # 单文件上传最大
      max-file-size: 10MB
      # 多文件上传最大
      max-request-size: 100MB
<!--upload.html-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>单文件上传</title>
</head>
<body>
<form action="/dev-api/upload" method="post" enctype="multipart/form-data">
  <input type="file" name="uploadFile" value="选择文件" />
  <input type="submit" value="上传" />
</form>
</body>
</html>
@RestController
public class FileUploadController {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd/");
    private String uploadPath = "/target/classes/static/uploadFile/";
    @PostMapping("/upload")
    public String upload(MultipartFile uploadFile, HttpServletRequest req) {
        String realPath = System.getProperty("user.dir")+uploadPath;
        String format = sdf.format(new Date());
        File folder = new File(realPath + format);
        System.out.println(folder.isDirectory());
        if (!folder.isDirectory()) {
            folder.mkdirs();
        }
        String oldName = uploadFile.getOriginalFilename();
        String newName = UUID.randomUUID().toString() + oldName.substring(oldName.lastIndexOf("."), oldName.length());
        try {
            uploadFile.transferTo(new File(folder, newName));
            String filePath = req.getScheme() + "://" + req.getServerName() + ":" + req.getServerPort() + "/dev-api/static/uploadFile/" + format + newName;
            return filePath;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "失败";
    }
}

多文件上传

<!--uploads.html-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>多文件上传</title>
</head>
<body>
<form action="/dev-api/uploads" method="post" enctype="multipart/form-data">
  <input type="file" name="uploadFiles" value="选择文件" multiple/>
  <input type="submit" value="上传" />

</form>
</body>
</html>

    @PostMapping("/uploads")
    public List<String> uploads(MultipartFile[] uploadFiles, HttpServletRequest req) {
        List<String> strings = new ArrayList<>();
        for (MultipartFile uploadFile : uploadFiles) {
            strings.add(this.upload(uploadFile, req)); // 调用单文件上传
        }
        return strings;
    }

全局异常处理

@ControllerAdvice
public class CustomExceptionHandler {
    @ExceptionHandler(MaxUploadSizeExceededException.class)
    public void upload(MaxUploadSizeExceededException e, HttpServletResponse resp) throws IOException {
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter out = resp.getWriter();
        out.write("上传文件大小限制");
        out.flush();
        out.close();
    }
}

全局数据

@ControllerAdvice
public class GlobalConfig {
    @ModelAttribute(value = "info")
    public Map<String,String> userInfo(){
        HashMap<String,String> map = new HashMap<>();
        map.put("id","0");
        map.put("ids","01");
        return map;
    }
}
@GetMapping("/hello")
    public String hello(Model model){
        Map<String,Object> map = model.asMap();
        Map<String,Object> maps = model.asMap();
        Set<String> ket = map.keySet();
        Iterator<String> its = ket.iterator();
        Map s = null;
        while (its.hasNext()){
            String k = its.next();
            Object v = map.get(k);
            if (k.equals("info")){
                s = (Map) v;
            }
        }
        return (String) s.get("id");
    }

请求参数预处理

/ccc?u.id=1&b.id=9

    @GetMapping("/ccc")
    public String ccc(@ModelAttribute("u") User user,@ModelAttribute("b") Bian bian){
        return user.toString()+">>"+bian.toString();
    }
@ControllerAdvice
public class GlobalConfig {
    @InitBinder("u")
    public void init(WebDataBinder webDataBinder){
        webDataBinder.setFieldDefaultPrefix("u.");
    }
    @InitBinder("b")
    public void init2(WebDataBinder webDataBinder){
        webDataBinder.setFieldDefaultPrefix("b.");
    }
}

错误页

1.在 resources/static 下新建error
在这里插入图片描述
2. 自定义 error数据

@Component
public class MyErrorAttribute extends DefaultErrorAttributes {
    @Override
    public Map<String, Object> getErrorAttributes(WebRequest webRequest, ErrorAttributeOptions options) {
        Map<String,Object> errorAttr = super.getErrorAttributes(webRequest,options);
        errorAttr.put("zdy","错误了");
        errorAttr.remove("error");
        return errorAttr;
    }
}
  1. 自定义视图
@Component
public class MyErrorViewResolver implements ErrorViewResolver {
    @Override
    public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) {
        ModelAndView mv = new ModelAndView("errorPage");
        mv.addObject("zdy","错误了");
        mv.addAllObjects(model);
        return mv;
    }
}
<!--resources/templates/errorPage.html-->
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
  <meta charset="UTF-8">
  <title>error</title>
</head>
<body>
<div>
  自定义视图
  <div>timestamp: <span th:text="${timestamp}"></span></div>
  <div>status: <span th:text="${status}"></span></div>
  <div>error: <span th:text="${error}"></span></div>
  <div>messages: <span th:text="${#messages}"></span></div>
  <div>path: <span th:text="${path}"></span></div>
  <div>zdy: <span th:text="${zdy}"></span></div>
</div>
</body>
</html>

  1. 完全自定义 (包含2,3)
@Controller
public class MyErrorController extends BasicErrorController {
    @Autowired
    public MyErrorController(ErrorAttributes errorAttributes, ServerProperties serverProperties,List<ErrorViewResolver> errorViewResolvers) {
        super(errorAttributes, serverProperties.getError(),errorViewResolvers);
    }

    @Override
    public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
        HttpStatus status = getStatus(request);
        Map<String,Object> model = getErrorAttributes(request,isIncludeStackTrace(request, MediaType.TEXT_HTML));
        model.put("zdy","错误了???????");
        ModelAndView modelAndView = new ModelAndView("errorPage",model,status);
        return modelAndView;
    }

    @Override
    public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
        Map<String,Object> body = getErrorAttributes(request,isIncludeStackTrace(request,MediaType.ALL));
        body.put("zdy","错误了?????123123??");
        HttpStatus status = getStatus(request);
        
        return new ResponseEntity<>(body,status);
    }
}

CORS 支持

Controller 类加注解 @CrossOrigin

xml 配置

public class Hello {
    public String sayHellos(String name){
        return "hellos "+name;
    }
}
<!--resources/beans.xml-->
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean class="com.Hello" id="hello"></bean>
</beans>
    @Autowired
    Hello hello;
    @GetMapping("/beans")
    public String beans(){
        return hello.sayHellos("啊啊啊啊啊");
    }

拦截器

public class MyInterceptor1 implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("MyInterceptor1---preHandle");
        return true; // true 才会往下执行
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("MyInterceptor1---postHandle");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("MyInterceptor1---afterCompletion");
    }
}
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptor1())
                .addPathPatterns("/**")   // 拦截的路径
                .excludePathPatterns("/hello");  // 排除路径
    }
}

启动系统任务

  1. CommandLineRunner
    启动任务是加入
    123 3565 999
@Component
@Order(1) // 执行顺序
public class MyCommandLineRunner2 implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        System.out.println("MyCommandLineRunner2---"+ Arrays.toString(args));
    }
}



@Component
@Order(2) // 执行顺序
public class MyCommandLineRunner1 implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        System.out.println("MyCommandLineRunner1---"+ Arrays.toString(args));
    }
}
  1. ApplicationRunner
    启动任务是加入
    –a=a --b=b 123 3565 999
@Component
@Order(1)
public class MyApplicationRunner2 implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        List<String> nonOptionArgs = args.getNonOptionArgs();
        System.out.println("2-nonOptionArgs"+nonOptionArgs);
        Set<String> optionsNames = args.getOptionNames();
        for (String optionsName : optionsNames){
            System.out.println("2-key:"+optionsName+";value:"+args.getOptionValues(optionsName));
        }
    }
}



@Component
@Order(2)
public class MyApplicationRunner1 implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        List<String> nonOptionArgs = args.getNonOptionArgs();
        System.out.println("1-nonOptionArgs"+nonOptionArgs);
        Set<String> optionsNames = args.getOptionNames();
        for (String optionsName : optionsNames){
            System.out.println("1-key:"+optionsName+";value:"+args.getOptionValues(optionsName));
        }
    }
}

整合 Servlet Filter Listener

// 启动类上加注解
@ServletComponentScan
@WebServlet("/my")
public class MyServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("name>>>>>"+req.getParameter("name"));
    }
}



@WebFilter("/*")
public class MyFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("MyFilter>>init");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("MyFilter>>doFilter");
        filterChain.doFilter(servletRequest,servletResponse);
    }

    @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");
    }
}

路径映射

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/sun").setViewName("999"); // 第一个:路径  第二个:模板  
    }
}
<!--resources/templates/999.html-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
999999
</body>
</html>

配置 AOP

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
// service 
@Service
public class UserService {
    public List<User> users(User user){
        List<User> users = new ArrayList<>();
        users.add(user);
        return users;
    }
}



@Component
@Aspect
public class LogAspect {

    @Pointcut("execution(* com.example.d1.service.*.*(..))")
    public void pcl(){}

    @Before(value = "pcl()")
    public void before(JoinPoint jp){
        String name = jp.getSignature().getName();
        System.out.println(name+"方法执行开始");
    }

    @After(value = "pcl()")
    public void after(JoinPoint jp){
        String name = jp.getSignature().getName();
        System.out.println(name+"方法执行结束");
    }

    @AfterReturning(value = "pcl()",returning = "result")
    public void afterReturning(JoinPoint jp,Object result){
        String name = jp.getSignature().getName();
        System.out.println(name+"方法返回值为:"+result);
    }

    @AfterThrowing(value = "pcl()",throwing = "e")
    public void afterThrowing(JoinPoint jp,Exception e){
        String name = jp.getSignature().getName();
        System.out.println(name+"方法抛异常为:"+e.getMessage());
    }

    @Around("pcl()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        return pjp.proceed();
    }

}



@CrossOrigin
@RestController
public class UserController {
    @Autowired
    UserService userService;

    @GetMapping("/ceshilog")
    public List<User> getUserService() {
        return userService.users(new User(1,"ceshi","9999"));
    }
}

ico

在 resources/static/ 添加 favicon.ico

去除某个自动配置

启动类上添加注解 @EnableAutoConfiguration(exclude = {某个类.class})

持久层技术

JdbcTemplate

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency> <!--数据库驱动-->
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
         <dependency><!--  数据库连接池-->
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>
# 数据库配置
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    url: jdbc:mysql:///ssm
    username: root
    password: 521314

在这里插入图片描述

public class Ccc {
    private int id;
    private String name;
    private String author;
	// get,set...
}
@Repository
public class CccDao {
    @Autowired
    JdbcTemplate jdbcTemplate;

    public int addCcc(Ccc ccc){
        return jdbcTemplate.update("INSERT INTO ccc(name,author) VALUES (?,?)",ccc.getName(),ccc.getAuthor());
    }

    public int updateCcc(Ccc ccc){
        return jdbcTemplate.update("UPDATE ccc SET name =?,author=? WHERE id=?",ccc.getName(),ccc.getAuthor(),ccc.getId());
    }
    
    public int delCcc(int id){
        return jdbcTemplate.update("DELETE FROM ccc WHERE id=?",id);
    }

    public Ccc getIdCcc(int id){
        return jdbcTemplate.queryForObject("select * from ccc book where id=?",new BeanPropertyRowMapper<>(Ccc.class),id);
    }
    
    public List<Ccc> getCcc(int id){
        return jdbcTemplate.query("select * from ccc",new BeanPropertyRowMapper<>(Ccc.class));
    }
}



@Service
public class CccService {
    @Autowired
    CccDao cccDao;

    public int addCcc(Ccc ccc){
        return cccDao.addCcc(ccc);
    }

    public int updateCcc(Ccc ccc){
        return cccDao.updateCcc(ccc);
    }

    public int delCcc(int id){
        return cccDao.delCcc(id);
    }

    public Ccc getIdCcc(int id){
        return cccDao.getIdCcc(id);
    }

    public List<Ccc> getCcc(){
        return cccDao.getCcc();
    }
}


@Autowired
    CccService cccService;
    @GetMapping("/ceshi")
    public String indexs(){
        System.out.println("添加:::"+cccService.addCcc(new Ccc("哈哈哈","发发撒顶起")));
        System.out.println("修改:::"+cccService.updateCcc(new Ccc(1,"11111","gasfasfafa")));
        System.out.println("删除:::"+cccService.delCcc(1));
        System.out.println("id:::"+cccService.getIdCcc(2));
        System.out.println("List:::"+cccService.getCcc());
        return "999";
    }
多数据源配置
spring:
  datasource:
    one:
      datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        url: jdbc:mysql:///ssm
        username: root
        password: 521314
    two:
      datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        url: jdbc:mysql:///bk
        username: root
        password: 521314
// 根据配置生成两个数据源
@Configuration
public class DataSourceConfig {
    @Bean
    @ConfigurationProperties("spring.datasource.one")
    DataSource dsOne(){
        return DruidDataSourceBuilder.create().build();
    }
    @Bean
    @ConfigurationProperties("spring.datasource.two")
    DataSource dsTwo(){
        return DruidDataSourceBuilder.create().build();
    }
}
// 配置jdbcTemplate
@Configuration
public class JdbcTemplateConfig {
    @Bean
    JdbcTemplate jdbcTemplateOne(@Qualifier("dsOne")DataSource dataSource){
        return new JdbcTemplate(dataSource);
    }
    @Bean
    JdbcTemplate jdbcTemplateTwo(@Qualifier("dsTwo")DataSource dataSource){
        return new JdbcTemplate(dataSource);
    }
}
	// Dao 注入JdbcTemplate 时切换
    @Resource(name = "jdbcTemplateTwo")
    JdbcTemplate jdbcTemplate;

MyBatis

类/表与上面一样

 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>	<!--mybatis-->
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.4</version>
        </dependency>
        <dependency> <!--数据库驱动-->
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency><!--        数据库连接池-->
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    url: jdbc:mysql:///ssm
    username: root
    password: 521314
mybatis:
  mapper-locations: classpath:mapper/*.xml

在这里插入图片描述


@Mapper
public interface CccMapper {
    int addCcc (Ccc ccc);
    int updateCcc (Ccc ccc);
    int delCcc (int id);
    Ccc getIdCcc (int id);
    List<Ccc> ListCcc ();
}



@Service
public class CccService {
    @Autowired
    CccMapper cccMapper;

    public int addCcc(Ccc ccc){
        return cccMapper.addCcc(ccc);
    }

    public int updateCcc(Ccc ccc){
        return cccMapper.updateCcc(ccc);
    }

    public int delCcc(int id){
        return cccMapper.delCcc(id);
    }

    public Ccc getIdCcc(int id){
        return cccMapper.getIdCcc(id);
    }

    public List<Ccc> getCcc(){
        return cccMapper.ListCcc();
    }
}



@CrossOrigin
@RestController
public class CccController {
    @Autowired
    CccService cccService;

    @GetMapping("/ceshilog")
    public String cehsi() {
        System.out.println("添加:::"+cccService.addCcc(new Ccc("哈哈哈","发发撒顶起")));
        System.out.println("修改:::"+cccService.updateCcc(new Ccc(6,"11111","gasfasfafa")));
        System.out.println("删除:::"+cccService.delCcc(2));
        System.out.println("id:::"+cccService.getIdCcc(6));
        System.out.println("List:::"+cccService.getCcc());
        return "999";
    }
}

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.d2.mapper.CccMapper">

    <insert id="addCcc" parameterType="com.example.d2.Ccc">
        insert into ccc(name,author) values (#{name},#{author})
    </insert>

    <update id="updateCcc" parameterType="com.example.d2.Ccc">
        UPDATE ccc SET name =#{name},author=#{author} WHERE id=#{id}
    </update>

    <delete id="delCcc" parameterType="int">
        DELETE FROM ccc WHERE id=#{id}
    </delete>

    <select id="getIdCcc" parameterType="int" resultType="com.example.d2.Ccc">
        select * from ccc where id=#{id}
    </select>

    <select id="ListCcc" resultType="com.example.d2.Ccc">
        select * from ccc
    </select>
</mapper>

多数据源配置

在这里插入图片描述

spring:
  datasource:
    one:
      type: com.alibaba.druid.pool.DruidDataSource
      jdbc-url: jdbc:mysql:///ssm
      username: root
      password: 521314
    two:
      type: com.alibaba.druid.pool.DruidDataSource
      jdbc-url: jdbc:mysql:///bk
      username: root
      password: 521314
@Configuration
@MapperScan(basePackages = "com.example.d2.mapper", sqlSessionFactoryRef = "OneSqlSessionFactory")//basePackages:接口文件的包路径
public class OneDataSourceConfig {

    @Bean(name = "OneDataSource")
    // 表示这个数据源是默认数据源
    @Primary//这个一定要加,如果两个数据源都没有@Primary会报错
    @ConfigurationProperties(prefix = "spring.datasource.one")//我们配置文件中的前缀
    public DataSource getOneDateSource() {
        return DataSourceBuilder.create().build();
    }


    @Bean(name = "OneSqlSessionFactory")
    @Primary
    public SqlSessionFactory OneSqlSessionFactory(@Qualifier("OneDataSource") DataSource datasource)
            throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(datasource);
        bean.setMapperLocations(
                new PathMatchingResourcePatternResolver().getResources("classpath*:xml/mapper/CccMapper.xml"));
        return bean.getObject();// 设置mybatis的xml所在位置
    }


    @Bean("OneSqlSessionTemplate")
    // 表示这个数据源是默认数据源
    @Primary
    public SqlSessionTemplate OneSqlSessionTemplate(
            @Qualifier("OneSqlSessionFactory") SqlSessionFactory sessionfactory) {
        return new SqlSessionTemplate(sessionfactory);
    }

}


@Configuration
@MapperScan(basePackages = "com.example.d2.mapperTwo", sqlSessionFactoryRef = "TwoSqlSessionFactory")
public class TwoDataSourceConfig {

    @Bean(name = "TwoDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.two")
    public DataSource getTwoDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "TwoSqlSessionFactory")
    public SqlSessionFactory TwoSqlSessionFactory(@Qualifier("TwoDataSource") DataSource datasource)
            throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(datasource);
        bean.setMapperLocations(
                new PathMatchingResourcePatternResolver().getResources("classpath*:xml/mapper/CccMapper2.xml"));
        return bean.getObject();// 设置mybatis的xml所在位置
    }

    @Bean("TwoSqlSessionTemplate")
    public SqlSessionTemplate TwoSqlSessionTemplate(
            @Qualifier("TwoSqlSessionFactory") SqlSessionFactory sessionfactory) {
        return new SqlSessionTemplate(sessionfactory);
    }
}


@Mapper
public interface CccMapper {
    int addCcc (Ccc ccc);
    int updateCcc (Ccc ccc);
    int delCcc (int id);
    Ccc getIdCcc (int id);
    List<Ccc> ListCcc ();
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.d2.mapper.CccMapper">

    <insert id="addCcc" parameterType="com.example.d2.Ccc">
        insert into ccc(name,author) values (#{name},#{author})
    </insert>

    <update id="updateCcc" parameterType="com.example.d2.Ccc">
        UPDATE ccc SET name =#{name},author=#{author} WHERE id=#{id}
    </update>

    <delete id="delCcc" parameterType="int">
        DELETE FROM ccc WHERE id=#{id}
    </delete>

    <select id="getIdCcc" parameterType="int" resultType="com.example.d2.Ccc">
        select * from ccc where id=#{id}
    </select>

    <select id="ListCcc" resultType="com.example.d2.Ccc">
        select * from ccc
    </select>
</mapper>

@Mapper
public interface CccMapper2 {
    int addCcc (Ccc ccc);
    int updateCcc (Ccc ccc);
    int delCcc (int id);
    Ccc getIdCcc (int id);
    List<Ccc> ListCcc ();
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.d2.mapperTwo.CccMapper2">

    <insert id="addCcc" parameterType="com.example.d2.Ccc">
        insert into ccc(name,author) values (#{name},#{author})
    </insert>

    <update id="updateCcc" parameterType="com.example.d2.Ccc">
        UPDATE ccc SET name =#{name},author=#{author} WHERE id=#{id}
    </update>

    <delete id="delCcc" parameterType="int">
        DELETE FROM ccc WHERE id=#{id}
    </delete>

    <select id="getIdCcc" parameterType="int" resultType="com.example.d2.Ccc">
        select * from ccc where id=#{id}
    </select>

    <select id="ListCcc" resultType="com.example.d2.Ccc">
        select * from ccc
    </select>
</mapper>
@Service
public class CccService {
//    @Autowired
//    CccMapper cccMapper; // one   这个位置的切换
    @Autowired
CccMapper2 cccMapper;    // two  这个位置的切换

    public int addCcc(Ccc ccc){
        return cccMapper.addCcc(ccc);
    }

    public int updateCcc(Ccc ccc){
        return cccMapper.updateCcc(ccc);
    }

    public int delCcc(int id){
        return cccMapper.delCcc(id);
    }

    public Ccc getIdCcc(int id){
        return cccMapper.getIdCcc(id);
    }

    public List<Ccc> getCcc(){
        return cccMapper.ListCcc();
    }
}

@CrossOrigin
@RestController
public class CccController {
    @Autowired
    CccService cccService;

    @GetMapping("/ceshilog")
    public String cehsi() {
        System.out.println("添加:::"+cccService.addCcc(new Ccc("哈哈哈","发发撒顶起")));
        System.out.println("List:::"+cccService.getCcc());
        return "999";
    }
}

Spring Data JPA

新建数据库 demo


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.10</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
            <!--排除springboot2默认的数据源HikariCP,使用druid连接池-->
            <exclusions>
                <exclusion>
                    <groupId>com.zaxxer</groupId>
                    <artifactId>HikariCP</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/demo?serverTimezone=Asia/Shanghai&characterEncoding=utf-8
    username: root
    password: 521314
    type: com.alibaba.druid.pool.DruidDataSource
  jpa:
    show-sql: true
    database: mysql
    hibernate:
      ddl-auto: update
server:
  port: 9090

//Book
@Entity(name = "s_book")
public class Book {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    @Column(name = "book_name",nullable = false)
    private String name;
    @Transient   // 生成数据库表时,不生成该字段
    private String ooo;
    // ...set,get
}

//BookDao
public interface BookDao extends JpaRepository<Book,Integer> {

    List<Book> getBooksByNameContaining(String name);

    @Query(value = "select * from s_book where id=(select max(id) from s_book)",nativeQuery = true)
    Book getMaxIdBook();

    @Query(value = "select * from s_book where id>:id",nativeQuery = true)
    List<Book> getBookById(@Param("id") Integer id);
}
//BookService
@Service
public class BookService {
    @Autowired
    BookDao bookDao;
    public Book getMaxIdBook(){
        return bookDao.getMaxIdBook();
    }
    public List<Book> getBookById(Integer id){
        return bookDao.getBookById(id);
    }
}
//BookController
@CrossOrigin
@RestController
public class BookController {
    @Autowired
    BookService bookService;
    @GetMapping("/")
    public String index(){
        System.out.println("getMaxIdBook:::"+bookService.getMaxIdBook());
        System.out.println("getBookById:::"+bookService.getBookById(1));
        return "99";
    }
}
多数据源配置

在这里插入图片描述

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    primary:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://localhost:3306/demo?serverTimezone=Asia/Shanghai&characterEncoding=utf-8
      username: root
      password: 521314
    secondary:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://localhost:3306/bk?serverTimezone=Asia/Shanghai&characterEncoding=utf-8
      username: root
      password: 521314
  jpa:
    show-sql: true
    database: mysql
    hibernate:
      ddl-auto: update
server:
  port: 9090
//DataSourceConfig
/**
 * 数据库配置
 */
@Configuration
public class DataSourceConfig  {

    @Primary
    @Bean(value = "primaryDataSource")
    @ConfigurationProperties("spring.datasource.primary") //标红为yml文件中数据源路径:primary
    public DataSource dataSourceOne(){
        return DruidDataSourceBuilder.create().build();
    }

    @Bean(value = "secondDataSource")
    @ConfigurationProperties("spring.datasource.secondary")//标红为yml文件中数据源路径:secondary
    public DataSource dataSourceTwo(){
        return DruidDataSourceBuilder.create().build();
    }
}
//PrimaryJpaConfig
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "entityManagerFactoryPrimary",
        transactionManagerRef = "transactionManagerPrimary",
        basePackages = {"com.example.d3.one"}) //设置Repository所在位置
public class PrimaryJpaConfig {
    @Autowired
    private JpaProperties jpaProperties;
    @Autowired
    private HibernateProperties hibernateProperties;

    @Autowired
    @Qualifier("primaryDataSource")
    private DataSource primaryDataSource;

    @Primary
    @Bean(name = "entityManagerPrimary")
    public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
        return entityManagerFactoryPrimary(builder).getObject().createEntityManager();
    }

    @Primary
    @Bean(name = "entityManagerFactoryPrimary")
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary(EntityManagerFactoryBuilder builder) {
        return builder
                .dataSource(primaryDataSource)// 设置数据源
                .properties(jpaProperties.getProperties())// 设置jpa配置
                .properties(getVendorProperties())// 设置hibernate配置
                .packages("com.example.d3.etwo") //设置实体类所在位置
                .persistenceUnit("primaryPersistenceUnit")// 设置持久化单元名,用于@PersistenceContext注解获取EntityManager时指定数据源
                .build();
    }

    private Map getVendorProperties() {
        return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());
    }

    @Primary
    @Bean(name = "transactionManagerPrimary")
    public PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject());
    }

}
//SecondJpaConfig
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "entityManagerFactorySecond",
        transactionManagerRef = "transactionManagerSecond",
        basePackages = {"com.example.d3.two"}) //设置Repository所在位置
public class SecondJpaConfig {
    @Autowired
    private JpaProperties jpaProperties;
    @Autowired
    private HibernateProperties hibernateProperties;

    @Autowired
    @Qualifier("secondDataSource")
    private DataSource secondDataSource;

    @Bean(name = "secondEntityManager")
    public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
        return entityManagerFactorySecond(builder).getObject().createEntityManager();
    }

    @Bean(name = "entityManagerFactorySecond")
    public LocalContainerEntityManagerFactoryBean entityManagerFactorySecond(EntityManagerFactoryBuilder builder) {
        return builder
                .dataSource(secondDataSource)
                .properties(jpaProperties.getProperties())// 设置jpa配置
                .properties(getVendorProperties())
                .packages("com.example.d3.etwo") //设置实体类所在位置
                .persistenceUnit("secondPersistenceUnit")
                .build();
    }

    private Map getVendorProperties() {
        return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());
    }

    @Bean(name = "transactionManagerSecond")
    public PlatformTransactionManager transactionManagerSecond(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(entityManagerFactorySecond(builder).getObject());
    }
}
//BookService
@Service
public class BookService {
    @Autowired
    BookDao bookDao;   // 这个位置切换数据源
    public Book getMaxIdBook(){
        return bookDao.getMaxIdBook();
    }
    public List<Book> getBookById(Integer id){
        return bookDao.getBookById(id);
    }
}

整合 redis

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>io.lettuce</groupId>
                    <artifactId>lettuce-core</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>
spring:
  redis:
    # redis 库编号 0-15
    database: 0
    # ip
    host: 192.168.75.129
    # 端口号
    port: 6379
    # 密码
    password: 123456
    jedis:
      pool:
        # 最大连接数
        max-active: 8
        # 最大空闲连接数
        max-idle: 8
        # 最大阻塞等待时间   -1 表示没有限制
        max-wait: -1ms
        # 最小空闲连接数
        min-idle: 0
public class Book implements Serializable {
    private Integer id;
    private String name;
    private String ooo;
	// get / set
}
	@Autowired
    RedisTemplate redisTemplate;
    @Autowired
    StringRedisTemplate stringRedisTemplate;
    @GetMapping("/redis")
    public String Redis(){
        ValueOperations<String,String> opsl = stringRedisTemplate.opsForValue();
        opsl.set("id","1");
        System.out.println(opsl.get("id"));
        ValueOperations ops2 = redisTemplate.opsForValue();
        Book b = new Book();
        b.setId(1);
        b.setName("测名称");
        b.setOoo("sadasdasd");
        ops2.set("book",b);
        Book bd = (Book) ops2.get("book");
        System.out.println(bd);
        return "99";
    }

整合 MongoDB

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>
spring:
  data:
    mongodb:
      authentication-database: admin
      database: admin
      host: 192.168.75.129
      port: 27017
      username: guoguo
      password: 123456
public class Book implements Serializable {
    private Integer id;
    private String name;
    private String ooo;
	// get / set
}
public interface BookMongoDB extends MongoRepository<Book,Integer> {
    List<Book> findByNameContains(String name);
    Book findByNameEquals(String name);
}

@Autowired
    BookMongoDB mongoDB;

    @GetMapping("/mongodb")
    public String mongodb(){
        List<Book> books = new ArrayList<>();
        Book b1 = new Book();
        b1.setOoo("000");
        b1.setName("名称1");
        b1.setId(1);
        Book b2 = new Book();
        b2.setOoo("22222");
        b2.setName("名称2");
        b2.setId(2);
        books.add(b1);
        books.add(b2);
        mongoDB.insert(books);

        System.out.println(mongoDB.findByNameContains("1"));
        System.out.println(mongoDB.findByNameEquals("名称2"));

        return "99";
    }

Session 共享

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>io.lettuce</groupId>
                    <artifactId>lettuce-core</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
        </dependency>
spring:
  redis:
    # redis 库编号 0-15
    database: 0
    # ip
    host: 192.168.75.129
    # 端口号
    port: 6379
    # 密码
    password: 123456
    jedis:
      pool:
        # 最大连接数
        max-active: 8
        # 最大空闲连接数
        max-idle: 8
        # 最大阻塞等待时间   -1 表示没有限制
        max-wait: -1ms
        # 最小空闲连接数
        min-idle: 0
server:
  port: 9091
@Configuration
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 86400 * 30)
public class SessionConfig {
}



/**
 * session共享测试controller
 * 启动两个服务,端口为9090的服务设置session,端口为9091的服务来获取session,测试是否能够获取,实现session共享
 */
@RestController
@RequestMapping("/session")
public class SessionController {

    @Value("${server.port}")
    private Integer port;

    @GetMapping("/set")
    public String set(HttpSession session) {
        session.setAttribute("username", "test");
        return String.valueOf(port);
    }
    
    @GetMapping("/get")
    public String get(HttpSession session) {
        String username = (String) session.getAttribute("username");
        return username + ":" + port;
    }
}

JPA REST

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId> 
        </dependency>
        <!--mysql依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!--jpa依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <!--rest依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-rest</artifactId>
        </dependency>
spring:
  data:
    rest:
      # 每页查询记录数
      default-page-size: 20
      # 分页查询页码参数名
      page-param-name: page
      # 分页查询记录数参数名
      limit-param-name: size
      # 分页查询排序参数名
      sort-param-name: sort
      # 所有请求加上前缀
      base-path: /api
      # 添加成功是否返回添加内容
      return-body-on-create: true
      # 修改成功是否返回修改内容
      return-body-on-update: true
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/bk?serverTimezone=Asia/Shanghai&characterEncoding=utf-8
    username: root
    password: 521314
  jpa:
    show-sql: true
    database: mysql
    hibernate:
      ddl-auto: update
server:
  port: 9090
@Entity(name = "s_book")
public class Book implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    @Column(name = "book_name",nullable = false)
    private String name;
    @Transient   // 生成数据库表时,不生成该字段
    private String ooo;
    // get set
}
public interface BookRepository extends JpaRepository<Book,Integer> {
}
get  http://localhost:9090/books		查询全部  
page=1 size=3 sort=id,desc 第二页  三条记录  id倒叙
get  http://localhost:9090/books/1		根据id查询
post http://localhost:9090/books		新增
put http://localhost:9090/books			修改
delete http://localhost:9090/books/1    根据id删除
@CrossOrigin  // cors
// 自定义路径
@RepositoryRestResource(path = "bs",collectionResourceRel = "bs",itemResourceRel = "b")//exported = true 暴露出来,false不暴露
public interface BookRepository extends JpaRepository<Book,Integer> {
//自定义查询方法
// http://localhost:9090/bs/search/name?name=a
    @RestResource(path = "name",rel = "name",exported = true) //exported = true 暴露出来,false不暴露
    List<Book> findByNameContaining(@Param("name")String name);
}

devtools

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>
# Idea 需要配置
# devtools 默认不会监听静态文件

在这里插入图片描述

# 按 ctrl + shift + alt + /

在这里插入图片描述
在这里插入图片描述

spring:
  devtools:
    restart:
      # 是否关闭自动重启
      enabled: false

缓存

Ehcache 2.x 缓存

 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>
        <dependency>
            <groupId>net.sf.ehcache</groupId>
            <artifactId>ehcache</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
// Book
public class Book implements Serializable {
    private Integer id;
    private String name;
    private String ooo;
    private String uuu;
    // get/set/tostring
}
// BookDao
@Repository
@CacheConfig(cacheNames = "book_cache") // 缓存名称
public class BookDao {
    @Cacheable
    public Book getBookById(Integer id){
        System.out.println("getBookById");
        Book b = new Book();
        b.setId(id);
        b.setName("999as十大");
        b.setOoo("1232");
        return  b;
    }
    @CachePut(key = "#book.id")
    public Book updateBookById(Book book){
        System.out.println("updateBookById");
        book.setOoo("oooooooooo");
        return book;
    }
    @CacheEvict(key = "#id")
    public void delBookById(Integer id){
        System.out.println("delBookById");
    }
}

// 启动类上添加
@EnableCaching // 开启缓存
spring:
  cache:
    ehcache:
      config: classpath:ehcache.xml # 重命名缓存配置文件位置
<!--ehcache.xml-->
<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
    <!--
       diskStore:为缓存路径,ehcache分为内存和磁盘两级,此属性定义磁盘的缓存位置。参数解释如下:
       user.home – 用户主目录
       user.dir  – 用户当前工作目录
       java.io.tmpdir – 默认临时文件路径
     -->
    <diskStore path="java.io.tmpdir/cache"/>
    <!--
       defaultCache:默认缓存策略,当ehcache找不到定义的缓存时,则使用这个缓存策略。只能定义一个。
     -->
    <!--
      name:缓存名称。
      maxElementsInMemory:缓存最大数目
      maxElementsOnDisk:硬盘最大缓存个数。
      eternal:对象是否永久有效,一但设置了,timeout将不起作用。
      overflowToDisk:是否保存到磁盘,当系统当机时
      timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
      timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。
      diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
      diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
      diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
      memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。
      clearOnFlush:内存数量最大时是否清除。
      memoryStoreEvictionPolicy:可选策略有:LRU(最近最少使用,默认策略)、FIFO(先进先出)、LFU(最少访问次数)。
      FIFO,first in first out,这个是大家最熟的,先进先出。
      LFU, Less Frequently Used,就是上面例子中使用的策略,直白一点就是讲一直以来最少被使用的。如上面所讲,缓存的元素有一个hit属性,hit值最小的将会被清出缓存。
      LRU,Least Recently Used,最近最少使用的,缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。
   -->
    <defaultCache
            eternal="false"
            maxElementsInMemory="10000"
            overflowToDisk="false"
            diskPersistent="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            diskExpiryThreadIntervalSeconds="120"/>
    <cache
            name="book_cache"
            eternal="true"
            maxElementsInMemory="10000"
            overflowToDisk="true"
            diskPersistent="true"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            diskExpiryThreadIntervalSeconds="600"/>
</ehcache>

@Autowired
BookDao bookDao;
    @Test
    void contextLoads() {
        bookDao.getBookById(1);
        bookDao.getBookById(1);
        bookDao.delBookById(1);
        Book b3 = bookDao.getBookById(1);
        System.out.println("b3:"+b3);
        Book b = new Book();
        b.setOoo("5555");
        b.setName("123");
        b.setId(1);
        bookDao.updateBookById(b);
        Book b4 = bookDao.getBookById(1);
        System.out.println("b4--"+b4);
    }

Redis 单机缓存

 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>io.lettuce</groupId>
                    <artifactId>lettuce-core</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>
spring:
  cache:
    cache-names: book_cache
    redis:
      time-to-live: 1800s
  redis:
    database: 0
    host: 127.0.0.1
    port: 6379
    password:
    jedis:
      pool:
        max-active: 8
        max-idle: 8
        max-wait: -1ms
        min-idle: 0

启动类注解 @EnableCaching,Book,BookDao同上

@Autowired
    BookDao bookDao;

    @Test
    void contextLoads() {
        bookDao.getBookById(1);
        bookDao.getBookById(1);
        bookDao.delBookById(1);
        Book b3 = bookDao.getBookById(1);
        System.out.println("b3:" + b3);
        Book b = new Book();
        b.setOoo("5789");
        b.setName("9999");
        b.setId(1);
        bookDao.updateBookById(b);
        Book b4 = bookDao.getBookById(1);
        System.out.println("b4--" + b4);
    }

安全管理

Spring-Security 基本使用

 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
spring:
  security:
    user:
      name: admin
      password: 123
      roles: admin
 @Test
    void reg() {
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(10);
        String encodePasswod = encoder.encode("123");
        System.out.println(encodePasswod);
    }
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true,securedEnabled = true)
public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Bean
    PasswordEncoder passwordEncoder(){
//        return NoOpPasswordEncoder.getInstance(); // 明文
        return new BCryptPasswordEncoder(10);
    }
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception{
        auth.inMemoryAuthentication()
                .withUser("root").password("$2a$10$13wlsj3mVvgRkyaM9iUvDu7hecAMPMQkuKD7kGiZ/g3sVp8T3l2MC").roles("ADMIN","DBA")
                .and()
                .withUser("admin").password("$2a$10$13wlsj3mVvgRkyaM9iUvDu7hecAMPMQkuKD7kGiZ/g3sVp8T3l2MC").roles("ADMIN","USER")
                .and()
                .withUser("sun").password("$2a$10$13wlsj3mVvgRkyaM9iUvDu7hecAMPMQkuKD7kGiZ/g3sVp8T3l2MC").roles("USER");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/admin/**")
                .hasRole("ADMIN")
                .antMatchers("/user/**")
                .access("hasAnyRole('ADMIN','USER')")
                .antMatchers("/db/**")
                .access("hasRole('ADMIN') and hasRole('DBA')")
                .anyRequest()
                .authenticated()
                .and()
                .logout()
                .logoutUrl("logout")
                .clearAuthentication(true)
                .invalidateHttpSession(true)
                .addLogoutHandler(new LogoutHandler() {
                    @Override
                    public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {

                    }
                })
                .logoutSuccessHandler(new LogoutSuccessHandler() {
                    @Override
                    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
                        response.sendRedirect("/login_page");
                    }
                })
                .and()
                .formLogin()
                .loginPage("/login_page")
                .loginProcessingUrl("/login")
                .usernameParameter("name")
                .passwordParameter("passwd")
                .successHandler(new AuthenticationSuccessHandler() {
                    @Override
                    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
                        Object principal = authentication.getPrincipal();
                        response.setContentType("application/json;charset=utf-8");
                        PrintWriter out = response.getWriter();
                        response.setStatus(200);
                        Map<String,Object> map = new HashMap<>();
                        map.put("status",200);
                        map.put("msg",principal);
                        ObjectMapper om = new ObjectMapper();
                        out.write(om.writeValueAsString(map));
                        out.flush();
                        out.close();
                    }
                })
                .failureHandler(new AuthenticationFailureHandler(){

                    @Override
                    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
                        response.setContentType("application/json;charset=utf-8");
                        PrintWriter out = response.getWriter();
                        response.setStatus(401);
                        Map<String,Object> map = new HashMap<>();
                        map.put("status",401);
                        if(exception instanceof LockedException){
                            map.put("msg","账号被锁定,登录失败");
                        }else if(exception instanceof BadCredentialsException){
                            map.put("msg","账号名称或密码输入错误");
                        }else if(exception instanceof DisabledException){
                            map.put("msg","账号被禁用");
                        }else if(exception instanceof AccountExpiredException){
                            map.put("msg","账号已过期");
                        }else if(exception instanceof CredentialsExpiredException){
                            map.put("msg","密码已过期");
                        }else{
                            map.put("msg","登录失败");
                        }
                        ObjectMapper om = new ObjectMapper();
                        out.write(om.writeValueAsString(map));
                        out.flush();
                        out.close();
                    }
                })
                .permitAll()
                .and()
                .csrf()
                .disable();
    }
}
@RestController
@CrossOrigin
public class HelloController {
//    @GetMapping("/admin")
//    @Secured("ROLE_ADMIN")
//    public String a(){
//        return "admin角色注解99十大";
//    }
//    @GetMapping("/a1")
//    @PreAuthorize("hasAnyRole('ADMIN','DBA','USER')")
//    public String a1(){
//        return "'ADMIN','DBA','USER'";
//    }
//    @GetMapping("/a2")
//    @PreAuthorize("hasRole('ADMIN') and hasRole('DBA')")
//    public String a2(){
//        return "ADMIN 和 DBA";
//    }
    @GetMapping("/hello")
    public String hello(){
        return "999十大";
    }
    @GetMapping("/admin/hello")
    public String admin(){
        return "admin";
    }
    @GetMapping("/user/hello")
    public String user(){
        return "user";
    }
    @GetMapping("/db/hello")
    public String dba(){
        return "db";
    }
}

Spring-Security 动态权限认证

gitee

WebSocket

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
@Configuration
public class WebSocketConfiguration {
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

@Component
@Slf4j
@ServerEndpoint("/websocket/{userId}")
public class WebSocket {
    //与某个客户端的连接会话,需要通过它来给客户端发送数据
    private Session session;
    /**
     * 用户ID
     */
    private String userId;
    //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
    //虽然@Component默认是单例模式的,但springboot还是会为每个websocket连接初始化一个bean,所以可以用一个静态set保存起来。
    private static CopyOnWriteArraySet<WebSocket> webSockets =new CopyOnWriteArraySet<>();
    // 用来存在线连接用户信息
    private static ConcurrentHashMap<String,Session> sessionPool = new ConcurrentHashMap<String,Session>();

    /**
     * 链接成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam(value="userId")String userId) {
        try {
            this.session = session;
            this.userId = userId;
            webSockets.add(this);
            sessionPool.put(userId, session);
            log.info("【websocket消息】有新的连接,总数为:"+webSockets.size());
        } catch (Exception e) {
        }
    }

    /**
     * 链接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        try {
            webSockets.remove(this);
            sessionPool.remove(this.userId);
            log.info("【websocket消息】连接断开,总数为:"+webSockets.size());
        } catch (Exception e) {
        }
    }
    /**
     * 收到客户端消息后调用的方法
     */
    @OnMessage
    public void onMessage(String message) {
        log.info("【websocket消息】收到客户端消息:"+message);
//        sendAllMessage("此为广播消息:"+message);
        sendOneMessage(this.userId,"此为单点消息:"+message);
//        sendMoreMessage("此为单点消息(多人):"+message);
    }

    /** 发送错误时的处理
     */
    @OnError
    public void onError(Session session, Throwable error) {

        log.error("用户错误,原因:"+error.getMessage());
        error.printStackTrace();
    }


    // 此为广播消息
    public void sendAllMessage(String message) {
        log.info("【websocket消息】广播消息:"+message);
        for(WebSocket webSocket : webSockets) {
            try {
                if(webSocket.session.isOpen()) {
                    webSocket.session.getAsyncRemote().sendText(message);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    // 此为单点消息
    public void sendOneMessage(String userId, String message) {
        Session session = sessionPool.get(userId);
        if (session != null&&session.isOpen()) {
            try {
                log.info("【websocket消息】 单点消息:"+message);
                session.getAsyncRemote().sendText(message);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    // 此为单点消息(多人)
    public void sendMoreMessage(String message) {
        for(WebSocket webSocket:webSockets) {
            Session session = webSocket.session;
            if (session != null&&session.isOpen()) {
                try {
                    log.info("【websocket消息】 单点消息:"+message);
                    session.getAsyncRemote().sendText(message);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

Activemq

 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
@Bean
Queue queue(){
	return new ActiveMQQueue("amq");
}
@Component
public class JmsComponent {
    @Resource
    JmsMessagingTemplate messagingTemplate;

    @Resource
    Queue queue;


    public void send(Message msg){
        messagingTemplate.convertAndSend(this.queue,msg);
    }


    @JmsListener(destination = "amq")
    public void receive(Message msg){
        System.out.println("re:"+msg);
    }


}

class Message implements Serializable{
    private String content;
    private Date date;

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    @Override
    public String toString() {
        return "Message{" +
                "content='" + content + '\'' +
                ", date=" + date +
                '}';
    }
}

@Resource
JmsComponent jmsComponent;

@Test
void contextLoads() {
	Message msg = new Message();
	msg.setContent("hello jms");
	msg.setDate(new Date());
	jmsComponent.send(msg);
}

RabbitMQ

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>
spring:
  rabbitmq:
    host: 127.0.0.1
    port: 5672
    username: guest
    password: guest
@Configuration
public class RabbitmqConfig {

    public static final String QUEUE_ONE = "queue_inform_one";
    public static final String QUEUE_TWO = "queue_inform_two";
    public static final String EXCHANGE_TOPICS_INFORM="exchange_topics_inform";
    public static final String ROUTINGKEY_ONE="inform.#.one.#";
    public static final String ROUTINGKEY_TWO="inform.#.two.#";

    //声明交换机
    @Bean(EXCHANGE_TOPICS_INFORM)
    public Exchange EXCHANGE_TOPICS_INFORM(){
        //durable(true) 持久化,mq重启之后交换机还在
        return ExchangeBuilder.topicExchange(EXCHANGE_TOPICS_INFORM).durable(true).build();
    }

    //声明 one 队列
    @Bean(QUEUE_ONE)
    public Queue QUEUE_INFORM_EMAIL(){
        return new Queue(QUEUE_ONE);
    }
    //声明 two 队列
    @Bean(QUEUE_TWO)
    public Queue QUEUE_INFORM_SMS(){
        return new Queue(QUEUE_TWO);
    }

    //ROUTINGKEY_ONE队列绑定交换机,指定routingKey
    @Bean
    public Binding BINDING_QUEUE_INFORM_EMAIL(@Qualifier(QUEUE_ONE) Queue queue,
                                              @Qualifier(EXCHANGE_TOPICS_INFORM) Exchange exchange){
        return BindingBuilder.bind(queue).to(exchange).with(ROUTINGKEY_ONE).noargs();
    }
    //ROUTINGKEY_TWO队列绑定交换机,指定routingKey
    @Bean
    public Binding BINDING_ROUTINGKEY_SMS(@Qualifier(QUEUE_TWO) Queue queue,
                                          @Qualifier(EXCHANGE_TOPICS_INFORM) Exchange exchange){
        return BindingBuilder.bind(queue).to(exchange).with(ROUTINGKEY_TWO).noargs();
    }

}



@Component
public class ReceiveHandler {
    //监听 one 队列
    @RabbitListener(queues = {RabbitmqConfig.QUEUE_ONE})
    public void receive_email(Object msg, Message message, Channel channel){
        System.out.println("one"+msg);
    }
    //监听 two 队列
    @RabbitListener(queues = {RabbitmqConfig.QUEUE_TWO})
    public void receive_sms(Object msg, Message message, Channel channel){
        System.out.println("two"+msg);
    }
}

邮件 Mail

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>
spring:
  mail:
    host: smtp.qq.com
    username: ***@qq.com # 邮箱
    password: *** # 授权码
    port: 465
    protocol: smtp
    default-encoding: utf-8
    properties:
      mail:
        smtp:
          auth: true
          starttls:
            enable: true
            required: true
          ssl:
            enable: true
          socketFactory:
            port: 465
            class: javax.net.ssl.SSLSocketFactory
@Component
public class MailService {
    @Resource
    JavaMailSender javaMailSender;


    /**
     * 普通邮件
     *
     * @param from    发送人邮箱
     * @param to      接收人邮箱
     * @param cc      抄送人邮箱
     * @param subject 邮箱主题
     * @param content 邮箱内容
     */
    public void sendSimpleMail(String from, String to, String cc, String subject, String content) {
        MimeMessage message = mimeMessage();
        mimeMessageHelper(from, to, cc, subject, content,message);
        javaMailSender.send(message);
    }

    /**
     * 附件邮件
     *
     * @param from    发送人邮箱
     * @param to      接收人邮箱
     * @param cc      抄送人邮箱
     * @param subject 邮箱主题
     * @param content 邮箱内容
     * @param file    邮箱附件
     */
    public void sendAttachFileMail(String from, String to, String cc, String subject, String content, File file) {
        try {
            MimeMessage message = mimeMessage();
            MimeMessageHelper helper = mimeMessageHelper(from, to, cc, subject, content,message);
            helper.addAttachment(file.getName(), file);
            javaMailSender.send(message);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 图片邮件
     *
     * @param from    发送人邮箱
     * @param to      接收人邮箱
     * @param cc      抄送人邮箱
     * @param subject 邮箱主题
     * @param content 邮箱内容
     * @param srcPath 图片路径
     * @param resIds  图片 ID
     */
    public void sendMailImg(String from, String to, String cc, String subject, String content, String[] srcPath, String[] resIds) {
        if (srcPath.length != resIds.length) {
            System.out.println("发送失败");
            return;
        }
        try {
            MimeMessage message = mimeMessage();
            MimeMessageHelper helper = mimeMessageHelper(from, to, cc, subject, content,message);
            for (int i = 0; i < srcPath.length; i++) {
                FileSystemResource res = new FileSystemResource(new File(srcPath[i]));
                helper.addInline(resIds[i], res);
            }
            javaMailSender.send(message);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    private MimeMessage mimeMessage() {
        return javaMailSender.createMimeMessage();
    }

    private MimeMessageHelper mimeMessageHelper(String from, String to, String cc, String subject, String content,MimeMessage message) {
        try {
            MimeMessageHelper helper = new MimeMessageHelper(message, true);
            helper.setFrom(from);
            helper.setTo(to);
            helper.setBcc(cc);
            helper.setSubject(subject);
            helper.setText(content, true);
            return helper;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

@Resource
MailService mailService;
    @Test
void contextLoads() {        mailService.sendSimpleMail("***@qq.com","***@qq.com","***@qq.com","主题9999","内容运行阿三大苏打");
        mailService.sendAttachFileMail("***@qq.com","***@qq.com","***@qq.com","主题99991","查看附件",new File("D:\\README.txt"));
        mailService.sendMailImg("***@qq.com","***@qq.com","***@qq.com","主题图片","<div><img src='cid:p01' /><img src='cid:p02' /></div>",new String[]{"D:\\1.png","D:\\2.png"},new String[]{"p01","p02"});
    }

定时任务

Scheduled

// 启动类
@EnableScheduling   // 开启
@Component
public class MyScheduling {
    // fixedDelay=1000 当前任务执行结束 1s 后开启另一个任务
    // fixedRate=2000  当前任务开始执行 2s 后开启另一个任务
    // initialDelay    首次执行延迟时间
    // cron=* * * * * ?   每秒执行一次
    @Scheduled(fixedDelay = 1000)
    public void test1(){
        System.out.println("test1:"+new Date());
    }
    @Scheduled(fixedRate = 2000)
    public void test2(){
        System.out.println("test2:"+new Date());
    }
    @Scheduled(fixedRate = 2000,initialDelay = 1000)
    public void test3(){
        System.out.println("test3:"+new Date());
    }
    @Scheduled(cron = "* * * * * ?")
    public void test4(){
        System.out.println("cron表达式:"+new Date());
    }
}

Quartz

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-quartz</artifactId>
        </dependency>
spring:
  quartz:
    job-store-type: memory # Job 存储器类型。默认为 memory 表示内存,可选 jdbc 使用数据库。
    auto-startup: true # Quartz 是否自动启动
    startup-delay: 0 # 延迟 N 秒启动
    wait-for-jobs-to-complete-on-shutdown: true # 应用关闭时,是否等待定时任务执行完成。默认为 false ,建议设置为 true
    overwrite-existing-jobs: false # 是否覆盖已有 Job 的配置
    properties: # 添加 Quartz Scheduler 附加属性
      org:
        quartz:
          threadPool:
            threadCount: 25 # 线程池大小。默认为 10 。
            threadPriority: 5 # 线程优先级
            class: org.quartz.simpl.SimpleThreadPool # 线程池类型
@Slf4j
public class FirstJob extends QuartzJobBean {
    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        String now = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(LocalDateTime.now());
        log.info("当前的时间: " + now);
    }
}

@Slf4j
public class SecondJob extends QuartzJobBean {

    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        String now = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(LocalDateTime.now());
        log.info("SecondJob执行, 当前的时间: " + now);
    }
}

@Configuration // 自动
public class QuartzConfig {

    private static final String ID = "SUN";

    @Bean
    public JobDetail jobDetail1() {
        return JobBuilder.newJob(FirstJob.class)
                .withIdentity(ID + " 01")
                .storeDurably()
                .build();
    }

    @Bean
    public Trigger trigger1() {
        // 简单的调度计划的构造器
        SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
                .withIntervalInSeconds(5) // 频率
                .repeatForever(); // 次数

        return TriggerBuilder.newTrigger()
                .forJob(jobDetail1())
                .withIdentity(ID + " 01Trigger")
                .withSchedule(scheduleBuilder)
                .build();
    }
}

@Component  // 手动
public class JobInit implements ApplicationRunner {

    private static final String ID = "SUN";

    @Resource
    private Scheduler scheduler;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        JobDetail jobDetail = JobBuilder.newJob(FirstJob.class)
                .withIdentity(ID + " 01")
                .storeDurably()
                .build();
        CronScheduleBuilder scheduleBuilder =
                CronScheduleBuilder.cronSchedule("0/5 * * * * ? *");
        // 创建任务触发器
        Trigger trigger = TriggerBuilder.newTrigger()
                .forJob(jobDetail)
                .withIdentity(ID + " 01Trigger")
                .withSchedule(scheduleBuilder)
                .startNow() //立即執行一次任務
                .build();
        // 手动将触发器与任务绑定到调度器内
        scheduler.scheduleJob(jobDetail, trigger);
    }
}

Knife4j

<dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring-boot-starter</artifactId>
            <version>3.0.3</version>
        </dependency>
spring:
  mvc:
    pathmatch:
      matching-strategy: ant_path_matcher
knife4j:
  enable: true
  basic:
    enable: true
    username: sun
    password: 123
@Configuration
@EnableSwagger2
public class Knife4jConfiguration {
    @Bean(value = "defaultApi2")
    public Docket defaultApi2() {
        String groupName = "1.X版本";
        Docket docket = new Docket(DocumentationType.OAS_30)
                .apiInfo(new ApiInfoBuilder()
                        .title("999999999")
                        .description("文档")
                        .termsOfServiceUrl("https://gitee.com/sunlei0718")
                        .contact(new Contact("sunlei0718", "https://gitee.com/sunlei0718", "2294073848@qq.com"))
                        .version("1.0")
                        .build())
                .securitySchemes(Collections.singletonList(HttpAuthenticationScheme.JWT_BEARER_BUILDER
                        .name("Authorization")//页面展示字段
                        .build()))
                .securityContexts(Collections.singletonList(SecurityContext.builder()
                        .securityReferences(Collections.singletonList(SecurityReference.builder()
                                .scopes(new AuthorizationScope[0])
                                .reference("Authorization")
                                .build()))
                        .operationSelector(o -> o.requestMappingPattern().matches("/.*"))// 声明作用域
                        .build()))
                //分组名称
                .groupName(groupName)
                .select()
                //这里指定Controller扫描包路径
                .apis(RequestHandlerSelectors.basePackage("com.example.demowebsocket.controller"))
                .paths(PathSelectors.any())
                .build();
        return docket;
    }
}

@Data
@ToString
@ApiModel(value = "测试",description = "描述")
public class Ceshi {
    @ApiModelProperty(value = "id")
    private Integer id;
    @ApiModelProperty(value = "用户名称")
    private String name;
    @ApiModelProperty(value = "密码")
    private String pass;
}

@RestController
@CrossOrigin
@Api(tags = "测试接口999")
public class ccccontroller {
    @GetMapping("/get")
    @ApiOperation(value = "get查询",notes = "备注")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query",name="id",value="ID",required = true,defaultValue = "1")
    })
    public String get(@RequestParam Integer id){
        return "99"+id;
    }

    @GetMapping("/cget")
    @ApiIgnore
    public String cget(@RequestParam Integer id){
        return "99"+id;
    }

    @PostMapping("/p")
    @ApiOperationSupport(ignoreParameters = {"id"})
    @ApiOperation(value = "post新增",notes = "备注")
    public String p(@RequestBody Ceshi id){
        return "99"+id;
    }
    @PutMapping("/put")
    @ApiOperation(value = "修改",notes = "备注")
    public String pd(@RequestBody Ceshi id){
        return "99"+id;
    }
}

Validation

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>

统一返回

public interface StatusCode {
    public int getCode();
    public String getMsg();
}
public enum ResultCode implements StatusCode{
    SUCCESS(1000, "请求成功"),
    FAILED(1001, "请求失败"),
    VALIDATE_ERROR(1002, "参数校验失败"),
    RESPONSE_PACK_ERROR(1003, "response返回包装失败");

    private int code;
    private String msg;

    ResultCode(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    @Override
    public int getCode() {
        return this.code;
    }

    @Override
    public String getMsg() {
        return this.msg;
    }
}

@Data
public class ResultVo {
    // 状态码
    private int code;

    // 状态信息
    private String msg;

    // 返回对象
    private Object data;

    // 手动设置返回vo
    public ResultVo(int code, String msg, Object data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    // 默认返回成功状态码,数据对象
    public ResultVo(Object data) {
        this.code = ResultCode.SUCCESS.getCode();
        this.msg = ResultCode.SUCCESS.getMsg();
        this.data = data;
    }

    // 返回指定状态码,数据对象
    public ResultVo(StatusCode statusCode, Object data) {
        this.code = statusCode.getCode();
        this.msg = statusCode.getMsg();
        this.data = data;
    }

    // 只返回状态码
    public ResultVo(StatusCode statusCode) {
        this.code = statusCode.getCode();
        this.msg = statusCode.getMsg();
        this.data = null;
    }
}
@Data
public class User{
    @NotNull(message = "用户id不能为空")
    private Long id;

    @NotNull(message = "用户账号不能为空")
    @Size(min = 6, max = 11, message = "账号长度必须是6-11个字符")
    private String account;

    @NotNull(message = "用户密码不能为空")
    @Size(min = 6, max = 11, message = "密码长度必须是6-16个字符")
    private String password;

    @NotNull(message = "用户邮箱不能为空")
    @Email(message = "邮箱格式不正确")
    private String email;
}


@RestController
@Validated
public class ValidController {
    @PostMapping("/findByVo")
    public ResultVo findByVo(@Valid @RequestBody User vo) {
        return new ResultVo("999");
    }
    @PostMapping("/findByVo1")
    public ResultVo findByVo1(@Validated User vo, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            List<String> ls = new ArrayList();
         List<ObjectError> list =  bindingResult.getAllErrors();
            for (ObjectError o : list) {
                ls.add(o.getDefaultMessage());
            }
            return new ResultVo(ls);
        }
        return new ResultVo("999");
    }
    @GetMapping("/findByVo12")
    public ResultVo findByVo12(@NotNull(message="id不能为空") Integer id) {
        return new ResultVo("999");
    }
}

异常拦截

@ControllerAdvice
@ResponseBody
public class GlobleExceptionHandler {
    /**
     * 处理 json 请求体调用接口对象参数校验失败抛出的异常
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResultVo jsonParamsException(MethodArgumentNotValidException e) {
        BindingResult bindingResult = e.getBindingResult();
        List errorList = new ArrayList();

        for (FieldError fieldError : bindingResult.getFieldErrors()) {
            String msg = String.format("%s%s;", fieldError.getField(), fieldError.getDefaultMessage());
            errorList.add(msg);
        }
        return new ResultVo(errorList);
    }


    /**
     * 处理单个参数校验失败抛出的异常
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public ResultVo ParamsException(ConstraintViolationException e) {

        List errorList = new ArrayList();
        Set<ConstraintViolation<?>> violations = e.getConstraintViolations();
        for (ConstraintViolation<?> violation : violations) {
            errorList.add(violation.getMessageTemplate());
        }
        return new ResultVo(errorList);
    }

    /**
     * handlerMapping  接口不存在跑出异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(NoHandlerFoundException.class)
    public ResultVo noHandlerFoundException(NoHandlerFoundException e) {
        return new ResultVo(e.getMessage());
    }

    /**
     *
     * @param e 未知异常捕获
     * @return
     */
    @ExceptionHandler(Exception.class)
    public ResultVo UnNoException(Exception e) {
        return new ResultVo(e.getMessage());
    }
}

操作日志

<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.41</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
@Data
@ToString
public class WebLog { // 操作日志
    /**
     * 描述信息
     */
    private String description;
    /**
     * URL
     */
    private String URL;
    /**
     * 请求方式
     */
    private String manner;
    /**
     * 请求方法
     */
    private String method;
    /**
     * IP
     */
    private String IP;
    /**
     * 请求参数
     */
    private String req;
    /**
     * 响应参数
     */
    private String res;
    /**
     * userID 操作人 id
     */
    private Integer userid;
}
@Data
@ToString
public class User {
    private Integer id;
    private String user;
    private String name;
}
@Data
public class ResultVo<T> {
    private Integer code;
    private String msg;
    private T data;
    public ResultVo(T data){
        this.code = 200;
        this.msg = "成功";
        this.data = data;
    }
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface LogPrint {
    String description() default "";
}
@Aspect
@Component
@Slf4j
public class LogPrintAspect {
    private static final String LINE_SEPARATOR = System.lineSeparator();


//    @Pointcut("@annotation(com.example.demoaop.LogPrint)")
//    //@Pointcut("execution(* com.example.demoaop.controller.*.*(..))")
//    public void logPrint() {
//    }

    /**
     * 请求完成后执行
     */
    @AfterReturning(pointcut = "@annotation(com.example.demoaop.LogPrint)",returning = "jsonResult")
    public void doAfterReturnibng(JoinPoint joinPoint, Object jsonResult) throws Throwable {
        log.info("=========================================== 执行操作日志 ===========================================");
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        String methodDescription = getAspectLogDescription(joinPoint);
        // 打印请求 url
        log.info("URL            : {}", request.getRequestURL().toString());
        // 打印描述信息
        log.info("描述信息    : {}", methodDescription);
        // 打印 Http method
        log.info("请求方式    : {}", request.getMethod());
        // 打印调用 controller 的全路径以及执行方法
        log.info("执行方法   : {}.{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
        // 打印请求的 IP
        log.info("IP             : {}", request.getRemoteAddr());
        // 打印请求入参
        log.info("请求参数   : {}", getParams(joinPoint));
        log.info("请求返回   : {}", JSON.toJSONString(jsonResult));
        log.info("=========================================== 结束操作日志 ===========================================");
    }

    /**
     * 在切点之前
     * @param joinPoint
     * @throws Throwable
     */
//    @Before("logPrint()")
//    public void doBefore(JoinPoint joinPoint) throws Throwable {
//        log.info("=========================================== 进入请求 ===========================================");
//        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
//        HttpServletRequest request = attributes.getRequest();
//        String methodDescription = getAspectLogDescription(joinPoint);
//        // 打印请求 url
//        log.info("URL            : {}", request.getRequestURL().toString());
//        // 打印描述信息
//        log.info("描述信息    : {}", methodDescription);
//        // 打印 Http method
//        log.info("请求方式    : {}", request.getMethod());
//        // 打印调用 controller 的全路径以及执行方法
//        log.info("执行方法   : {}.{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
//        // 打印请求的 IP
//        log.info("IP             : {}", request.getRemoteAddr());
//        // 打印请求入参
//        log.info("请求参数   : {}", getParams(joinPoint));
//    }

    /**
     * 在切点之后
     */
//    @After("logPrint()")
//    public void doAfter() throws Throwable {
//        // 接口结束后换行,方便分割查看
//        log.info("=========================================== 请求完成 ===========================================" + LINE_SEPARATOR);
//    }

    /**
     * 环绕
     */
//    @Around("logPrint()")
//    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
//        long startTime = System.currentTimeMillis();
//        Object result = proceedingJoinPoint.proceed();
//        // 打印出参
//        log.info("返回参数  : {}", JSONObject.toJSONString(result));
//        // 执行耗时
//        log.info("响应时间 : {} ms", System.currentTimeMillis() - startTime);
//        return result;
//    }


    public String getAspectLogDescription(JoinPoint joinPoint)
            throws Exception {
        String targetName = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] arguments = joinPoint.getArgs();
        Class targetClass = Class.forName(targetName);
        Method[] methods = targetClass.getMethods();
        StringBuilder description = new StringBuilder("");
        for (Method method : methods) {
            if (method.getName().equals(methodName)) {
                Class[] clazzs = method.getParameterTypes();
                if (clazzs.length == arguments.length) {
                    description.append(method.getAnnotation(LogPrint.class).description());
                    break;
                }
            }
        }
        return description.toString();
    }

    private String getParams(JoinPoint joinPoint) {
        String params = "";
        if (joinPoint.getArgs() != null && joinPoint.getArgs().length > 0) {
            for (int i = 0; i < joinPoint.getArgs().length; i++) {
                Object arg = joinPoint.getArgs()[i];
                if ((arg instanceof HttpServletResponse) || (arg instanceof HttpServletRequest)
                        || (arg instanceof MultipartFile) || (arg instanceof MultipartFile[])) {
                    continue;
                }
                try {
                    params += JSONObject.toJSONString(joinPoint.getArgs()[i]);
                } catch (Exception e1) {
                    log.error(e1.getMessage());
                }
            }
        }
        return params;
    }
}
@RestController
@CrossOrigin
public class asdasd {
    @GetMapping("/cgg")
    public String gg(){
        return "99:";
    }
    @PostMapping("/findByVo")
    @LogPrint(description = "测试json验证")
    public ResultVo findByVo(@RequestBody User vo) {
        return new ResultVo("999");
    }
    @PostMapping("/findByVo1")
    @LogPrint(description = "测试form验证")
    public ResultVo findByVo1(User vo) {
        return new ResultVo("999");
    }
    @GetMapping("/findByVo12")
    @LogPrint(description = "测试单个验证")
    public ResultVo findByVo12(Integer id) {
        return new ResultVo("999");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它提供了一种简化的方法来配置和部署应用程序,使开发人员能够更快地开发和运行应用程序。 Spring Boot Actuator是Spring Boot的一个组件,它可以帮助我们监控和管理Spring Boot应用程序,包括健康检查、审计、统计和HTTP追踪等功能。要使用Spring Boot Actuator,只需引入相应的起步依赖,并在应用程序的入口点类上添加@SpringBootApplication注解即可。在该类使用@SpringBootApplication注解相当于同时添加了@Configuration、@EnableAutoConfiguration和@ComponentScan注解,它标识了当前应用程序是一个Spring Boot应用程序。要启动Spring Boot应用程序,只需在主启动类编写main函数,通过调用SpringApplication.run(Application.class, args)方法来启动应用程序。在开发过程,<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [SpringBoot入门](https://blog.csdn.net/weixin_45905210/article/details/121712027)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *2* [spring boot 入门](https://blog.csdn.net/zhshx19900318/article/details/129476812)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值