.net转Java学习笔记15-使用hutool中的FileUtil+ConcurrentHashMap + json实现文件模拟数据库的增删改查

87 阅读4分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

项目上要做一个小的客户端,但是用C#这边做桌面应用程序的不是很熟练,项目要求又比较急,只能用传统的BS架构,java做后台然后前台打包成exe程序。 这里就涉及到一个问题,对于一些数据的存储,列表的增删改查,因为是控制硬件的小插件不想单独设置数据库,需要用文件的形式进行数据的存储,并实现增删改查。

所用到的技术

springboot,swgger,lomock,ConcurrentHashMap,hutool等 swagger是一个在线文档和在线的调试,之前介绍过简单的使用springboot整合swagger-UI和swagger-bootstrap-ui的使用 lomock个工具类库,可以用简单的注解形式来简化代码,提高开发效率。@data get/set方法自动生成 @Log4j/@Slf4j 日志注解等都需要 ConcurrentHashMap它是HashMap的一个线程安全的、支持高效并发的版本 hutool是一个Java工具包,官方网址 提供了大量的“util”包,这里我们用到了FileUtil工具包

准备工作 1.首先我们要准备一个springboot项目 2.idea工具需要set->plugins添加插件 在这里插入图片描述

添加之后的目录结构如下 在这里插入图片描述

**


正式开始编程,这里我们的思路是首先在文件加载之前就去读取一个json文件,将文件里面的数据放在全局的静态的ConcurrentHashMap 当中,页面查询只是查询ConcurrentHashMap 当进行新增和修改删除操作时,我们只需要对ConcurrentHashMap 进行操作,然后以覆盖的方式将json文件覆盖写入即可。


1.pom文件

**

 <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <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.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.12.0</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.6.3</version>
        </dependency>


        <!-- https://mvnrepository.com/artifact/io.netty/netty-all -->
        <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-all</artifactId>
            <version>4.1.66.Final</version>
        </dependency>
        <!--swagger-->
        <dependency>
            <groupId>com.spring4all</groupId>
            <artifactId>swagger-spring-boot-starter</artifactId>
            <version>1.7.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>swagger-bootstrap-ui</artifactId>
            <version>1.9.6</version>
        </dependency>

    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

2.yml文件

server:
  port: 8081

spring:
  application:
    name: acconfig

control:
  file:
    controlpath: //controldata.json
  timeout: 10
logging:
  pattern:
    console: "%clr(%d{HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(---){faint} %clr(%-40.40logger{39}){cyan}[line:%line]    %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:%wEx}"
    file: "%d{yyyy-MM-dd HH:mm:ss.SSS} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] %-40.40logger{39}[line:%line]: %m%n${LOG_EXCEPTION_CONVERSION_WORD:%wEx}"
  level:
    com.zkrd: debug
    com: error
    org: error
    io: error
  file:
    name: ./logs/${spring.application.name}.log

3.启动文件

@SpringBootApplication
public class Application {

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

}

@Component
public class InitControlData implements ApplicationRunner {
	@Autowired
	private ControlDataService controlDataService;

	@Override
	public void run(ApplicationArguments args) throws Exception {
		controlDataService.loadDataFromFile();
	}
}

这里InitControlData 继承ApplicationRunner ,这样程序在启动的时候就会首先执行这一段代码。

4.实体类

//控制器实体
@Data
public class ControlData {

    private String id;
    private String name;
    private String sex;
    private String phone;
    private String like;
}

5.swagger配置文件

在这里插入代码片@Configuration
@EnableSwagger2
@EnableSwaggerBootstrapUI
public class SwaggerConfig {
    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.withClassAnnotation(RestController.class))
                .paths(PathSelectors.any())
                .build();
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("接口文档")
                .description("接口文档")
                .version("1.0")
                .contact(new Contact("刘涛", "", "1299828500@qq.com"))
                .build();
    }

}

6.Service层

这里我们首先定义全局变量,然后程序启动会调用loadDataFromFile方法,将json文件路径进行解析,如果存在就将文件内容读取到map集合当中去


@Service
public class ControlDataService {
	private static ConcurrentHashMap<String, ControlData> controlDataMap = new ConcurrentHashMap<>();

	@Value("${control.file.controlpath}")
	private String controlFilename;



	public void loadDataFromFile() {
		ApplicationHome home = new ApplicationHome(getClass());
		File jarFile = home.getSource();
		String  path = jarFile.getParent();
		String controlFilePath = path + controlFilename;

		if (FileUtil.exist(controlFilePath)) {
			String listJson = FileUtil.readString(controlFilePath, "UTF-8");
			if (StringUtils.isEmpty(listJson)) return;
			List<ControlData> list = JSONUtil.toList(listJson, ControlData.class);
			list.forEach(data->{
				controlDataMap.put(data.getId(), data);
			});
		}
	}

	public List<ControlData> getControlList() {
		return new ArrayList(controlDataMap.values());
	}

	public ControlData getControlDataByid(String id) {
		return controlDataMap.get(id);
	}

	public void saveControlData(ControlData controlData) {
		controlDataMap.put(controlData.getId(), controlData);
		saveMapToFile();
	}

	public void removeControlData(String id) {
		controlDataMap.remove(id);
		saveMapToFile();
	}

	public void removeAll() {
		controlDataMap.clear();
		saveMapToFile();
	}

	private void saveMapToFile() {
		ApplicationHome home = new ApplicationHome(getClass());
		File jarFile = home.getSource();
		String  path = jarFile.getParent();
		String controlFilePath = path + controlFilename;

		FileUtil.writeString(JSONUtil.toJsonStr(getControlList()), controlFilePath, "UTF-8");
	}
}

无论是增删改查都是对map集合的操作,用id作为key值,实体类对象作为value,这样对集合的put,remove都能做到增删改的效果。 除了查询之外,设计到map集合的改变,都要调用saveMapToFile将map集合内容重新写入json文件中 FileUtil.writeString第一次调用如果json文件不存在会自动创建

7.Control层增删改查的调用


@RestController
@Slf4j
@RequestMapping(value = "/api/device")
@Api(tags = "列表相关接口")
public class ControlDataController extends JsonController {
	@Autowired
	private ControlDataService controlDataService;

	@PostMapping("list")
	@ApiOperation("搜索列表")
	public JsonResponse list() {
		return okJson(controlDataService.getControlList());
	}

	@PostMapping("detail")
	@ApiOperation("展示详细信息")
	public JsonResponse detail(String id) {
		return okJson(controlDataService.getControlDataByid(id));
	}


	@PostMapping("save")
	@ApiOperation("保存信息")
	public JsonResponse save(HttpServletRequest request
			, @RequestBody(required=true)ControlData controlDataInfo) {
		if (StringUtils.isAnyEmpty(controlDataInfo.getName(), controlDataInfo.getId())) {
			return errorJson("所有参数不能为空,端口不能为0");
		}

		controlDataService.saveControlData(controlDataInfo);
		return okJson();
	}

	@PostMapping("remove")
	@ApiOperation("删除信息")
	public JsonResponse remove(String ip) {
		controlDataService.removeControlData(ip);
		return okJson();
	}

	@PostMapping("removeAll")
	@ApiOperation("清空信息")
	public JsonResponse removeAll() {
		controlDataService.removeAll();
		return okJson();
	}
}

**

其他一些文件类

** JsonController


public class JsonController {

	protected JsonResponse okJson() {
		JsonResponse json = new JsonResponse();
		json.setStatus(true);
		json.setCode("200");
		return json;
	}

	protected JsonResponse okJson(Object data) {
		JsonResponse json = new JsonResponse();
		json.setStatus(true);
		json.setCode("200");
		json.setData(data);
		return json;
	}

	protected JsonResponse okJson(Object data, String message) {
		JsonResponse json = new JsonResponse();
		json.setStatus(true);
		json.setCode("200");
		json.setMessage(message);
		json.setData(data);
		return json;
	}

	protected JsonResponse errorJson(String message) {
		JsonResponse json = new JsonResponse();
		json.setStatus(false);
		json.setCode("500");
		json.setMessage(message);
		return json;
	}

	protected JsonResponse errorJson(String message, Object data) {
		JsonResponse json = new JsonResponse();
		json.setStatus(false);
		json.setCode("500");
		json.setMessage(message);
		json.setData(data);
		return json;
	}
}

JsonResponse

@Data
public class JsonResponse {
	private String code;
	private boolean status;
	private String message;
	private Object data;
}

效果访问http://localhost:8081/doc.html#进行调试