美文网首页
java开发

java开发

作者: ljt001 | 来源:发表于2023-06-28 19:56 被阅读0次

    java开发小结

    注解

    @Serverice标记service类、business类

    @Repository标记仓储类

    @Autowired自动注入

    @Service
    public class StudentService {
        @Autowired
        private StudentRepository studentRepository;
    }
    
    @Repository
    public class StudentRepository {
    }
    
    

    String

    好多String的Util。

    import java.text.MessageFormat;
    import org.apache.commons.lang3.StringUtils;
    
    // 空字符串
    var str = StringUtils.EMPTY;
    var a = StringUtils.isEmpty(str);
    var b = StringUtils.isNotEmpty(str);
    var strArray = str.split(",");
    var strArray2 = StringUtils.split("a,b",',');
    
    // join
    var ids = new List<Integer>();
    ids.add(1);
    ids.add(2);
    StringUtils.join(ids,",")
    
    // 用MessageFormat.format 代替 String.format
    var str11 = String.format("id:{0} name:{1}", 111 ,1001);//没生效
    var str12 = String.format("id:%s name:%s", 111 ,1001);//生效,没有千分号
    var str22 = MessageFormat.format("id:{0} name:{1}", 111 ,1001);//注意:10001生成的字符串会有千分号
    var str23 = MessageFormat.format("id:{0} name:{1}", 111 ,String.valueOf(1001));//没有千分号
    

    Equals

    基本数值类型与包装类的等值比较。

    包装类对象为null时,==直接比较会抛异常。

    Integer对象为null时,执行j instance of Integer结果为false

    package demo;
    import java.util.Objects;
    import org.junit.jupiter.api.Test;
    import cn.hutool.core.util.ObjectUtil;
    import static org.junit.jupiter.api.Assertions.*;
    
    class IntegerEqualsTest {
        @Test
        public void intEqualsToIntegerNull_Error() {
            assertThrows(NullPointerException.class, () -> {
                int i = 0;
                Integer j = null;
                var result = i == j;
                fail("no null pointer expected");
            });
        }
    
        @Test
        public void intObjectUtilEqualsToIntegerNull_Success() {
            int i = 0;
            Integer j = null;
            var result = ObjectUtil.equals(i, j);
            assertFalse(result);
        }
    
        @Test
        public void intObjectsEqualsToIntegerNull_Success() {
            int i = 0;
            Integer j = null;
            var result = Objects.equals(i, j);
            assertFalse(result);
        }
        
        @Test
        public void integerValueOfIntEqualsToIntegerNull_Success() {
            int i = 0;
            Integer j = null;
            var result = Integer.valueOf(i).equals(j);
            assertFalse(result);
        }
        
        @Test
        public void integerNullInstanceofIntegerAsFalse(){
            Integer j = null;
            var result = j instanceof Integer;
            assertFalse(result);
        }
    }
    

    Json

    import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.JSONObject;
    import com.alibaba.fastjson.TypeReference;
    
    var student = new Student();
    var strStudent = JSON.toJSONString(student);
    student = JSON.parseObject(strStudent, Student.class)
    
    // 解析为列表
    List<Student> students = new ArrayList<>();
    students.add(student);
    var strStudents = JSON.toJSONString(student);
    students = JSON.parseArray(strStudents, Student.class);
    

    // 复杂类型,如HashMap且map的值为复杂结构,见下
    HashMap<String, Student> dataMap = JSON.parseObject(request.getData(), new TypeReference<HashMap<String, Student>>(){});
    HashMap<String, Student> dataMap = JSON.parseObject(request.getData(), new TypeReference<>(){});
    // 反例:在使用dataMap
    HashMap<String, Student> dataMap = JSON.parseObject(request.getData(), HashMap.class);
    for (var dataItem : dataMap.entrySet()) {
    // 调用getValue会出现转换异常
    var valueItem = dataItem.getValue();
    }

    DateTime

    import java.time.LocalDateTime;
    
    // 本地时间
    var now = LocalDateTime.now();
    var nowStr = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
    var date = now.toLocalDate();
    var time = now.toLocalTime();
    
    // 用时ms
    long startTime = System.currentTimeMillis();
    var elapsedMs = System.currentTimeMillis() - startTime;
    

    Array

    array和list互转参考:

    import org.apache.commons.lang3.ArrayUtils;
    
    String[] arr =  new String[]{ "a","b","c" };
    ArrayUtils.contains(arr,"a");
    
    // List:交集Intersect
    var ids1 = new ArrayList<Integer>(); ids1.add(1); ids1.add(2);
    var ids2 = new ArrayList<Integer>(); ids2.add(1); ids2.add(3);
    var ids3 = new ArrayList<Integer>(); ids3.add(2); ids3.add(4);
    // ids1作为交集结果有改变,ids2不变
    var flag = ids1.retainAll(ids2);
    assertTrue(flag);
    assertTrue(ids1.size()==1 && ids1.contains(1));
    assertTrue(ids2.size()==2 && ids2.contains(1) && ids2.contains(3));
    // ids3交ids2,ids3作为交集结果是空集合,ids2不变
    var flag2 = ids3.retainAll(ids2);
    assertTrue(flag);
    assertTrue(ids3.isEmpty());
    assertTrue(ids2.size()==2 && ids2.contains(1) && ids2.contains(3));
    
    // Array to List
    List<String> list = Arrays.asList(arr);
    var arr2 = list.toArray();
    var arr3 = list.toArray(new String[0]);
    var arr4 = list.toArray(new String[list.size()]);
    

    Collection

    列表:List/ArrayList/LinkedList (最终会继承Collection)
    字典:Map/HashMap/LinkedHashMap/ConcurrentHashMap(Map的values和keySet是Collection或最终继承Collection)

    import java.util.ArrayList;
    import java.util.List;
    import java.util.stream.Collectors;
    
    // .map(类似C#的select)
    // .filter(类似C#的where)
    // toList()、findFirst().orElse
    List<String> names=new ArrayList<>();
    names.add("tom");
    List<Student> students = new ArrayList<>();
    var ids = students.stream().map(x -> x.geId()).collect(Collectors.toList());
    // orElse(null)有什么用,找不到时有和没有orElse会不会抛出异常?findFirst()返回Optional<T>,加orElse会返回T。
    var firstOne = students.stream().filter(x -> x.getId() == 1).findFirst().orElse(null);
    
    Map<String, String> map = new HashMap<>();
    map.put("1","tom");
    for (Map.Entry<String, String> entry : map.entrySet()) {
        var val = entry.getKey() + entry.getValue();
    }
    
    // 按条件移除多个元素
    names.removeIf(t -> t.contains("foo"));
    
    // 类似C#的SelectMany
    var students = new ArrayList<Student>();
    var student1 = new Student();
    var student1ClassInfos = new ArrayList<ClassInfo>(); 
    var classInfo11 = new ClassInfo();classInfo11.setId(1);
    var classInfo12 = new ClassInfo();classInfo12.setId(2);
    student1.setClassInfos(student1ClassInfos);
    var student2 = new Student();
    var student2ClassInfos = new ArrayList<ClassInfo>(); 
    var classInfo21 = new ClassInfo();classInfo21.setId(1);
    var classInfo22 = new ClassInfo();classInfo22.setId(3);
    student2.setClassInfos(student2ClassInfos);
    students.add(student1);
    students.add(student2);
    var classIds = students
            .stream()
            .flatMap(t -> t.getClassInfos().stream().map(s -> s.geClassId()))
            .distinct()
            .collect(Collectors.toList());
    
    // 交集
    // 使用CollectionUtils.intersection
    import org.apache.commons.collections4.CollectionUtils;
    var list1 = new ArrayList<>(List.of(1,2,3));
    var list2 = new ArrayList<>(List.of(1,2,4));
    var resultCollection = CollectionUtils.intersection(list1,list2);
    
    // 使用ArrayList.retainAll,据说会改变原集合,并且全真时返回false。比如以下会改掉list1
    var success = list1.retainAll(list2);
    

    Mapping

    default自定义转换

    import org.mapstruct.Mapper;
    import org.mapstruct.factory.Mappers;
    
    @Mapper
    public interface StudentMapping {
        StudentMapping INSTANCE = Mappers.getMapper(StudentMapping.class);
    
        // 数据表字段与Dto字段名不一样的mapping处理
        @Mapping(target = "name", source = "cnName")
        StudentDto toDto(Student student);
        
        // toDtoList的实现调用了上面的toDto
        List<StudentDto> toDtoList(List<Student> students);
        List<StudentExtDto> toDtoListExt(List<Student> students);
        
        default StudentDto toDtoExt(Student student){
            return null;
        }
    }
    
    

    Lombok

    使用lombok让实体类自带getter、setter。

    在IDEA中,File >> Settings >> Plugins >> 搜索Lombok >> 安装。

    增加注解@Data

    对于boolean(小写),lombok会生成isXXX而不是getXXX的getter,见下isInSchool(),而对于大写Boolean的处理与其他类型是一样的getXXX。

    import lombok.Data;
    
    @Data
    public class Student {
        private String name;
        private boolean inSchool;
        private Boolean inSchool2;
    }
    
    var student = new Student();
    student.getName();
    student.isInSchool();
    student.setInSchool(true);
    student.getInSchool2();
    

    Lombok编译出错提示找不到符号

    所遇到的情况是lombok 和mapstruct冲突引起的。使用方法是在pom文件maven-compiler-plugin的annotationProcessorPaths中,需要把lombok配置要放在mapstruct-processor之前

    <properties>
      <lombok.version>1.18.24</lombok.version>
    </properties>
    
    <project>
      <build>
       <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
              <source>11</source>
              <target>11</target>
              <encoding>UTF-8</encoding>
              <annotationProcessorPaths>
                <!-- lombok的配置要在mapstruct-processor之前 -->
                <path>
                  <groupId>org.projectlombok</groupId>
                  <artifactId>lombok</artifactId>
                  <version>${lombok.version}</version>
                </path>
                <path>
                  <groupId>org.mapstruct</groupId>
                  <artifactId>mapstruct-processor</artifactId>
                  <version>${org.mapstruct.version}</version>
                </path>
              </annotationProcessorPaths>
            </configuration>
          </plugin>
    
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-resources-plugin</artifactId>
            <configuration>
              <propertiesEncoding>UTF-8</propertiesEncoding>
            </configuration>
          </plugin>
        </plugins>
      </build>
    </project>
    

    Mongo

    import org.bson.Document;
    import org.bson.BsonDocument;
    import com.alibaba.fastjson.JSON;
    import org.springframework.data.domain.Sort;
    import org.springframework.data.mongodb.core.query.Query;
    import org.springframework.data.mngodb.core.query.Criteria;
    import org.bson.Document;
    import org.bson.BsonDocument;
    import com.alibaba.fastjson.JSON;
    
    var query = new Query();
    var name = "tom";
    
    var classNames = new ArrayList<>();
    List<Integer> types = new ArrayList<>();
    Criteria criteria = new Criteria();
    criteria.and("_id").ne(id);
    criteria.and("Name").is("foo");
    var subCriteria = new Criteria().and("className").in(classNames);
    criteria.and("Classes").elemMatch(subCriteria);
    criteria.and("Types").in(types);
    var query2 = new Query(criteria);
    
    // 模糊查询
    query.addCriteria(Criteria.where("Name").regex("^.*" + name + ".*$"));
    // query生成的条件为{ "Name" : { "$regularExpression" : { "pattern" : "^.*tom.*$", "options" : ""}}}
    
    # or
    var orCriteria = new Criteria()
      .orOperator(Criteria.where("_id").is(1L), Criteria.where("Name").is("Foo"));
    var criteria = new Criteria()
      .and("sex").is("boy")
      .andOperator(orCriteria);
    
    # sort两个字段,skip, limit
    var query = new Query(criteria)
                    .with(Sort.by(Sort.Direction.DESC,"Name").and(Sort.by(Sort.Direction.DESC,"UpdateTime")))
                    .skip(skip)
                    .limit(limit);
    
    // 将对象转为Document、BsonDocument,需要转Bson可查看org.springframework.data.mongodb.util.BsonUtils.asBson();
    var student = new Student();
    var json = JSON.toJSONString(student);
    var document = Document.parse(json);
    var bsonDocument = Document.parse(json).toBsonDocument();
    var bsonDocument2 = BsonDocument.parse();
    
    @Document(collection = "OperationLog")
    @Data
    public class OperationLog {
        @Id
        private String id;
        
        @Field("ContentBefore")
        private Object contentBefore;  
    }
    
    var logEntity = new OperationLog();
    logEntity.setContentBefore(student);// 写入db中嵌套字段id为.ContentBefore._id
    // logEntity.setContentBefore(document);// 写入db中嵌套字段id为.ContentBefore.id
    // logEntity.setContentBefore(bsonDocument);// 同上
    // repo.insert(logEntity);
    

    HttpRequest

    RetrofitClient

    import com.github.lianjiatech.retrofit.spring.boot.annotation.Intercept;
    import com.github.lianjiatech.retrofit.spring.boot.annotation.RetrofitClient;
    
    @RetrofitClient(baseUrl = "${demo.service.url}")
    @Intercept(handler = TraceInterceptor.class)
    public interface StudentServiceClient {
        @GET("/student/queryByName")
        public Result<StudentDto> queryByName(@Query("name") String name);
    
        @POST("/student/create")
        public Result create(@Body CreateStudentRequest request);
    }
    

    WebApi

    /**
     * @GetMapping("getById")
     * @PostMapping("getById")
     * @RequestMapping同时支持Get和Post
    */
    @RequestMapping(value = "getById", method = {RequestMethod.GET,RequestMethod.POST})
    public String getById(){
      return "foo";
    }
    

    错误处理:There is already 'xxxController' bean method
    原因是controller中的@RequestMapping路径重复。

    
    

    Log

    log4j

    package com.example.utils;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    public class JsonUtil {
        private static final Logger log = LoggerFactory.getLogger(JsonUtil.class);
        
        public void test(){
            try{
            log.info("test info");
            }
            catch(Exception e){
                log.warn("error : {}", e.getMessage());
            }
        }
    }
    

    泛型Generic

    import com.alibaba.fastjson.JSON;
    
    public <T> List<T> doSome(){
        return null;
    }
    
    public <T> List<T> doSome(String str, Class<T> clazz){
        return JSON.parseArray(str, clazz);
    }
    

    Reflection

    public class Student extends BaseEntity {
        private long id;
        private String name;
    }
    var student = new Student();
    // 此方法不包含父类字段
    var fields = student.getClass().getDeclaredFields();
    // private字段需要设置accessble才可访问取值
    field[0].setAccessible(true);
    field[1].setAccessible(true);
    var id = fields[0].getLong(student);
    var name = fields[1].get(student).toString();
    
    // 获取包含父类在内的字段
    cn.hutool.core.util.ReflectUtil.getFields(student.getClass());
    

    File

    import org.springframework.util;
    
    public static String readFileAsString(String filename) throws IOException {
        var resource = new ClassPathResource(filename);
        var bytes = FileCopyUtils.copyToByteArray(resource.getInputStream());
        // copyToString(@Nullable Reader in)应该也可以,还没试过
        return new String(bytes);
    }
    

    配置

    student.properties文件:

    student.id=1
    student.name=foo
    

    配置类,@PropertySource可以指定配置文件,也可以不指定

    @Component
    @ConfigurationProperties(prefix = "student")
    @PropertySource(value = "file:/mnt/demo/config/student.properties", ignoreResourceNotFound = true)
    public class Student {
        private Long id;
        private String name;
    }
    

    应用

    导入excel

    EasyExcel

    import org.springframework.web.multipart.MultipartFile;
    import com.alibaba.excel.EasyExcel;
    import com.alibaba.excel.context.AnalysisContext;
    import com.alibaba.excel.event.AnalysisEventListener;
    
    @ApiOperation("导入student")
    @PostMapping("uploadStudents")
    @FileType({"xlsx", "xls"})
    public Object uploadStudents(MultipartFile file, @RequestHeader("teacherId") Long teacherId) throws IOException {
        InputStream inputStream = file.getInputStream();
        byte[] bytes = inputStream.readAllBytes();
        ByteArrayInputStream stream = new ByteArrayInputStream(bytes);
        
        var listener = new AnalysisEventListener<StudentUploadData>() {
            private ArrayList<StudentUploadData> list = new ArrayList<>();
            // 按批处理,每批行数
            private int maxRow = 1000;
            @Override
            public void invoke(StudentUploadData data, AnalysisContext analysisContext) {
              list.add(data);
            }
            @Override
            public void doAfterAllAnalysed(AnalysisContext analysisContext) {          
                int count = (int) Math.ceil((double) list.size() / maxRow);
                for (int i = 0; i < count; i++) {
                    int fromIndex = i * maxRow;
                    int toIndex = fromIndex + maxRow;
                    if (toIndex > list.size()) {
                        toIndex = list.size();
                    }
                    List<T> subList = list.subList(fromIndex, toIndex);
                    // TODO:处理一批数据,比如保存
                }
                list.clear();
            }
        };
        EasyExcel.read(inputStream, StudentUploadData.class, listener).sheet(0).headRowNumber(1).doRead();
        inputStream.close();
        return null;
    }
    

    IDE工具

    IDEA运行调试

    • 编译:在右侧Maven窗口的root>Lifecycle下,选中clear+validate+compile后点击上方Run Maven Build绿色三角按钮,等待编译完毕。
    • 运行或调试:首次运行可以先找到目标host所在的ServiceInitializer,点击代码左侧的绿色三角按钮,在下列菜单中选择Run或Debug。
    • 命名运行调试配置:工具栏运行按钮左边的下拉菜单列出运行过的host,默认名字为ServiceInitializer,在下拉菜单选中Edit Configuration对各host命名以便区分多host。

    IDEA正则式替换字符串

    • 比如想将dotnet字段注释改为java注释
    // name
    private String name;
    
    /**
     * name
     */
    private String name;
    

    操作:在IDEA替换对话框(ctrl+H)中选中正则式方式(图标为.*),填写以下查找值和替换值

    查找值:
    // (.*)
    替换值:
    /**
     * $1
     */
    
    • 方法首字母大写转为小写

    jetbrains官方文档

    // 条件值:注意前面有一空格,本示例是查带左小括号的,并且选中`Cc`和`.*`(即大小写和正则)
     ([A-Z])(\w+\()
    // 替换值:注意前面有一空格,`\l``\L`转为小写,`\u``\U`转为大写。
     \l$1$2
    

    示例

    // 转换前
    public String GetName() {}
    // 转换后
    public String getName() {}
    
    • 给字段增加@Field注解,将名首字母大小后的字段名填写到注解
    查找值:
    (    private .+ )(.+);
    替换值:
        @Field("\u$2")
    $1$2;
    

    示例

    // 替换前
        private String name;
    // 替换后
        @Field("Name")
        private String name;
    

    Maven包处理

    • 清除IDEA缓存

    在打开的项目中,File菜单>Invalidate Caches/Restart...>点击Invalidate Caches And Restart。将会清除Maven缓存并重新打开项目,重新拉取Maven包。

    制作项目模板

    https://maven.apache.org/archetype/maven-archetype-plugin/

    依赖jar打包

    我有一个非bootstrap项目,打包时没有包含依赖jar包,在pom文件的build>plugins中添加下面的plugin后,在idea的maven工具中选择以下项运行打包Plugins>assembly>assembly:assembly,可以得到jar-with-dependencies的jar包,里面包含了依赖包的class文件。

      <build>
        <plugins>
          <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <configuration>
              <descriptorRefs>
                <descriptorRef>jar-with-dependencies</descriptorRef>
              </descriptorRefs>
            </configuration>
          </plugin>
        </plugins>
      </build>
    

    相关文章

      网友评论

          本文标题:java开发

          本文链接:https://www.haomeiwen.com/subject/zztrldtx.html