开发宝典~~

JSON

 <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.28</version>
</dependency>
  1. string --> json --> map/object
 JSONArray jsonArray = new JSONArray();
        for(int i=0;i<2;i++){
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("userid",11);
            jsonObject.put("name","拉拉");
            jsonObject.put("deptId",1);
            jsonArray.add(jsonObject);
        }
        String str = jsonArray.toString();
        out.println("String: "+str);
        /*-----------------------以上是模拟前端传过来的--------------------------------*/
        JSONArray jsonArray1 = JSON.parseArray(str);  //将String换化为JSONArray
        out.println("jsonArray: "+jsonArray1);

        /**
         * json数组转化为对象数组
         */
        List<User> collect = jsonArray1.stream()
                .map(e -> JSONObject.parseObject(e.toString(), User.class))
                .collect(Collectors.toList());
        out.println("jsonArray转化为对象数组:"+collect);

        /**
         * json数组转化为map数组
         */
        List<Map> collect1 = jsonArray1.stream()
                .map(e -> JSONObject.parseObject(e.toString(), Map.class))
                .collect(Collectors.toList());
        out.println("jsonArray转化为map数组:"+collect1);
String: [{"name":"拉拉","deptId":1,"userid":11},{"name":"拉拉","deptId":1,"userid":11}]
jsonArray: [{"name":"拉拉","deptId":1,"userid":11},{"name":"拉拉","deptId":1,"userid":11}]
jsonArray转化为对象数组:[User{id=null, userid='11', password='null', name='拉拉', sex='null', adress='null', email='null', deptId=1}, User{id=null, userid='11', password='null', name='拉拉', sex='null', adress='null', email='null', deptId=1}]
jsonArray转化为map数组:[{name=拉拉, deptId=1, userid=11}, {name=拉拉, deptId=1, userid=11}]

2.object -> string

        List<User> userList = new ArrayList<>();
        User user = new User();
        user.setUserid("1");
        user.setName("心心");
        user.setDeptId(null);
        userList.add(user);

        User user1 = new User();
        user1.setUserid("1");
        user1.setName("心心");
        user1.setAdress("");
        userList.add(user1);
        out.println(userList.toString());
        String s = JSON.toJSONString(userList,SerializerFeature.WriteMapNullValue);// 去掉忽略实体类中字段为null的字段
        out.println(s);
实体类集合:[User{id=null, userid='1', password='null', name='心心', sex='null', adress='null', email='null', deptId=null}, User{id=null, userid='1', password='null', name='心心', sex='null', adress='', email='null', deptId=null}]
json集合:[{"adress":null,"deptId":null,"email":null,"id":null,"name":"心心","password":null,"sex":null,"userid":"1"},{"adress":"","deptId":null,"email":null,"id":null,"name":"心心","password":null,"sex":null,"userid":"1"}]

amq消息队列

//发送                                                  频道                          内容
publisher.doPublish(Message.builder().channel("asset_hub_addDeviceInfo").content(indexData.toJSONString()).build());
//接收                         监听频道 可多个
    @SubscribeMapping("asset_hub_addDeviceInfo") 
    public void addDeviceInfo(Message message) {
        if (StringUtils.isNotBlank(message.getContent())) {
            JSONArray.parseArray(message.getContent())
                    .forEach(asset -> {
                        Map assetInfo = (JSONObject) asset;
                        gdpsProxyService.handleAsset(assetInfo);
                    });
        }
    }

feign

feign旨在使编写 java Http客户端变得更容易
在Feign的实现下,我们只需要创建一个接口并使用注解的方式来配置他
在公司的大项目中,通常会写一个公共模块,在公共项目中写好各模块的提供的服务接口,供其他服务调用。
如图:
在这里插入图片描述
如上图是一个公共模块下的fegin模块
其中service中的是各个模块提供的给其他模块可调用的接口,entity中的是接口返回值所需要用到的包装类;
在这里插入图片描述资产模块下的提供的可调用的接口

1.提供fegin

//fengin
@AuthorizedFeignClient(name = "asset-hub")  //指定接口在的服务
public interface AssetHubFeignService {
    @RequestMapping(value = "/deviceInfo/getAssetById", method = RequestMethod.GET)
    BaseGduiDTO<?> getAssetById(@RequestParam("id") Long id);

    @RequestMapping(value = "/deviceInfo/updateDeviceInfo", method = RequestMethod.POST)
    BaseGduiDTO<?> updateDeviceInfo(@RequestParam("map") Map<String, String> map);
    }

2.在想用的类中注入

public class UserserviceImpl implements Userservice {
    @Autowired
    private AssetHubFeignService assetHubFeignService;

    private List<Map<String, Object>> fetchAlarmAssetTypeTop4(List<AlarmDO> alarmListByRecently) {
        List<Map<String, Object>> maps = new ArrayList<>();
        Map<String, String> assetTypeMap = new HashMap<>();
        List<AssetTypeDO> allAssetType = assetHubFeignService.updateDeviceInfo(); //调用
        allAssetType.forEach(type -> assetTypeMap.put(type.getId().toString(), type.getTypeName()));
        Map<Integer, List<AlarmDO>> collect = alarmListByRecently.stream().collect(Collectors.groupingBy(s -> s.getAssetTypeId()));
        for (Map.Entry<Integer, List<AlarmDO>> c : collect.entrySet()) {
            Map<String, Object> map = new HashMap<>();
            map.put("name", assetTypeMap.get(c.getKey().toString()));
            map.put("id", c.getKey());
            map.put("num", c.getValue().size());
            maps.add(map);
        }
        Collections.sort(maps, new AlarmComparable());
        return maps.subList(0, maps.size() > 4 ? 4 : maps.size());
    }
}

导入导出

1. ExcelWriter

ExcelWriter writer = new ExcelWriter(response.getOutputStream(), ExcelTypeEnum.XLSX, true);
Table table = new Table(0);
List<List<String>> titles = new ArrayList<>();
for (int i = 0; i < dayNum; i++) {
titles.add(Arrays.asList(i));
}
table.setHead(titles);  //表头

List<List<String>> data = new ArrayList<>();   //数据填装
for (OpsScheduel opsScheduel : scheduel) {
     List<String> opsInfo = new ArrayList<>();
     for(·····){
      opsInfo.add(XXXXX);
     }
     data.add(opsInfo);
  }
  
writer.write0(data, new Sheet(1, 0), table);
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            String fname = java.net.URLEncoder.encode("排班表", "UTF-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + new String(fname.getBytes("UTF-8"), "GBK") + ".xlsx");
            writer.finish();

2.EasyExcel

导出:
1.定义实体类

@Data
public class DemoData {
    @ExcelProperty("字符串标题")
    private String string;
    @ExcelProperty("日期标题")
    private Date date;
    @ExcelProperty("数字标题")
    private Double doubleData;
    /**
     * 忽略这个字段
     */
    @ExcelIgnore
    private String ignore;
}

2.写出

    /**
     * 最简单的写
     * <p>1. 创建excel对应的实体对象 参照{@link DemoData}
     * <p>2. 直接写即可
     */
    @Test
    public void simpleWrite() {
        // 写法1
        String fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx";
        // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
        // 如果这里想使用03 则 传入excelType参数即可
        EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data());

        // 写法2
        fileName = TestFileUtil.getPath() + "simpleWrite" + System.currentTimeMillis() + ".xlsx";
        // 这里 需要指定写用哪个class去写
        ExcelWriter excelWriter = null;
        try {
            excelWriter = EasyExcel.write(fileName, DemoData.class).build();
            WriteSheet writeSheet = EasyExcel.writerSheet("模板").build();
            excelWriter.write(data(), writeSheet);
        } finally {
            // 千万别忘记finish 会帮忙关闭流
            if (excelWriter != null) {
                excelWriter.finish();
            }
        }
    }




    /**
     * 根据参数只导出指定列
     * <p>
     * 1. 创建excel对应的实体对象 参照{@link DemoData}
     * <p>
     * 2. 根据自己或者排除自己需要的列
     * excludeColumnFiledNames   指定排除某些列
     * includeColumnFiledNames   指定导出某些列
     * <p>
     * 3. 直接写即可
     *
     * @since 2.1.1
     */
    @Test
    public void excludeOrIncludeWrite() {
        String fileName = TestFileUtil.getPath() + "excludeOrIncludeWrite" + System.currentTimeMillis() + ".xlsx";

        // 根据用户传入字段 假设我们要忽略 date
        Set<String> excludeColumnFiledNames = new HashSet<String>();
        excludeColumnFiledNames.add("date");
        // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
        EasyExcel.write(fileName, DemoData.class).excludeColumnFiledNames(excludeColumnFiledNames).sheet("模板")
            .doWrite(data());

        fileName = TestFileUtil.getPath() + "excludeOrIncludeWrite" + System.currentTimeMillis() + ".xlsx";
        // 根据用户传入字段 假设我们只要导出 date
        Set<String> includeColumnFiledNames = new HashSet<String>();
        includeColumnFiledNames.add("date");
        // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
        EasyExcel.write(fileName, DemoData.class).includeColumnFiledNames(includeColumnFiledNames).sheet("模板")
            .doWrite(data());
    }

3.结合注解使用

@Data
public class ConverterData {
    /**
     * 我想所有的 字符串起前面加上"自定义:"三个字
     */
    @ExcelProperty(value = "字符串标题", converter = CustomStringStringConverter.class)
    private String string;
    /**
     * 我想写到excel 用年月日的格式
     */
    @DateTimeFormat("yyyy年MM月dd日HH时mm分ss秒")
    @ExcelProperty("日期标题")
    private Date date;
    /**
     * 我想写到excel 用百分比表示
     */
    @NumberFormat("#.##%")
    @ExcelProperty(value = "数字标题")
    private Double doubleData;
}

在这里插入图片描述
导入

// 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
public class DemoDataListener extends AnalysisEventListener<DemoData> {
    private static final Logger LOGGER = LoggerFactory.getLogger(DemoDataListener.class);
    /**
     * 每隔5条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收
     */
    private static final int BATCH_COUNT = 5;
    List<DemoData> list = new ArrayList<DemoData>();
    /**
     * 假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。
     */
    private DemoDAO demoDAO;
    public DemoDataListener() {
        // 这里是demo,所以随便new一个。实际使用如果到了spring,请使用下面的有参构造函数
        demoDAO = new DemoDAO();
    }
    /**
     * 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
     *
     * @param demoDAO
     */
    public DemoDataListener(DemoDAO demoDAO) {
        this.demoDAO = demoDAO;
    }
    /**
     * 这个每一条数据解析都会来调用
     *
     * @param data
     *            one row value. Is is same as {@link AnalysisContext#readRowHolder()}
     * @param context
     */
    @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();
        }
    }
    /**
     * 所有数据解析完成了 都会来调用
     *
     * @param context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 这里也要保存数据,确保最后遗留的数据也存储到数据库
        saveData();
        LOGGER.info("所有数据解析完成!");
    }
    /**
     * 加上存储数据库
     */
    private void saveData() {
        LOGGER.info("{}条数据,开始存储数据库!", list.size());
        demoDAO.save(list);
        LOGGER.info("存储数据库成功!");
    }
}
/**
 * 假设这个是你的DAO存储。当然还要这个类让spring管理,当然你不用需要存储,也不需要这个类。
 **/
public class DemoDAO {
    public void save(List<DemoData> list) {
        // 如果是mybatis,尽量别直接调用多次insert,自己写一个mapper里面新增一个方法batchInsert,所有数据一次性插入
    }
}
    /**
     * 最简单的读
     * <p>1. 创建excel对应的实体对象 参照{@link DemoData}
     * <p>2. 由于默认一行行的读取excel,所以需要创建excel一行一行的回调监听器,参照{@link DemoDataListener}
     * <p>3. 直接读即可
     */
    @Test
    public void simpleRead() {
        // 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
        // 写法1:
        String fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx";
        // 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
        EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).sheet().doRead();

        // 写法2:
        fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx";
        ExcelReader excelReader = null;
        try {
            excelReader = EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).build();
            ReadSheet readSheet = EasyExcel.readSheet(0).build();
            excelReader.read(readSheet);
        } finally {
            if (excelReader != null) {
                // 这里千万别忘记关闭,读的时候会创建临时文件,到时磁盘会崩的
                excelReader.finish();
            }
        }
    }

注解

@ExcelProperty(value="字段值",index=1) //index指定该字段在第几个列表展示   
@ExcelIgnore  忽略某个字段
@DateTimeFormat()  日期格式  比如 :yyyy-MM-dd

测试类

添加注解
@SpringBootTest(classes = MonitorHubApplication.class)
@RunWith(SpringRunner.class)

stream

        List<User> users= Arrays.asList(
               new User(1, "1111","1111","wang1","男","济南","19999",1),
               new User(2, "1111","1111","wang2","男","济南","1999",2),
               new User(3, "3333","1111","wang3","男","威海","1999",1),
               new User(4, "4444","1111","wang4","男","青岛","1999",3),
               new User(5, "5555","1111","wang5","女","烟台","1999",null)
       );

常用的stream三种创建方式

  • 集合 Collection.stream()
  • 静态方法 Stream.of
  • 数组 Arrays.stream
//1.集合
Stream<Student> stream = list.stream();
//2.静态方法
Stream<String> stream2 = Stream.of("a", "b", "c");
//3.数组
String[] arr = {"a","b","c"};
Stream<String> stream3 = Arrays.stream(arr);

Stream的终止操作

  1. foreach(Consumer c) 遍历操作
  2. collect(Collector) 将流转化为其他形式
  3. max(Comparator) 返回流中最大值
  4. min(Comparator) 返回流中最小值
  5. count 返回流中元素综述

映射

Map

接收流中元素,并且将其映射成为新元素

 List<Map<String, Object>> list1 = users.stream().map(e->{
                 Map<String,Object> map=new HashMap<>();
                 map.put(e.getName(),e.getDept_id());
                 return map;
            }).collect(Collectors.toList());  //生成新的map
            
 list1.forEach(System.out::println);`
flatMap

.flatMap(s -> s.stream()) 一段代码将所有集合打散合成一个流,后续再对流进行中间操作

 List<Integer> list1 = new ArrayList<>();
        List<String> list2 = new ArrayList<>();
        List<String> list3 = new ArrayList<>();
        List<User> list4 = new ArrayList<>();
        List<User> list5 = new ArrayList<>();
        list1.add(1);
        list1.add(2);
        list1.add(3);
        list2.add("aa");
        list2.add("bb");
        list2.add("cc");
        list3.add("a");
        list3.add("b");
        list3.add("c");
        list4.add(new User(1,"小红a"));
        list4.add(new User(2,"小明a"));
        list5.add(new User(3,"小红B"));
        list5.add(new User(4,"小明B"));
        //1。将三个list合为一个  
        final List<? extends Serializable> collect = Stream.of(list1, list2, list3).flatMap(s -> s.stream()).collect(Collectors.toList());
        System.out.println(collect.toString());
        //2.将两个List<Integer>合2为一
        List<String> list = Stream.of(list2, list3).flatMap(s -> s.stream()).collect(Collectors.toList());
        System.out.println(list.toString());
        //3.获取两个List<User>中得所有名字name集合
        List<String> collect1 = Stream.of(list4, list5).flatMap(s -> s.stream().map(User::getName)).collect(Collectors.toList());
        System.out.println(collect1.toString());

结果

[1, 2, 3, aa, bb, cc, a, b, c]
[aa, bb, cc, a, b, c]
[小红a, 小明a, 小红B, 小明B]

peek(Consumer c)

获取流中元素,操作流中元素,与foreach不同的是不会截断流,可继续操作流

//将DeptId为空的User变为99
            Map<Integer, List<User>> collect2 = users.stream().peek(e -> {
                if (e.getDeptId() == null) {
                    e.setDeptId(99);
                }
            }).collect(Collectors.groupingBy(User::getDeptId));

分组

            //按部门分组
            Map<Integer, List<User>> collect2 = users.stream().peek(e -> {
                if (e.getDeptId() == null) {
                    e.setDeptId(99);
                }
            }).collect(Collectors.groupingBy(User::getDeptId));
            System.out.println(collect2);
           //每个部门的个数
            Map<Integer, Long> collect = users.stream().peek(e -> {
                if (e.getDeptId() == null) {
                    e.setDeptId(99);
                }
            }).collect(Collectors.groupingBy(User::getDeptId, Collectors.counting()));
            System.out.println(collect);
            //每个部门userid最大的
            Map<Integer, Optional<User>> collect1 = users.stream().peek(e -> {
                if (e.getDeptId() == null) {
                    e.setDeptId(99);
                }
            }).collect(Collectors.groupingBy(User::getDeptId, Collectors.maxBy(Comparator.comparing(User::getUserid))));
            System.out.println(collect1);            

            System.out.println("lamba表达式进行分组");
            Map<String, List<User>> collect3 = users.stream().peek(e -> {
                if (e.getDeptId() == null) {
                    e.setDeptId(99);
                }
            }).collect(Collectors.groupingBy(user -> {
                if (user.getEmail().length() > 4)
                    return "格式不正确";
                else
                    return "格式正确";
            }));
            System.out.println(collect3.get("格式正确"));
            System.out.println(collect3.get("格式不正确"));
结果
按部门分组
{1=[User{id=1, userid='1111', password='1111', name='wang1', sex='男', adress='济南', email='19999', deptId=1}, User{id=3, userid='3333', password='1111', name='wang3', sex='男', adress='威海', email='1999', deptId=1}], 2=[User{id=2, userid='1111', password='1111', name='wang2', sex='男', adress='济南', email='1999', deptId=2}], 99=[User{id=5, userid='5555', password='1111', name='wang5', sex='女', adress='烟台', email='1999', deptId=99}], 3=[User{id=4, userid='4444', password='1111', name='wang4', sex='男', adress='青岛', email='1999', deptId=3}]}
每个部门的个数
{1=2, 2=1, 99=1, 3=1}
每个部门userid最大的
{1=Optional[User{id=3, userid='3333', password='1111', name='wang3', sex='男', adress='威海', email='1999', deptId=1}], 2=Optional[User{id=2, userid='1111', password='1111', name='wang2', sex='男', adress='济南', email='1999', deptId=2}], 99=Optional[User{id=5, userid='5555', password='1111', name='wang5', sex='女', adress='烟台', email='1999', deptId=99}], 3=Optional[User{id=4, userid='4444', password='1111', name='wang4', sex='男', adress='青岛', email='1999', deptId=3}]}
lamba表达式进行分组
[User{id=2, userid='1111', password='1111', name='wang2', sex='男', adress='济南', email='1999', deptId=2}, User{id=3, userid='3333', password='1111', name='wang3', sex='男', adress='威海', email='1999', deptId=1}, User{id=4, userid='4444', password='1111', name='wang4', sex='男', adress='青岛', email='1999', deptId=3}, User{id=5, userid='5555', password='1111', name='wang5', sex='女', adress='烟台', email='1999', deptId=99}]
[User{id=1, userid='1111', password='1111', name='wang1', sex='男', adress='济南', email='19999', deptId=1}]

组内分组

//按照地区分组后再按部门分组
            Map<String, Map<Integer, List<User>>> collect4 = users.stream().peek(e -> {
                if (e.getDeptId() == null) {
                    e.setDeptId(99);
                }
            }).collect(Collectors.groupingBy(User::getAdress, Collectors.groupingBy(User::getDeptId)));
            out.println(collect4);
            Set set = collect4.keySet();
            out.println(set);
            for (Object key : set) {
                out.println(collect4.get(key));
            }
            
            System.out.println("lamba:按照地区分组后再按邮箱是否合格分组");
            Map<String, Map<String, List<User>>> collect5 = users.stream().peek(e -> {
                if (e.getDeptId() == null) {
                    e.setDeptId(99);
                }
            }).collect(Collectors.groupingBy(User::getAdress, Collectors.groupingBy(users -> {
                if (users.getEmail().length() > 4)
                    return "合格";
                else
                    return "不合格";
            })));
            Set set2 = collect5.keySet();
            out.println(set2);
            for (Object key : set2) {
                out.println(collect5.get(key));
            }
            
按照地区分组后再按部门分组
{济南={1=[User{id=1, userid='1111', password='1111', name='wang1', sex='男', adress='济南', email='19999', deptId=1}], 2=[User{id=2, userid='1111', password='1111', name='wang2', sex='男', adress='济南', email='1999', deptId=2}]}, 青岛={3=[User{id=4, userid='4444', password='1111', name='wang4', sex='男', adress='青岛', email='1999', deptId=3}]}, 烟台={99=[User{id=5, userid='5555', password='1111', name='wang5', sex='女', adress='烟台', email='1999', deptId=99}]}, 威海={1=[User{id=3, userid='3333', password='1111', name='wang3', sex='男', adress='威海', email='1999', deptId=1}]}}

[济南, 青岛, 烟台, 威海]

{1=[User{id=1, userid='1111', password='1111', name='wang1', sex='男', adress='济南', email='19999', deptId=1}], 2=[User{id=2, userid='1111', password='1111', name='wang2', sex='男', adress='济南', email='1999', deptId=2}]}
{3=[User{id=4, userid='4444', password='1111', name='wang4', sex='男', adress='青岛', email='1999', deptId=3}]}
{99=[User{id=5, userid='5555', password='1111', name='wang5', sex='女', adress='烟台', email='1999', deptId=99}]}
{1=[User{id=3, userid='3333', password='1111', name='wang3', sex='男', adress='威海', email='1999', deptId=1}]}

lamba:按照地区分组后再按邮箱是否合格分组

[济南, 青岛, 烟台, 威海]

{不合格=[User{id=2, userid='1111', password='1111', name='wang2', sex='男', adress='济南', email='1999', deptId=2}], 合格=[User{id=1, userid='1111', password='1111', name='wang1', sex='男', adress='济南', email='19999', deptId=1}]}
{不合格=[User{id=4, userid='4444', password='1111', name='wang4', sex='男', adress='青岛', email='1999', deptId=3}]}
{不合格=[User{id=5, userid='5555', password='1111', name='wang5', sex='女', adress='烟台', email='1999', deptId=99}]}
{不合格=[User{id=3, userid='3333', password='1111', name='wang3', sex='男', adress='威海', email='1999', deptId=1}]}

            ConcurrentMap<Boolean, List<String>> collect1 = Stream.of(list2, list3)
                    .flatMap(e -> e.stream())
                    .collect(Collectors.groupingByConcurrent(e -> e.length() > 1));

比较器+排序sort

            //按照部门从降序排序
            System.out.println("Comparator函数实现");
            List<User> collect = users.stream()
                    .filter(e -> e.getDeptId() != null)
                    .sorted(Comparator.comparing(User::getDeptId).reversed())
                    .collect(Collectors.toList());
            collect.forEach(System.out::println);

            System.out.println("lamba函数实现");
            List<User> collect1 = users.stream()
                    .filter(e -> e.getDeptId() != null)
                    .sorted((users1, users2) -> -users1.getDeptId().compareTo(users2.getDeptId()))
                    .collect(Collectors.toList());
            collect1.forEach(System.out::println);

            System.out.println("----------------------------------------------------------------------------------------------------------");

            //按照Userid降序排序,按照部门升序排序
            System.out.println("Comparator函数实现");
            List<User> collect2 = users.stream()
                    .filter(e -> e.getDeptId() != null)
                    .sorted(Comparator.comparing(User::getUserid).reversed().thenComparing(User::getDeptId))
                    .collect(Collectors.toList());
            collect2.forEach(System.out::println);

            System.out.println("lamba函数实现");
            List<User> collect3 = users.stream().filter(e -> e.getDeptId() != null).sorted((users1, users2) -> {
                if (users1.getUserid().equals(users2.getUserid()))
                    return users1.getDeptId().compareTo(users2.getDeptId());
                else
                    return -users1.getUserid().compareTo(users2.getUserid());
            }).collect(Collectors.toList());
            collect3.forEach(System.out::println);
        }


 
排序结果:
Comparator函数实现
User{id=4, userid='4444', password='1111', name='wang4', sex='男', adress='青岛', email='1999', deptId=3}
User{id=2, userid='1111', password='1111', name='wang2', sex='男', adress='济南', email='1999', deptId=2}
User{id=1, userid='1111', password='1111', name='wang1', sex='男', adress='济南', email='19999', deptId=1}
User{id=3, userid='3333', password='1111', name='wang3', sex='男', adress='威海', email='1999', deptId=1}
lamba函数实现
User{id=4, userid='4444', password='1111', name='wang4', sex='男', adress='青岛', email='1999', deptId=3}
User{id=2, userid='1111', password='1111', name='wang2', sex='男', adress='济南', email='1999', deptId=2}
User{id=1, userid='1111', password='1111', name='wang1', sex='男', adress='济南', email='19999', deptId=1}
User{id=3, userid='3333', password='1111', name='wang3', sex='男', adress='威海', email='1999', deptId=1}
----------------------------------------------------------------------------------------------------------
Comparator函数实现
User{id=4, userid='4444', password='1111', name='wang4', sex='男', adress='青岛', email='1999', deptId=3}
User{id=3, userid='3333', password='1111', name='wang3', sex='男', adress='威海', email='1999', deptId=1}
User{id=1, userid='1111', password='1111', name='wang1', sex='男', adress='济南', email='19999', deptId=1}
User{id=2, userid='1111', password='1111', name='wang2', sex='男', adress='济南', email='1999', deptId=2}
lamba函数实现
User{id=4, userid='4444', password='1111', name='wang4', sex='男', adress='青岛', email='1999', deptId=3}
User{id=3, userid='3333', password='1111', name='wang3', sex='男', adress='威海', email='1999', deptId=1}
User{id=1, userid='1111', password='1111', name='wang1', sex='男', adress='济南', email='19999', deptId=1}
User{id=2, userid='1111', password='1111', name='wang2', sex='男', adress='济南', email='1999', deptId=2}

去重

按一个字段去重
List<Map<String, Object>> dlist = readbooks.readFile(file.getInputStream());
        //將表格导入的数据去重
        List<Map<String, String>> data = dlist.stream().map(e -> {
            Map<String, String> map1 = new HashMap<>();
            map1.put("0", e.get("0").toString());
            map1.put("1", e.get("1").toString());
            return map1;
        }).collect(Collectors.toList());
      	  data = data.stream()
                .collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(m -> m
                        .get("1")))), ArrayList::new));
按多个字段去重
List<ClassEntity> distinctClass = classEntities.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(o -> o.getProfessionId() + ";" + o.getGrade()))), ArrayList::new));

其他

//根据部门计算数量,总值,最大最小,平均值
  DoubleSummaryStatistics collect2 = users.stream().filter(e -> e.getDeptId() != null).collect(Collectors.summarizingDouble(User::getDeptId));
            out.println(collect2);

//查找最大值
  Optional<User> collect1 = users.stream().filter(e -> e.getDeptId() != null).collect(Collectors.maxBy(Comparator.comparing(User::getDeptId)));
            collect1.ifPresent(out::println);
//查找最小值举例:minby()中放的是自定义比较器(适用于比较条件复杂的情况)
  Optional<User> collect3 = users.stream().collect(Collectors.minBy((users1, users2) -> {
                if (users1.getUserid().equals(users2.getUserid())){
                    System.out.println(users1.getDeptId().compareTo(users2.getDeptId()));
                    return -users1.getDeptId().compareTo(users2.getDeptId());
                }
                else
                    return -users1.getUserid().compareTo(users2.getUserid());
            }));     
DoubleSummaryStatistics{count=4, sum=7.000000, min=1.000000, average=1.750000, max=3.000000}
User{id=4, userid='4444', password='1111', name='wang4', sex='男', adress='青岛', email='1999', deptId=3}
-1
minOptional[User{id=5, userid='5555', password='1111', name='wang5', sex='女', adress='烟台', email='1999', deptId=null}]
匹配
  1. booelan allMatch(Predicate) 都符合
  2. boolean anyMatch(Predicate) 任一元素符合
  3. boolean noneMatch(Predicate) 都不符合
boolean b = basketballClub.stream().allMatch(e -> e.getAge() < 20);
boolean b1 = basketballClub.stream().anyMatch(e -> e.getAge() < 20);
boolean b2 = basketballClub.stream().noneMatch(e -> e.getAge() < 20);
寻找元素
  1. findFirst——返回第一个元素
  2. findAny——返回当前流中的任意元素
Optional<Student> first = basketballClub.stream().findFirst();
if (first.isPresent()) {   //IsPresent判断对象是否存在
    Student student = first.get();
    System.out.println(student);
}

Optional<Student> any = basketballClub.stream().findAny();
if (any.isPresent()) {
    Student student2 = any.get();
    System.out.println(student2);
}
Optional<Student> any1 = basketballClub.stream().parallel().findAny();
System.out.println(any1);
计数与极值
  1. count——返回流中元素的总个数
  2. max——返回流中最大值
  3. min——返回流中最小值
long count = basketballClub.stream().count();
Optional<Student> max = basketballClub.stream().max(Comparator.comparing(Student::getAge));
if (max.isPresent()) {
    Student student = max.get();
}
Optional<Student> min = basketballClub.stream().min(Comparator.comparingInt(Student::getAge));
if (min.isPresent()) {
    Student student = min.get();
}

MAP

根据 id 和 name 将其转成 Map 集合

Map<Long, String> map = list.stream()
.collect(Collectors.toMap(GroupInfoEntity::getId, GroupInfoEntity::getName));

根据 id 和 对象自己 转成 Map 集合

Map<Long, GroupInfoEntity> map = list.stream()
.collect(Collectors.toMap(GroupInfoEntity::getId, Function.identity()));

防止key重复

一般toMap时只用到两个参数,第一个设定Key,第二个设定value。但如果Key重复的话,那就需要用到第三个参数,可以这么写(k1,
k2)-> k1。
什么意思呢,就是说如果k1和k2的key都相同,那么只取k1的值去覆盖之前的值,也可以改为取k2的值,这样就解决了duplicate
key的问题

Map<Long, String> map = list.stream()
.collect(Collectors.toMap(GroupInfoEntity::getId, GroupInfoEntity::getName, (k1, k2) -> k1));

TreeMap

按key值从大到小

        TreeMap<Integer, List<DepartmentDTO>> treeMap = new TreeMap<>(Comparator.reverseOrder());
        treeMap.putAll(collect); //将要排序的map放入treeMap中

逆向工程

    mybatis需要程序员自己编写sql语句,mybatis官方提供逆向工程,可以针对单表自动生成mybatis执行所需要的代码(mapper.java、mapper.xml、pojo…),可以让程序员将更多的精力放在繁杂的业务逻辑上。

    企业实际开发中,常用的逆向工程方式:由数据库的表生成java代码。

    之所以强调单表两个字,是因为Mybatis逆向工程生成的Mapper所进行的操作都是针对单表的,也许你可能会觉得那这就有点鸡肋了,但是在大型项目中,很少有复杂的多表关联查询,所以作用还是很大的

依赖

<!-- SpringBoot - MyBatis -->
<dependency>
  <groupId>org.mybatis.spring.boot</groupId>
  <artifactId>mybatis-spring-boot-starter</artifactId>
  <version>1.3.0</version>
</dependency>
<!-- SpringBoot - MyBatis 逆向工程 -->
<dependency>
  <groupId>org.mybatis.generator</groupId>
  <artifactId>mybatis-generator-core</artifactId>
  <version>1.3.2</version>
</dependency>
 
<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>5.1.40</version>
</dependency>

插件

build>
        <plugins>
            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.3.5</version>
                <configuration>
                    <!-- 在控制台打印执行日志 -->
                    <verbose>true</verbose>
                    <!-- 重复生成时会覆盖之前的文件-->
                    <overwrite>true</overwrite>
                    <configurationFile>src/main/resources/generatorConfig.xml</configurationFile>
                </configuration>
                <!-- 数据库连接选择8.0以上的,因为用的mysql8.0-->
                <dependencies>
                    <dependency>
                        <groupId>mysql</groupId>
                        <artifactId>mysql-connector-java</artifactId>
                        <version>8.0.13</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
    </build>

generatorConfig.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
    <!-- context 是逆向工程的主要配置信息 -->
    <!-- id:起个名字 -->
    <!-- targetRuntime:设置生成的文件适用于那个 mybatis 版本 -->

    <context id="default" targetRuntime="MyBatis3">
        <property name="suppressTypeWarnings" value="true" />
<!--        <plugin type="org.mybatis.generator.plugins.UnmergeableXmlMappersPlugin" />-->
        <plugin type="org.mybatis.generator.plugins.SerializablePlugin" />
        <plugin type="org.mybatis.generator.plugins.CaseInsensitiveLikePlugin" />
        <plugin type="org.mybatis.generator.plugins.RowBoundsPlugin" />
        <plugin type="org.mybatis.generator.plugins.RenameExampleClassPlugin">
            <property name="searchString" value="Example$" />
            <property name="replaceString" value="Criteria" />
        </plugin>
        <!--optional,指在创建class时,对注释进行控制-->
        <commentGenerator>
            <property name="suppressDate" value="true"/>
            <!-- 是否去除自动生成的注释 true:是 : false:否 -->
            <property name="suppressAllComments" value="true"/>
        </commentGenerator>
        <!--jdbc的数据库连接 wg_insert 为数据库名字-->
        <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
                        connectionURL="jdbc:mysql://10.10.16.246:3306/vops_asset_hub?useUnicode=true&amp;characeterEncoding=utf-8&amp;serverTimezone=Asia/Shanghai"
                        userId="root"
                        password="goldencis">
            <property name="nullCatalogMeansCurrent" value="true"/>
        </jdbcConnection>
        <!--非必须,类型处理器,在数据库类型和java类型之间的转换控制-->
        <javaTypeResolver>
            <!-- 默认情况下数据库中的 decimal,bigInt 在 Java 对应是 sql 下的 BigDecimal 类 -->
            <!-- 不是 double 和 long 类型 -->
            <!-- 使用常用的基本类型代替 sql 包下的引用类型 -->
            <property name="forceBigDecimals" value="false"/>
        </javaTypeResolver>
        <!-- targetPackage:生成的实体类所在的包 -->
        <!-- targetProject:生成的实体类所在的硬盘位置 -->
        <javaModelGenerator targetPackage="com.example.demo.pojo"
                            targetProject="src/main/java">
            <!-- 是否允许子包 -->
            <property name="enableSubPackages" value="false"/>
            <!-- 是否对modal添加构造函数 -->
            <property name="constructorBased" value="true"/>
            <!-- 是否清理从数据库中查询出的字符串左右两边的空白字符 -->
            <property name="trimStrings" value="true"/>
            <!-- 建立modal对象是否不可改变 即生成的modal对象不会有setter方法,只有构造方法 -->
            <property name="immutable" value="false"/>
        </javaModelGenerator>
        <!-- targetPackage 和 targetProject:生成的 mapper 文件的包和位置 -->
        <sqlMapGenerator targetPackage="mybatis.mapper"
                         targetProject="src/main/resources">
            <property name="enableSubPackages" value="false"/>
        </sqlMapGenerator>
        <!-- targetPackage 和 targetProject:生成的 interface 文件的包和位置 -->
        <javaClientGenerator type="XMLMAPPER"
                             targetPackage="com.example.demo.mapper" targetProject="src/main/java">
            <property name="enableSubPackages" value="false"/>
        </javaClientGenerator>
        <!-- tableName是数据库中的表名,domainObjectName是生成的JAVA模型名,后面的参数不用改,要生成更多的表就在下面继续加table标签 -->
        <table tableName="t_camera" domainObjectName="Camera"
               enableCountByExample="true" enableUpdateByExample="true"
               enableDeleteByExample="true" enableSelectByExample="true"
               selectByExampleQueryId="true"></table>
    </context>
</generatorConfiguration>

启用格式

方式一:
       CameraCriteria cameraCriteria = new CameraCriteria();
       usersCriteria.or().andXXXX
    
方式二:criteria1与criteria2是or的关系 
       DemoExample example=new DemoExample ();
       DemoExample.Criteria criteria=example.createCriteria();
       criteria.andidEqualTo(id);
       criteria.andStatusEqualTo("0");
		
       DemoExample.Criteria criteria2=example.createCriteria();
       criteria2.andidEqualTo(id);
       criteria2.andstatusEqualTo("1");
       example.or(criteria2);
       dao.countByExample(example);
       
       select count(*) from demo WHERE ( ID = ? and STATUS = ? ) or( ID = ? and STATUS = ? ) 
example增加条件例子
    查询条件1:a=? and (b=? or c=?) ==不支持==
    查询条件2(a=? And b=?) or (a=? And c=?) ==支持==
 
//想要查询(地址在丰奥家园)并且(部门为1到2或者4到5) 去重并且按照部门升序 
    UsersCriteria usersCriteria = new UsersCriteria();
    usersCriteria.or().andAddressEqualTo("丰奥家园").andDeptIdBetween(1,2);
    usersCriteria.or().andAddressEqualTo("丰奥家园").andDeptIdBetween(4,5);
    usersCriteria.setDistinct(true);
    usersCriteria.setOrderByClause("dept_id  asc");   //desc降序
    
//SQL==
    select distinct  id, userid, passward, name, sex, address, email, dept_id from usertb WHERE ( address = ? and dept_id between ? and ? ) or( address = ? and dept_id between ? and ? ) order by dept_id asc     
    

    IS NULL-表示相关列必须为NULL
    IS NOT NULL-表示相关列不能为NULL
    =(等于)-表示相关列必须等于方法调用中传递的值
    <>(不等于)-表示相关列不得等于方法调用中传递的值
    >(大于)-表示相关列必须大于方法调用中传递的值
    > =(大于或等于)-表示相关列必须大于或等于在方法调用中传递的值
    <(小于)-表示相关列必须小于方法调用中传递的值
    <=(小于或等于)-表示相关列必须小于或等于在方法调用中传递的值
    LIKE-表示相关列必须与方法调用中传递的值“相似”。 该代码未添加必需的’%’,您必须在方法调用中传递的值中自行设置该值。
    不喜欢-意味着相关列必须“不喜欢”方法调用中传递的值。 该代码未添加必需的’%’,您必须在方法调用中传递  的值中自行设置该值。
    BETWEEN-表示相关列必须在方法调用中传递的两个值之间。
    NOT BETWEEN-表示相关列必须在方法调用中传递的两个值之间“不在”之间。
    IN-表示相关列必须是方法调用中传入的值列表之一。
    NOT IN-表示相关列不得为方法调用中传递的值列表之一

分页查询
   int start = (currentPage - 1) * rows;
    //分页查询中的一页数量
    example.setPageSize(rows);   
    //开始查询的位置
    example.setStartRow(start);
    List<User> userList=userMapper.selectByExample(example);
    类似于:select * from user limit start to rows

到此为止,以上这些方法足够对单表进行操作,将所需要的数据取出来之后字啊用stream进行去重,映射,排序等操作;

增:

    int insert(User record);          插入新数据 有null则插入null
    int insertSelective(User record); 只将有值的属性进行插入

两者区别详解

    int deleteByExample(UserCriteria example);
    int deleteByPrimaryKey(Integer id);

改:

    int updateByExample(要更新的对象,条件);   根据条件将属性全部更新 
    int updateByExampleSelective(要更新的对象,条件);  根据条件将不为null的属性进行更新
    int updateByPrimaryKey(对象);  将传入的实体对象全部更新
    int updateByPrimaryKeySelective(对象); 将传入的实体对象的不为null的属性进行更新

     List<User> selectByExample(UserCriteria example);
     User selectByPrimaryKey(Integer id);

MySQL

case when

关于CASE WHEN的表达方式有两种:“简单CASE函数法“和“CASE搜索函数法”。
“简单CASE函数法”的语法更加简洁,但是只能处理等式的问题;
“CASE搜索函数法”更加灵活好用,可以处理等式问题也可以处理不等式问题。

离散数值与实际业务含义的一一对应

select *,
	case
	when Is_Discount =1 then "享受折扣"
	else "无折扣"
	end Discount_new,# 新列名
	case
	when Pay_Type in (1,3,5,7,10) then "微信支付"
	when Pay_Type in (6,9,12) then "银行卡支付"
	else "支付宝支付"
	end Pay_type_new# 新列名
from goods_orders
limit 5;

在这里插入图片描述

根据用户的出生日期将用户划分为60后、70后、80后、90后

select *,
	case
	when year(Birthday) between 1960 and 1969 then "60"
	when year(Birthday) between 1970 and 1979 then "70"
	when year(Birthday) between 1980 and 1989 then "80"
	else "90"
	end "年龄段"
from goods_orders
limit 5;

在这里插入图片描述

2018年每月各种支付方式的交易额

select month(Order_Date) as iMonth,# 提取月份
	case
	when Pay_Type in (1,3,5,7,10) then "微信支付"
	when Pay_Type in (6,9,12) then "银行卡支付"
	else "支付宝支付"
	end iType,
	sum(Pay_Amt) as Amt# 交易额
from goods_orders
where year(Order_Date) = 2018
group by month(Order_Date),itype
order by iMonth;

在这里插入图片描述

长形统计表转换成宽形统计表

select month(Order_Date) as iMonth,
	sum(case when Pay_Type in (1,3,5,7,10) then Pay_Amt end) as "weixin",
	sum(case when Pay_Type in (6,9,12) then Pay_Amt end) as "yinhangka",
	sum(case when Pay_Type in (2,4,8,11) then Pay_Amt end) as "zhifubao"
from goods_orders
where year(Order_Date) = 2018
group by iMonth
order by iMonth;

在这里插入图片描述

公司

//按照WBDW进行分组,并统计每组中SBZT(1:启用中---),总数和WBDQ(时间:已过保,维保到期)的数量
    <select id="getReportLifeCycle" parameterType="map" resultType="map">
        select WBDW,
        COUNT(1) totol,
        SUM(CASE WHEN SBZT = 1 THEN 1 ELSE 0 END) qiyongzhong, ## 每个case都会在结果中重新追加一列
        SUM(CASE WHEN SBZT = 2 THEN 1 ELSE 0 END) weixiu,
        SUM(CASE WHEN SBZT = 3 THEN 1 ELSE 0 END) chaichu,
        SUM(CASE WHEN SBZT = 4 THEN 1 ELSE 0 END) tingyong,
        SUM(CASE WHEN SBZT = 5 THEN 1 ELSE 0 END) daiyanshou,
        SUM(CASE WHEN DATEDIFF(WBDQ,NOW()) &lt;= 30 and DATEDIFF(WBDQ,NOW())&gt;0 THEN 1 ELSE 0 END) lessthrity,
        SUM(CASE WHEN date_format(WBDQ,'%Y-%m-%d') &lt; now() THEN 1 ELSE 0 END) yiguobao
        from    
        (select
        (CASE WHEN WBDW IS NULL THEN "未知单位" ELSE WBDW END ) WBDW,WBDQ,SBZT
        from t_asset_info  where    ## 添加条件
        <if test="assettypes != null and assettypes !='-1'">
            asset_type in (select  t2.id from t_asset_type t1 left join t_asset_type t2 on t1.id=t2.type_parent where t1.id=#{assettypes}) or asset_type=#{assettypes} and
        </if>
         main_show = 1) as c
        GROUP BY WBDW
        ORDER BY WBDW
    </select>

模糊匹配 Pattern和Matcher

	
	public boolean matcher(String userName(要匹配的str),String matchername(匹配模型)){
        Pattern pattern = Pattern.compile(matchername);
        Matcher matcher = pattern.matcher(userName);
        if(matcher.find()){
            return true;
        }else{
           return  false;
        }
    }

searchstr

      <if test="params.searchstr!=null and params.searchstr!=''">
        and ( name like CONCAT('%',#{params.searchstr},'%') or camera_index_code like CONCAT('%',#{params.searchstr},'%'))
      </if>

输出文件流

try {
           File file = new File("C:\\Users\\yinhd\\Desktop\\tollgateObjects.txt");
           if (!file.exists()) {
                   file.createNewFile();
             }
               BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(file, true));
               bufferedWriter.write(subscribeNotificationObject.toString());
                bufferedWriter.write("\r\n");
               bufferedWriter.flush();
                bufferedWriter.close();
           } catch (Exception e) {
             log.error("输出卡口设备报错{}", e.toString());        
     }

解决磁盘满的问题

下面给大家分享一篇关于Linux服务器磁盘占满问题解决方法(/dev/sda3 满了),需要的的朋友参考下吧

下面我们一起来看一篇关于Linux服务器磁盘占满问题解决(/dev/sda3 满了),希望碰到此类问题的人能带来帮助。

今天下班某电商技术部leader发现个问题,说他们服务器硬盘满了。把日志文件都删掉了,可硬盘空间依旧满。于是df -h查看了下各个挂载点的状况(如下图)。

/dev/sda3占用了100%,那么我们du -s -h ./*看下目录的占用情况(如下图)。
在这里插入图片描述

在工作中,我们也许会遇到这样的问题,发现某个磁盘空间快满了,于是,找到一些无用的大文件将其删除后,发现磁盘空间还是没有释放掉,这是什么原因呢?如何解决呢?下面来重现一下整个过程:

查看磁盘空间情况

[@74.114 var]# df -h
Filesystem      Size Used Avail Use% Mounted on
/dev/xvda2      9.7G 284M 8.9G  4% /
/dev/xvda1      251M  13M 226M  6% /boot
none         1.1G   0 1.1G  0% /dev/shm
/dev/xvda10      97G  60G  33G 65% /home
/dev/xvda3      3.9G 2.7G 1.1G 72% /usr
/dev/xvda5      3.9G 3.6G  77M 98% /var

var分区快满了,找到大文件,并删除

[@74.114 var]# cd /var
[@74.114 var]# du –sh *
3.3G  account
111M  cache
53M   log
0    mail
156K  run
344K  spool
[@74.114 var]# rm –rf account/*

df –h 看一下,却依然是/var 为98%,一点都没释放。

[@74.114 var]# df -h
Filesystem      Size Used Avail Use% Mounted on
/dev/xvda2      9.7G 284M 8.9G  4% /
/dev/xvda1      251M  13M 226M  6% /boot
none         1.1G   0 1.1G  0% /dev/shm
/dev/xvda10      97G  60G  33G 65% /home
/dev/xvda3      3.9G 2.7G 1.1G 72% /usr
/dev/xvda5      3.9G 3.6G  77M 98% /var

但du –sh * 却显示没有大文件了

[@74.114 ~]# cd /var && du –sh *
120K  account
111M  cache
53M   log
0    mail
156K  run
344K  spool

猜想1:应该是删除的内容依然被进程占用,内存没释放,所以用lsof |grep – I deleted 看了一下,发现如下:

[@74.114 account]# lsof |grep -i deleted
listserve 4833      blty  0u   CHR   136,2          4 /dev/pts/2 (deleted)
listserve 4833      blty  1u   CHR   136,2          4 /dev/pts/2 (deleted)
listserve 4833      blty  2u   CHR   136,2          4 /dev/pts/2 (deleted)
Billing_P 16989      blty  0u   CHR   136,0          2 /dev/pts/0 (deleted)
Billing_P 16989      blty  1u   CHR   136,0          2 /dev/pts/0 (deleted)
Billing_P 16989      blty  2u   CHR   136,0          2 /dev/pts/0 (deleted)
Billing_P 16990      blty  0u   CHR   136,0          2 /dev/pts/0 (deleted)
Billing_P 16990      blty  1u   CHR   136,0          2 /dev/pts/0 (deleted)
Billing_P 16990      blty  2u   CHR   136,0          2 /dev/pts/0 (deleted)

发现时billing程序占用没释放,所以联系项目经理将Billing_P停掉,重启,依然没有释放任何空间。无果
猜想2:删除的文件是accout目录下的pacct文件,应该是由psacct产生和管理,重启这个程序后是否会OK呢?解决

[@74.114 account]# /etc/init.d/psacct restart

最后看一下磁盘空间,磁盘空间释放鸟~~

[@74.114 var]# df -h
Filesystem      Size Used Avail Use% Mounted on
/dev/xvda2      9.7G 284M 8.9G  4% /
/dev/xvda1      251M  13M 226M  6% /boot
none         1.1G   0 1.1G  0% /dev/shm
/dev/xvda10      97G  60G  33G 65% /home
/dev/xvda3      3.9G 2.7G 1.1G 72% /usr
/dev/xvda5      3.9G 100M  3.6M 4% /var

小建议:

以后处理相关问题时,如果发现du 和df 大小不一致的情况,可以通过lsof 查看,也许可以找到一些出现问题的原因,如果还是找不到问题,在允许的情况下不妨试一下重启服务,也许问题就迎刃而解了。
重启服务得不到解决的情况下,可以通过卸载磁盘分区来试着解决。

在决定删除某些文件前,最好确定好这个文件被哪些服务使用,先停掉这些服务再删除,这样就很少出现空间释放不了的情况了
linux磁盘挂载点目录占用情况(图)
在这里插入图片描述
挂载点下的目录之和远小于4.5G,那么是什么占用了硬盘呢?

以下为该问题的解答:

在apache/tomcat服务在运行状态下,清空了运行服务的日志,从而导致了/dev/sda3 满了的问题。一般情况下,大多数服务(包括脚本)在运行时,是不能删除当前正在写入的日志文件的。

原理分析:

  1. 当前access.log日志正在被apache进程占用。

  2. 通过rm命令删除access.log,实际只删除了文件名(该日志文件应用记数不为0,因此空间不会被释放)。

  3. 通过rm命令删除了access.log后,apache依然写日志到access.log中,当开启apache进程时,已经通过access.log定位到该文件的inode了,就是说再写日志是不通过access.log,因此即使删除了access.log,apache依然写日志到access.log所在的inode节点,所以导致硬盘空间增加。

  4. 因为删除了access.log,所以我们就找不到该文件了,du也查不到,就会出现硬盘满了但看不到究竟是哪些文件占用的。
    (写的不甚详细,不明白的大家再google下。)

解决方法:

重启该日志文件的相关服务或程序,如:为apache日志文件则重启apache(如下图,重启后才硬盘空间占用正常)。

    UPDATE IPV4 =#{record.IPV4} ,asset_type =  if( asset_type !=47 ,asset_type, #{record.assetType}),SSXQGAJG = #{record.SSXQGAJG} ,online_status = #{record.onlineStatus},create_time = if( #{record.onlineStatus} = 0 ,create_time, #{record.createTime}) ,MACDZ = #{record.MACDZ}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值