700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > SpringBoot整合Thymeleaf+EasyExcel实现excel文件的读取并展示 附加swagger2配置(超详细示范!)

SpringBoot整合Thymeleaf+EasyExcel实现excel文件的读取并展示 附加swagger2配置(超详细示范!)

时间:2023-02-04 21:55:44

相关推荐

SpringBoot整合Thymeleaf+EasyExcel实现excel文件的读取并展示 附加swagger2配置(超详细示范!)

目录

1.Springboot整合Thyemleaf+EasyExcel步骤

1.1 pom文件引入依赖

1.2 yml文件配置

1.3 config配置类

1.3.1 Swagger2配置类

1.3.2 前端跨域问题解决

2. 后端代码编写

2.1 Controller层

2.1.1 补充:@RestController页面跳转方法

2.2 service层

实现AnalysisEventListener方法

2.3 Entity层

2.4 excel表

3. 前端页面设计

3.1 Thyemleaf模板

index.html

实际页面展示

id查询

查询全部

Springboot启动,方法自动执行

最近由于工作需要,实现从excel文件读取数据并用静态页面展示。(前端的html页面迟迟不发过来,只能自己动手写页面展示了,虽然现在都是前后端分离展示,但是对于好多后端开发刚入门的是一个难点,所以就考虑使用Thymeleaf模板引擎实现页面数据展示。

Thymeleaf是一款现代的服务器端 Java 模板引擎,可以轻松与SpringMvc、springBoot等web框架进行集成,适用于 Web 和独立环境开发。与jsp、Velocity、FreeMaker功能类似,thymeleaf可以通过thymeleaf标签渲染处理数据用以展示给用户。

1.Springboot整合Thyemleaf+EasyExcel步骤

1.1 pom文件引入依赖

<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.0</version></parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.2</version></dependency><!--fastjson--><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.76</version></dependency><!--thymeleaf--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId><version>2.7.0</version></dependency><!-- lombok依赖包 --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.16.10</version><scope>provided</scope></dependency><!--swagger依赖--><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.9.2</version></dependency><!--swagger-ui--><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>2.9.2</version></dependency><!-- easyexcel 依赖 --><dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.1.1</version></dependency>

这里有一个很大的坑,自己在这里花了很长时间来解决jar包冲突问题。

spring-boot-starter-parent在导入这个依赖后,必须要导入spring-boot-starter-web这个依赖。不然会导致springboot项目启动后立即停止的问题。spring-boot-starter-thymeleaf的这个依赖版本建议与spring-boot-starter-parent的版本一致,不然可能会导致thymeleaf加载不上。

1.2 yml文件配置

server:port: 8080// 解决springboot2.7与swagger2冲突问题spring:mvc:pathmatch:matching-strategy: ant_path_matcherthymeleaf:prefix: classpath:/templates/suffix: .htmlencoding: UTF-8mode: HTML5doctor:fileName: "C:\\\\Users\\\\admin\\\\Desktop\\\\Api\\\\医师节数据样例.xlsx"

1.3 config配置类

1.3.1 Swagger2配置类

@Configuration@EnableSwagger2public class Swagger2ApiConfig {/*** 创建API应用* apiInfo() 增加API相关信息* 通过select()函数返回一个ApiSelectorBuilder实例,用来控制哪些接口暴露给Swagger来展现,* 指定扫描的包路径来定义指定要建立API的目录。* @return*/@Beanpublic Docket coreApiConfig(){return new Docket(DocumentationType.SWAGGER_2).apiInfo(adminApiInfo()).groupName("Api-wx").select()// 用于指定扫描哪个包下的接口.apis(RequestHandlerSelectors.basePackage("com.yif.controller"))// 选择所有的API,如果你想只为部分API生成文档,可以配置这里.paths(PathSelectors.any()).build();}private ApiInfo adminApiInfo(){return new ApiInfoBuilder().title("wx--api文档").description("wx-api接口描述").version("1.0").contact(new Contact("凡仔","/hszyf2051/","151900983@")).build();}}

1.3.2 前端跨域问题解决

@Componentpublic class CrossFilter implements Filter {@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletResponse res = (HttpServletResponse) servletResponse;res.addHeader("Access-Control-Allow-Credentials", "true");res.addHeader("Access-Control-Allow-Origin", "*");//*代表所有网站均无拦截,也可设置自己相应的域名res.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");res.addHeader("Access-Control-Allow-Headers", "Content-Type,X-CAF-Authorization-Token,sessionToken,X-TOKEN");if (((HttpServletRequest) servletRequest).getMethod().equals("OPTIONS")) {servletResponse.getWriter().println("ok");return;}filterChain.doFilter(servletRequest, servletResponse);}}

2. 后端代码编写

2.1 Controller层

@Controllerpublic class DoctorController {@Autowiredprivate IDoctorService doctorService;/*** 查找所有医生* @param model* @return*/@RequestMapping("/getDoctors")public String getDoctors(Model model) {List<Doctor> doctors = doctorService.readDoctors();model.addAttribute("doctors",doctors);return "index";}/*** 根据id查找对应的医生* @param model* @param id* @return*/@GetMapping("/findDoctorById")public String findDoctorById(Model model,@RequestParam String id) {List<Doctor> doctors = doctorService.findDoctorById(id);model.addAttribute("doctors",doctors);return "index";}}

注意这里的@Controller注解不能写成@RestController,不然会导致页面直接返回index。

return "index" 填写的是resources/templates/下的html页面。必须与页面名字相一致。

2.1.1 补充:@RestController页面跳转方法

若只用@RestController注解,则需要将方法的类型改为ModelAndView。页面的返回路径前不可以加/,不然会无法解析路径,返回字符串!(本人在这里绕了很久)例如"/User",切记不能这么写

@GetMapping("/findUserById")public ModelAndView findDoctorById(Model model,@RequestParam String id) {List<User> userList = userService.findUserById(id);model.addAttribute("users",userList);// 返回值类型也必须是ModelAndView!!! return new ModelAndView("User");}

2.2 service层

@Slf4j@Servicepublic class DoctorServiceImpl implements IDoctorService {/*** 从yml中读取文件路径*/@Value("${doctor.fileName}")private String fileName;@Overridepublic List<Doctor> readDoctors() {// 创建一个数据格式来承装读取到数据Class<Doctor> head = Doctor.class;// 创建ExcelReader对象List<Doctor> doctorList = new ArrayList<>();ExcelReader excelReader = EasyExcel.read(fileName, head, new AnalysisEventListener<Doctor>() {@Overridepublic void invoke(Doctor doctor, AnalysisContext analysisContext) {if (doctor.getHealing() == null) {// 住院患者治疗量doctor.setHealing(0);}if (doctor.getBirthOperations() == null) {// 生日当天手术量doctor.setBirthOperations(0);}if (doctor.getBirthVisits() == null) {// 生日当天看诊量doctor.setBirthVisits(0);}doctorList.add(doctor);}@Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {}}).build();// 创建sheet对象,并读取Excel的第1个sheet(下标从0开始)ReadSheet readSheet = EasyExcel.readSheet(0).build();excelReader.read(readSheet);// 关闭流操作,在读取文件时会创建临时文件,如果不关闭,磁盘爆掉excelReader.finish();log.info(String.valueOf(doctorList));return doctorList;}@Overridepublic List<Doctor> findDoctorById(String id) {// 创建一个数据格式来承装读取到数据Class<Doctor> head = Doctor.class;// 创建ExcelReader对象List<Doctor> doctorList = new ArrayList<>();ExcelReader excelReader = EasyExcel.read(fileName, head, new AnalysisEventListener<Doctor>() {@Overridepublic void invoke(Doctor doctor, AnalysisContext analysisContext) {if (doctor.getId().equals(id)) {if (doctor.getHealing() == null) {// 住院患者治疗量doctor.setHealing(0);}if (doctor.getBirthOperations() == null) {// 生日当天手术量doctor.setBirthOperations(0);}if (doctor.getBirthVisits() == null) {// 生日当天看诊量doctor.setBirthVisits(0);}doctorList.add(doctor);}}@Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {if (doctorList.size() == 0) {log.info("该企业账号:"+ id +",查无此人");}}}).build();// 创建sheet对象,并读取Excel的第1个sheet(下标从0开始)ReadSheet readSheet = EasyExcel.readSheet(0).build();excelReader.read(readSheet);// 关闭流操作,在读取文件时会创建临时文件,如果不关闭,磁盘爆掉excelReader.finish();log.info(String.valueOf(doctorList));return doctorList;}}

实现AnalysisEventListener方法

invoke方法是遍历每一条excel中数据,可以实现空数据,重复数据的检查。可以在外层定义一个List,实现数据的临时缓存。

doAfterAllAnalysed方法是在整个遍历完成后执行的方法,我在这里增加逻辑判断,如果list的大小为0,则显示该id查无此人。

@Value("${doctor.fileName}")

private String fileName;

这一块引用的是yml里的属性,可以做到一定数据的解耦

2.3 Entity层

@Datapublic class Doctor {/*** 姓名*/@ExcelProperty(value = "姓名")private String name;/*** 企业账号*/@ExcelProperty(value = "企业账号")private String id;/*** 身份*/@ExcelProperty(value = "身份")private String identity;/*** 就诊量*/@ExcelProperty(value = "门诊就诊量")private Integer visits;/*** 看诊最多日期*/@DateTimeFormat("yyyy年MM月dd日")@ExcelProperty(value = "看诊最多日期")private String maxVisitDate;/*** 看诊最多日看诊量*/@ExcelProperty(value = "看诊最多日看诊量")private Integer maxVisit;/*** 住院患者治疗量*/@ExcelProperty(value = "住院患者治疗量")private Integer healing;/*** 手术量*/@ExcelProperty(value = "手术量")private Integer operation;/*** 手术总时长*/@ExcelProperty(value = "手术总时长")private String timeOperations;/*** 手术最多搭档*/@ExcelProperty(value = "手术最多搭档")private String partner;/*** 手术时长最长时间*/@ExcelProperty(value = "手术时长最长时间")private String maxTimeOperations;/*** 手术最长结束时间*/@DateTimeFormat("yyyy年MM月dd日HHmm")@ExcelProperty(value = "手术最长结束时间")private String latestTimeOperations;/*** 医生生日*/@DateTimeFormat("mm月dd日")@ExcelProperty(value = "医生生日")private String birthDate;/*** 生日当天看诊量*/@ExcelProperty(value = "生日当天看诊量")private Integer birthVisits;/*** 生日当天手术量*/@ExcelProperty(value = "生日当天手术量")private Integer birthOperations;/*** 线上诊疗人次(互联网门诊)*/@ExcelProperty(value = "线上诊疗人次(互联网门诊)")private Integer onlineVisits;}

@ExcelProperty(value = " ") 注解是EasyExcel提供的,value中填写excel中对应字段名字,一定要完全对应上,不然会出现映射错误,导致读取的数据为空值。

@DateTimeFormat("yyyy年MM月dd日") 实现对日期类型数据的转换,如果只需要部分时间字段,填写对应的日期格式就好了。

完整格式: yyyy-MM-dd HH:mm:ss

2.4 excel表

3. 前端页面设计

3.1 Thyemleaf模板

Thyemleaf入门教程:/RDU5r

index.html

<!DOCTYPE html><html lang="en" xmlns:th=""><head><meta charset="UTF-8"><title>循环遍历获取医生信息</title><script src="/ajax/libs/jquery/3.6.0/jquery.min.js"></script></head><body><h2 class="index-f-head" style="text-align: center"> 医师节活动 <span>查询医生信息</span> </h2><form action="http://localhost:8080/findDoctorById" method="get">企业账号:<input type="text" name="id" placeholder="请输入你的企业账号"><input type="submit" value="查询"><input type="reset" value="重置"></form><br><input type="reset" value="清空数据" onclick="resetAll()"><input type="button" value="查询全部" onclick="queryAll()"> <br><br><br><div class="index-f-body" style="text-align: center"><table style="border-width: 1px;border-style: solid;width: 100% "><tr><td>姓名</td><td>企业账号</td><td>身份</td><td>门诊就诊量</td><td>看诊最多日期</td><td>看诊最多日看诊量</td><td>住院患者治疗量</td><td>手术量</td><td>手术总时长</td><td>手术最多搭档</td><td>手术时长最长时间</td><td>手术最长结束时间</td><td>医生生日</td><td>生日当天看诊量</td><td>生日当天手术量</td><td>线上诊疗人次(互联网门诊)</td></tr><div th:each="doctor : ${doctors}" style="align-items: center"><tr><td th:text="${doctor.name}"></td><td th:text="${doctor.id}"></td><td th:text="${doctor.identity}"></td><td th:text="${doctor.visits}"></td><td th:text="${doctor.maxVisitDate}"></td><td th:text="${doctor.maxVisit}"></td><td th:text="${doctor.healing}"></td><td th:text="${doctor.operation}"></td><td th:text="${doctor.timeOperations}"></td><td th:text="${doctor.partner}"></td><td th:text="${doctor.maxTimeOperations}"></td><td th:text="${doctor.latestTimeOperations}"></td><td th:text="${doctor.birthDate}"></td><td th:text="${doctor.birthVisits}"></td><td th:text="${doctor.birthOperations}"></td><td th:text="${doctor.onlineVisits}"></td></tr></div></table></div></body><script>function resetAll() {window.location.href = 'http://localhost:8080/findDoctorById?id'}function queryAll(){window.location.href = 'http://localhost:8080/getDoctors'}</script></html>

注意这里的html页面路径一定要放在templates文件夹下,不然会映射不到。

实际页面展示

id查询

查询全部

在按钮中添加了window.location.href的方法,实现当前页面url的跳转。这里要注意的是配置跨域,前面已经在config中配置。

Springboot启动,方法自动执行

如果想实现Springboot启动后自动实现方法读取数据,可以实现ApplicationRunner接口。

@Slf4j@Component@Order(value = 1)public class MyApplicationRunner implements ApplicationRunner {@Autowiredprivate IDoctorService doctorService;@Overridepublic void run(ApplicationArguments args) throws Exception {log.info("测试MyApplicationRunner");doctorService.readDoctors();}}

以上,喜欢请点个赞吧~

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。