SpringBoot 第二篇

SpringBoot 第二篇,第1张

SpringBoot 第二篇

一、 SpringBoot整合FreeMarker 1.1 导入依赖

    org.springframework.boot
    spring-boot-starter-freemarker
1.2 在application.properties文件添加配置
########## 配置freemarker ##########
#是否开启缓存
spring.freemarker.cache=false
#路径
spring.freemarker.template-loader-path=classpath:/templates
#文件后缀
spring.freemarker.suffix=.ftl

spring.freemarker.charset=UTF-8
spring.freemarker.content-type=text/html
1.3 创建实体类
package com.qf.pojo;

public class Student {

    private Integer id;
    private String name;
    private Integer age;

    private String address;

    public Student(Integer id, String name, Integer age, String address) {

        this.id = id;
        this.name = name;
        this.age = age;
        this.address = address;
    }

    public Student() {
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {

        return name;
    }

    public void setName(String name) {
        this.name = name;
    }


    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}
1.4在templates目录下创建student.ftl文件(然后把该ftl文件拷贝到D:/ftl目录下,一会用)



    
    Title


    
        
            index
            id
            name
            age
            address
        
        <#list students as student>
            <#if student_index % 2 == 0>
            
                <#else>
            
            
            ${student_index}
            ${student.id}
            ${student.name}
            ${student.age}
            ${student.address}
            
        
    

1.5创建controller
package com.qf.controller;

import com.qf.pojo.Student;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.HashMap;

@Controller
@RequestMapping("/freemarker")
public class FreeMarkerController {

    @RequestMapping("/student")
    public String hello(Model model) throws Exception {

        //创建List集合获取多个元素
        ArrayList students = new ArrayList<>();
        students.add(new Student(1, "jack", 18, "郑州二七"));
        students.add(new Student(2, "rose", 19, "郑州中原"));
        students.add(new Student(3, "tom", 20, "郑州金水"));

        model.addAttribute("students",students);

        return "/student";
    }

    //生成静态页面的方法
    @RequestMapping("createHtml")
    @ResponseBody
    public String createHtml()throws Exception{
        //获取配置对象
        Configuration configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
        //设置字符集
        configuration.setDefaultEncoding("utf-8");

        //设置加载的模版目录
        configuration.setDirectoryForTemplateLoading(new File("D:/ftl"));
        //创建List集合获取多个元素
        ArrayList students = new ArrayList<>();
        students.add(new Student(1,"张三",18,"北京"));
        students.add(new Student(2,"李四",19,"上海"));
        students.add(new Student(3,"王五",20,"广州"));

        //使用map集合加载数据
        HashMap map = new HashMap<>();
        map.put("students",students);

        //创建输出流对象
        FileWriter fileWriter = new FileWriter(new
                File("D:/ftl_html/student.html"));

        //获取加载的模板
        Template template = configuration.getTemplate("student.ftl");
        //生成html文件
        template.process(map,fileWriter);
        //关流
        fileWriter.close();

        return "success";
    }

}

启动工程,进行测试

二、SpringBoot整合Thymeleaf 2.1导入依赖

    org.springframework.boot
    spring-boot-starter-thymeleaf
2.2在application.properties文件添加配置
########## 配置thymeleaf ##########
spring.thymeleaf.cache=false
spring.thymeleaf.encoding=utf-8

spring.thymeleaf.prefix=classpath:/templates

spring.thymeleaf.suffix=.html

spring.thymeleaf.mode=HTML5
spring.thymeleaf.servlet.content-type=text/html
2.3创建实体类
package com.qf.pojo;

import java.util.Date;

public class User {

    private Integer id;
    private String username;
    private String password;

    private Date birthday;

    public User(Integer id, String username, String password, Date birthday) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.birthday = birthday;
    }
    
    public User() {
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + ''' +
                ", password='" + password + ''' +
                ", birthday=" + birthday +
                '}';
    }
}
2.4创建Controller
package com.qf.controller;

import com.qf.pojo.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.ArrayList;
import java.util.Date;

@Controller
@RequestMapping("user")
public class UserController {


    @RequestMapping("findAll")
    public String findAll(Model model) {

        ArrayList users = new ArrayList<>();

        users.add(new User(1001, "张三", "123", new Date()));
        users.add(new User(1002, "李四", "456", new Date()));
        users.add(new User(1003, "王五", "789", new Date()));

        model.addAttribute("users", users);

        return "/list";
    }

    @RequestMapping("findById")
    public String findById(Model model, String uid) {
        System.out.println(uid);

        if (uid.equals("1001")) {
            User user = new User(1001, "张三", "123", new Date());
            model.addAttribute("user", user);
        }

        return "/queryOne";

    }

}
2.5在templates目录下创建list.html以及queryOne.html

list.html




    
    Title






    
        
            
            
            

            
        
    

    
    
        
        
            
            
            
            
        
    
    

    
        
        
            
            
            
            

        
    




序号 姓名 生日 详情 查询

queryOne.html




    
    Title





三、SpringBoot整合Redis 3.1导入依赖

    org.springframework.boot
    spring-boot-starter-data-redis




    org.apache.commons
    commons-pool2




    com.fasterxml.jackson.core
    jackson-databind
    2.12.3
3.2创建application.yml文件并添加配置
spring:
  redis:
    host: 127.0.0.1
    port: 6379
    database: 0
    lettuce:
      pool:
        max-active: 100
3.3创建User类
package com.qf.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

@AllArgsConstructor
@NoArgsConstructor
@Data
public class User implements Serializable {

    private Integer id;
    private String name;

}
3.4导入Redis序列化配置类
package com.qf.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig {

    
    @Bean
    public RedisTemplate redisTemplate(LettuceConnectionFactory connectionFactory) {
        RedisTemplate redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(connectionFactory);
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        redisTemplate.setKeySerializer(stringRedisSerializer); //设置key的序列化方式
        redisTemplate.setHashKeySerializer(stringRedisSerializer);//设置hash类型的数据的key的序列化方式

        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);//非final类型的数据才会被序列化
        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);

        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);//设置value的序列化方式为json
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);

        return redisTemplate;
    }
}
3.5导入Redis工具类
package com.qf.utils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Component
public final class RedisUtil {

    @Autowired
    private RedisTemplate redisTemplate;

    // =============================common============================

    
    public boolean expire(String key, long time, TimeUnit timeUnit) {
        try {
            if (time > 0) {
                redisTemplate.expire(key, time, timeUnit);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    
    public long getExpire(String key) {
        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
    }


    
    public boolean hasKey(String key) {
        try {
            return redisTemplate.hasKey(key);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    
    @SuppressWarnings("unchecked")
    public void del(String... key) {
        if (key != null && key.length > 0) {
            if (key.length == 1) {
                redisTemplate.delete(key[0]);
            } else {
                redisTemplate.delete((Collection) CollectionUtils.arrayToList(key));
            }
        }
    }


    // ============================String=============================

    
    public Object get(String key) {
        return key == null ? null : redisTemplate.opsForValue().get(key);
    }

    

    public boolean set(String key, Object value) {
        try {
            redisTemplate.opsForValue().set(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    

    public boolean set(String key, Object value, long time) {
        try {
            if (time > 0) {
                redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
            } else {
                set(key, value);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    
    public long incr(String key, long delta) {
        if (delta < 0) {
            throw new RuntimeException("递增因子必须大于0");
        }
        return redisTemplate.opsForValue().increment(key, delta);
    }


    
    public long decr(String key, long delta) {
        if (delta < 0) {
            throw new RuntimeException("递减因子必须大于0");
        }
        return redisTemplate.opsForValue().increment(key, -delta);
    }


    // ================================Map=================================

    
    public Object hget(String key, String item) {
        return redisTemplate.opsForHash().get(key, item);
    }

    
    public Map hmget(String key) {
        return redisTemplate.opsForHash().entries(key);
    }

    
    public boolean hmset(String key, Map map) {
        try {
            redisTemplate.opsForHash().putAll(key, map);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    
    public boolean hmset(String key, Map map, long time, TimeUnit timeUnit) {
        try {
            redisTemplate.opsForHash().putAll(key, map);
            if (time > 0) {
                expire(key, time, timeUnit);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    
    public boolean hset(String key, String item, Object value) {
        try {
            redisTemplate.opsForHash().put(key, item, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    
    public boolean hset(String key, String item, Object value, long time, TimeUnit timeUnit) {
        try {
            redisTemplate.opsForHash().put(key, item, value);
            if (time > 0) {
                expire(key, time, timeUnit);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    
    public void hdel(String key, Object... item) {
        redisTemplate.opsForHash().delete(key, item);
    }


    
    public boolean hHasKey(String key, String item) {
        return redisTemplate.opsForHash().hasKey(key, item);
    }


    
    public double hincr(String key, String item, double by) {
        return redisTemplate.opsForHash().increment(key, item, by);
    }


    
    public double hdecr(String key, String item, double by) {
        return redisTemplate.opsForHash().increment(key, item, -by);
    }


    // ============================set=============================

    
    public Set sGet(String key) {
        try {
            return redisTemplate.opsForSet().members(key);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    
    public boolean sHasKey(String key, Object value) {
        try {
            return redisTemplate.opsForSet().isMember(key, value);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    
    public long sSet(String key, Object... values) {
        try {
            return redisTemplate.opsForSet().add(key, values);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }


    
    public long sSetAndTime(String key, long time, TimeUnit timeUnit, Object... values) {
        try {
            Long count = redisTemplate.opsForSet().add(key, values);
            if (time > 0) {
                expire(key, time, timeUnit);
            }
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }


    
    public long sGetSetSize(String key) {
        try {
            return redisTemplate.opsForSet().size(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }


    

    public long setRemove(String key, Object... values) {
        try {
            Long count = redisTemplate.opsForSet().remove(key, values);
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    // ===============================list=================================

    
    public List lGet(String key, long start, long end) {
        try {
            return redisTemplate.opsForList().range(key, start, end);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    
    public long lGetListSize(String key) {
        try {
            return redisTemplate.opsForList().size(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }


    
    public Object lGetIndex(String key, long index) {
        try {
            return redisTemplate.opsForList().index(key, index);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    
    public boolean lSet(String key, Object value) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    
    public boolean lSet(String key, Object value, long time,TimeUnit timeUnit) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            if (time > 0) {
                expire(key, time,timeUnit);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

    }


    
    public boolean lSet(String key, List value) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

    }


    
    public boolean lSet(String key, List value, long time,TimeUnit timeUnit) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            if (time > 0) {
                expire(key, time,timeUnit);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    

    public boolean lUpdateIndex(String key, long index, Object value) {
        try {
            redisTemplate.opsForList().set(key, index, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }


    

    public long lRemove(String key, long count, Object value) {
        try {
            Long remove = redisTemplate.opsForList().remove(key, count, value);
            return remove;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }

    }

} 
3.6在项目自带的测试类中测试 
package com.qf;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.qf.pojo.User;
import com.qf.utils.RedisUtil;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;

@SpringBootTest
class Springboot05RedisApplicationTests {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RedisUtil redisUtil;

    @Test
    void contextLoads() {
        //测试redis中对应的数据类型
//        redisTemplate.opsForValue();// *** 作String
//        redisTemplate.opsForList();// *** 作List
//        redisTemplate.opsForSet();// *** 作Set
//        redisTemplate.opsForZSet();// *** 作ZSet
//        redisTemplate.opsForHash();// *** 作Hash

        //存储字符串
//        redisTemplate.opsForValue().set("username","张三");
//        Object username = redisTemplate.opsForValue().get("username");
//        System.out.println(username);

        //存储对象(使用json方式)
//        User user = new User(1, "李四");
//
//        ObjectMapper objectMapper = new ObjectMapper();
//        String userJson = null;
//        try {
//            userJson = objectMapper.writevalueAsString(user);
//        } catch (JsonProcessingException e) {
//            e.printStackTrace();
//        }
//
//        redisTemplate.opsForValue().set("user",userJson);
//        Object r_user = redisTemplate.opsForValue().get("user");
//        System.out.println(r_user);

        //存储对象(使用实体类序列化方式)
//        User user = new User(2, "王五");
//
//        redisTemplate.opsForValue().set("user",user);
//        Object r_user = redisTemplate.opsForValue().get("user");
//        System.out.println(r_user);

        //使用redis工具类进行 *** 作
        User user = new User(3, "赵六");

        redisUtil.set("user",user);
        Object r_user = redisUtil.get("user");
        System.out.println(r_user);

    }
}
四、SpringBoot整合Quartz以及异步方法调用 4.1 异步方法调用

1.创建AsyncController

package com.qf.controller;

import com.qf.service.AsyncService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("async")
public class AsyncController {

    @Autowired
    private AsyncService asyncService;

    @RequestMapping("testAsync")
    public String testAsync(){

        asyncService.testAsync();

        return "async";
    }
}

2.创建AsyncService

package com.qf.service;

public interface AsyncService {
    void testAsync();
}

3.创建AsyncServiceImpl

package com.qf.service.impl;

import com.qf.service.AsyncService;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

@Service
public class AsyncServiceImpl implements AsyncService {

    @Override
    @Async//指定当前方法为异步方法
    public void testAsync() {

        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("正在执行...");
    }
}

4.在启动上添加开启异步注解,然后测试

package com.qf;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;

@SpringBootApplication
@EnableAsync//开启异步
public class Springboot06Application {

    public static void main(String[] args) {
        SpringApplication.run(Springboot06Application.class, args);
    }

}
4.2使用@Scheduled注解实现定时任务

1.导入日志依赖(使用logback + slf4j ),使用日志输出可以看到线程数


    ch.qos.logback
    logback-classic

2.编写任务类,多个任务执行时,默认使用单线程,可以通过创建线程池和异步两种方式使其改变为多线程

package com.qf.service.impl;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.concurrent.Executors;

//任务
//@Configuration
@Component
public class Tasks implements SchedulingConfigurer {

    private Logger logger = LoggerFactory.getLogger(Tasks.class);

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        //创建线程池
        taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10));
    }

    @Scheduled(cron = "*/2 * * * * ?")
    //@Async
    public void task1(){
//        System.out.println("task1:"+new Date().toLocaleString());
        logger.info("task1:"+new Date().toLocaleString());
    }

    @Scheduled(cron = "*/2 * * * * ?")
    //@Async
    public void task2(){
//        System.out.println("task1:"+new Date().toLocaleString());
        logger.info("task2:"+new Date().toLocaleString());
    }

}

3.在启动上添加开启任务注解,然后测试

package com.qf;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@EnableAsync//开启异步
@EnableScheduling//开启任务
public class Springboot06Application {

    public static void main(String[] args) {
        SpringApplication.run(Springboot06Application.class, args);
    }

}
4.3整合quartz,首先导入依赖

1.导入依赖


    org.springframework.boot
    spring-boot-starter-quartz

2.编写任务类

package com.qf.quartz.job;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

import java.util.Date;

public class MyJob implements Job {
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("MyJob:"+ new Date().toLocaleString());
    }
}

3.编写配置类

package com.qf.quartz;

import com.qf.quartz.job.MyJob;
import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

@Configuration
public class QuartzConfig {

    //任务
    @Bean
    public JobDetailFactoryBean getJobDetailFactoryBean(){
        JobDetailFactoryBean jobDetailFactoryBean = new JobDetailFactoryBean();
        //指定任务
        jobDetailFactoryBean.setJobClass(MyJob.class);
        return jobDetailFactoryBean;
    }

    //触发器
    @Bean
    public CronTriggerFactoryBean getCronTriggerFactoryBean(JobDetailFactoryBean jobDetailFactoryBean){
        CronTriggerFactoryBean cronTriggerFactoryBean = new CronTriggerFactoryBean();
        JobDetail jobDetail = jobDetailFactoryBean.getObject();
        //指定任务详情
        cronTriggerFactoryBean.setJobDetail(jobDetail);
        //指定Cron表达式
        cronTriggerFactoryBean.setCronexpression("*/3 * * * * ?");

        return cronTriggerFactoryBean;
    }

    //调度器
    @Bean
    public SchedulerFactoryBean getSchedulerFactoryBean(CronTriggerFactoryBean cronTriggerFactoryBean){
        SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
        CronTrigger cronTrigger = cronTriggerFactoryBean.getObject();
        //指定触发器
        schedulerFactoryBean.setTriggers(cronTrigger);

        return schedulerFactoryBean;
    }
}

4.启动测试类测试即可

五、SpringBoot日志

SpringBoot默认使用的日志是Logback,官方建议日志文件命名为:logback-spring.xml

5.1在resources目录下创建logback-spring.xml






    
    
    

    
    
        
        
            debug
        
        
            
            ${CONSOLE_LOG_PATTERN}
            
            UTF-8
        
    
    
    
        ${log.path}/mylog1.log
        
            ${CONSOLE_LOG_PATTERN}
        
    
    
    
        
        ${log.path}/mylog2.log
        
        
            ${CONSOLE_LOG_PATTERN}
            UTF-8 
        
        
        
            
            ${log.path}/newlog-%d{yyyy-MM-dd}.%i.log
            
            
                1kb
            
            
            1
        
    

    
        
        
        
    

启动工程,进行测试

六、SpringBoot整合EasyExcel

EasyExcel官网:Alibaba Easy Excel - 简单、省内存的Java解析Excel工具 | 首页

6.1导入依赖

     com.alibaba
     easyexcel
     2.2.3
6.2写入 *** 作 6.2.1 创建pojo
package com.qf.pojo;

import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;

import java.util.Date;

@Data
public class DemoData {
    @ExcelProperty("字符串标题")
    private String string;
    @ExcelProperty("日期标题")
    private Date date;
    @ExcelProperty("数字标题")
    private Double doubleData;
    
    @ExcelIgnore
    private String ignore;
}
6.2.2 创建测试类
package com.qf.esayexcel;

import com.alibaba.excel.EasyExcel;
import com.qf.pojo.DemoData;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class TestEasyExcel {

    private List data() {
        List list = new ArrayList();
        for (int i = 0; i < 10; i++) {
            DemoData data = new DemoData();
            data.setString("字符串" + i);
            data.setDate(new Date());
            data.setDoubleData(0.56);
            list.add(data);
        }
        return list;
    }

    @Test
    public void simpleWrite() {
        // 写法1
        String fileName = "D:/TestEasyExcel.xlsx";
        // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
        EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data());
    }
}

运行测试类即可

6.3读取 *** 作 6.3.1 创建监听器
package com.qf.esayexcel;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.fastjson.JSON;
import com.qf.pojo.DemoData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

// 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
public class DemoDataListener extends AnalysisEventListener {
    private static final Logger LOGGER = LoggerFactory.getLogger(DemoDataListener.class);
    
    private static final int BATCH_COUNT = 5;
    List list = new ArrayList();
    
    private DemoDAO demoDAO;
    public DemoDataListener() {
        // 这里是demo,所以随便new一个。实际使用如果到了spring,请使用下面的有参构造函数
        demoDAO = new DemoDAO();
    }
    
    public DemoDataListener(DemoDAO demoDAO) {
        this.demoDAO = demoDAO;
    }
    
    @Override
    public void invoke(DemoData data, AnalysisContext context) {
        LOGGER.info("解析到一条数据:{}", JSON.toJSonString(data));
        list.add(data);
        // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
        if (list.size() >= BATCH_COUNT) {
            saveData();
            // 存储完成清理 list
            list.clear();
        }
    }
    
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 这里也要保存数据,确保最后遗留的数据也存储到数据库
        saveData();
        LOGGER.info("所有数据解析完成!");
    }
    
    private void saveData() {
        LOGGER.info("{}条数据,开始存储数据库!", list.size());
        demoDAO.save(list);
        LOGGER.info("存储数据库成功!");
    }
}
6.3.2 创建Dao
package com.qf.esayexcel;

import com.qf.pojo.DemoData;

import java.util.List;


public class DemoDAO {
    public void save(List list) {
        // 如果是mybatis,尽量别直接调用多次insert,自己写一个mapper里面新增一个方法batchInsert,所有数据一次性插入
    }
}
6.3.3创建测试类
@Test
public void simpleRead() {
    // 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
    // 写法1:
    String fileName =  "D:/TestEasyExcel.xlsx";
    // 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
    EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).sheet().doRead();

}
七、SpringBoot整合Swagger 7.1swagger介绍

现在开发,很多采用前后端分离的模式,前端只负责调用接口,进行渲染,前端和后端的唯一联系,变成了API接口。因此,API文档变得越来越重要。swagger是一个方便我们更好的编写API文档的框架,而且swagger可以模拟http请求调用。

大部分采取的方式:Vue + SpringBoot,Vue通过js渲染页面,后端把数据传递给js,早期前端只负责写页面,然后把写好的HTML页面给后端,后端使用模板引擎(Jsp,Thymeleaf、 freemarker)进行开发。

前后端分离的好处:各自开发,相对独立,松耦合,前后端通过API进行交互,后端提供接口给前端,前端去调用该接口,但可能会导致前后端团队人员不能做到及时协商,出现一些问题。解决方式:早期使用实时更新文档,但非常繁琐,后来又使用postman来进行一些测试。

swagger是目前流行的Api框架,官网:API documentation & Design Tools for Teams | Swagger

7.2导入依赖

    io.springfox
    springfox-swagger-ui
    2.9.2



    io.springfox
    springfox-swagger2
    2.9.2
7.3创建配置类
@Configuration
@EnableSwagger2//开启Swagger2
public class SwaggerConfig {

}

然后启动测试运行,访问:http://localhost:8080/swagger-ui.html,看到如下页面:

7.4手动配置实例,修改SwaggerConfig配置类
package com.qf.swagger.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.documentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;


@Configuration
@EnableSwagger2//开启Swagger2
public class SwaggerConfig {

    //配置Swagger的Bean实例
    @Bean
    public Docket createDocket() {
        return new Docket(documentationType.SWAGGER_2)
                .apiInfo(apiInfo());
    }


    //配置API的基本信息(会在http://项目实际地址/swagger-ui.html页面显示)
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("测试API文档标题")
                .description("测试api接口文档描述")
                .termsOfServiceUrl("http://www.baidu.com")
                .version("1.0")
                .build();
    }
}

 再次启动测试运行,访问:http://localhost:8080/swagger-ui.html,看到如下页面:

7.5创建实体类
package com.qf.entity;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

@ApiModel("用户")
public class User {

    @ApiModelProperty("编号")
    private String uid;
    
    @ApiModelProperty("用户名")
    private String username;
    
    @ApiModelProperty("密码")
    private String password;


    public String getUid() {
        return uid;
    }

    public void setUid(String uid) {
        this.uid = uid;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}
 7.6创建controller
package com.qf.controller;


import com.qf.entity.User;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;

//@Api(description = "用户接口")
@Api(tags = "用户接口")
@RestController
@RequestMapping("/user")
public class UserController {


    @ApiOperation("查询单个用户")
    @RequestMapping("/findById")
    public User findById(@RequestParam @ApiParam("用户ID") String uid){

        User user = new User();
        user.setUid(uid);
        user.setUsername("张三");
        user.setPassword("123");

        return  user;
    }

    @ApiOperation("删除单个用户")
    @PostMapping("/delete")
    public User delete(String uid){

        User user = new User();
        user.setUid(uid);
        user.setUsername("李四");
        user.setPassword("456");

        return  user;
    }

    @ApiOperation("查询所有用户")
    @GetMapping("/findAll")
    public List findAll(){

        User user1 = new User();
        user1.setUid("1001");
        user1.setUsername("张三");
        user1.setPassword("123");

        User user2 = new User();
        user2.setUid("1002");
        user2.setUsername("李四");
        user2.setPassword("456");

        ArrayList users = new ArrayList<>();
        users.add(user1);
        users.add(user2);

        return  users;
    }
}
7.7修改SwaggerConfig配置类
package com.qf.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.documentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2//开启Swagger2
public class SwaggerConfig {

    //配置Swagger的Bean实例
    @Bean
    public Docket createDocket(){

        return new Docket(documentationType.SWAGGER_2)
                .apiInfo(createApiInfo())
                .groupName("yangl")分组名称(可以创建多个Docket就有多个组名)
                .enable(true)//enable表示是否开启Swagger
                .select()
                //RequestHandlerSelectors指定扫描的包
                .apis(RequestHandlerSelectors.basePackage("com.qf.controller"))
                .build();
    }

    //配置API的基本信息(会在http://项目实际地址/swagger-ui.html页面显示)
    public ApiInfo createApiInfo(){
        return new ApiInfoBuilder()
                .title("测试标题")
                .description("测试描述")
                .termsOfServiceUrl("http://www.baidu.com")
                .build();

        //return ApiInfo.DEFAULT;
    }

}

Swagger通过注解表明该接口会生成文档,包括接口名、请求方法、参数、返回信息

@Api:修饰整个类,描述Controller的作用

@ApiOperation:描述一个类的一个方法,或者说一个接口

@ApiModel:用对象来接收参数 ,修饰类

@ApiModelProperty:用对象接收参数时,描述对象的一个字段

@ApiResponse:HTTP响应其中1个描述

@ApiResponses:HTTP响应整体描述,一般描述错误的响应

@ApiIgnore:使用该注解忽略这个API

@ApiError :发生错误返回的信息

@ApiParam:单个参数描述

@ApiImplicitParam:一个请求参数,用在方法上

@ApiImplicitParams:多个请求参数

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5523323.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-13
下一篇 2022-12-13

发表评论

登录后才能评论

评论列表(0条)