idea总过期,eclipse“笨重”,你有第三选项 最近我的idea又过期了,网上各种百度,不止我一个人被“杀猪”,网上一片人“惨叫”!浪迹互联网这么多年习惯白嫖,老是过期这感觉真不爽。
也不知道idea什么时候成了行业利器,我第一次使用大概是12年,当时住公司宿舍,同屋一个同事他们部门使用,于是我们合伙“搞事情”,他教我使用idea,我教他maven搭建ssm项目。第一次使用后,除了界面简洁点也没啥感觉,后面就扔掉了。再后面也有几次都是这样的经历,用来写个小项目就不用了,所以直到18、19年我才开始大规模的在生产项目中使用idea。这些年一直在一个公司混,也不知道啥时候idea就成了很多公司的必备工具。
之前一直使用eclipse-jee版本,纯净官方版本,功能强悍,足够简洁,说实话要不是很多人用idea,我真没打算换。但是网上都说eclipse“笨重”,咱也不懂,也不敢说啥,就默默告别eclipse。但是,真是受够了idea总是过期,咋办?现在我们有第三选项了,那就是面向新世纪的编辑工具vscode。vscode是微软参考github的atom(基于Electron)开发一款可开源扩展文本编辑器,功能非常强大,默认支持git,提供智能提示、调试、各种插件等等功能,已经成为了很多语言官方支持的编辑器(比如rust、go、typescript等)。好了,废话不多说,下面咱们动手搭建vscode的Java开发环境,并使用这个环境开发一个包含常用元素的demo项目。
安装 如果本机没有安装过vscode,可以直接下载安装Code Package for Java (mac ),这个安装包里面包含了vscode、jdk和一些重要的Java插件,可以开箱即用。
如果已经安装过vscode,那么大体上只需要安装一些插件就可以了(java查询的语法分析后台进程需要使用jdk11以上版本和代码的jdk版本无关)。下面是Java相关插件列表,一些是选装的。
Language Support for Java(TM) by Red Hat
Debugger for Java
Java Test Runner
Maven for Java
Project Manager for Java
大家可以直接安装Java Extension Pack这个插件,一下把所有这些插件都安装好。我本地还安装了tomcat插件,spring-boot插件等,都不是必须的。
快捷键 IDE作为高效开发的工具,方便好用的快捷键是必须的。熟悉和使用快捷键可能也是迁移IDE工具最主要的内容。这一点vscode同样非常擅长,它不光内置了大量的快捷键设置,也可以通过安装一些keymap的插件来模拟其他你习惯的IDE的快捷键,比如idea/eclipse/sublime/vim/visual studio等等。
vscode的默认快捷键设置可以参考下面的连接
常用的快捷键插件可以参考下面的连接:https://code.visualstudio.com/docs/getstarted/keybindings#_keymap-extensions
笔者自己在使用的时候,没有去安装插件来模拟其他ide,这样vscode还可以作为其他语言的ide。 我这里列几个我自己常用的快捷键:
alt + / : 智能提示(默认ctrl + space和windows的语言切换冲突)
ctrl + p : 快速定位文件/类等
ctrl + shift + p : 定位命令
ctrl + alt + f : 格式化文档
ctrl + . : 快速解决方法(quick fix)
alt + 左右箭头切换光标位置
开发spring-boot项目 现在是时候用新的IDE来搞点事情了,这里动手搭建一个包含crud的rest service,数据映射使用spring-data-jdbc,数据库使用h2内存数据库。
创建工程 首先,ctrl + shift + p打开命令窗口,输入spring,选择spring initializer: create maven project。
然后,就可以安装提示填写spring-boot版本、GAV、依赖,最后选择生成的目录,就可以搭建好一个spring-boot的项目。下面列表是选择的依赖:
spring web mvc
freemark
validation
flyway
mybatis
spring-boot-devtools
h2
mysql
spring-boot-configuration-processor
lombok
创建完成后,在弹出的提示中,选择打开项目,这时我们应该能够新生成的maven项目目录结构、启动类、测试类等都在.为基础目录的包中。
最后,咱们再把项目初始化为一个git项目,追溯文件的变化。
1 2 3 git init git add * git commit -m 'init project'
集成测试 项目已经初始化完成,现在咱们开始集成一些开发中常用的组件,并完成一个简单的crud。
目录结构 首先,这里先描述一下项目的目标目录结构,如下图所示:
.
├── ApplicationContextHolder.java
├── App.java
├── ServletInitializer.java
└── modules
└── demo
├── controller
│ └── PersonController.java
├── domain
│ └── Person.java
├── mapper
│ ├── PersonMapper.java
│ └── xml
│ └── PersonMapper.xml
├── service
│ ├── IPersonService.java
│ └── impl
│ └── PersonService.java
└── vo
└── PersonQuery.java
flyway 在resources/db/migration目录中创建一个V1__demo_person.sql的数据库脚本,内容如下:
1 2 3 4 5 6 7 8 9 10 create table person( id bigint not null primary key auto_increment, name varchar (100 ) not null , age int not null , email varchar (100 ) not null , sex int not null ); insert into person (name, age, email, sex) values ('zhangsan' , 34 , 'zhangsan@jd.com' , 1 );insert into person (name, age, email, sex) values ('lisi' , 34 , 'lisi@jd.com' , 1 );insert into person (name, age, email, sex) values ('wangwu' , 34 , 'wangwu@jd.com' , 1 );
mybatis 首先,在application.properties中配置mapper xml的路径.
1 2 mybatis.mapper-locations =classpath:<groupId>/<artifactId>/**/mapper/xml/*.xml mybatis.type-aliases-package =<groupId>.<artifactId>.**.domain
其次,mapper文件我们习惯放到和mapper类相同的路径,而编译时默认是不复制xml文件的,需要配置一下pom.xml文件,build下添加如下配置.
1 2 3 4 5 6 7 8 9 10 11 <resources > <resource > <directory > src/main/java</directory > <includes > <include > **/*.xml</include > </includes > </resource > <resource > <directory > src/main/resources</directory > </resource > </resources >
示例代码 多谢spring-boot的自动配置能力,就这么简单一点东西,就可以把项目配置好了. 这里假设大家已经非常熟悉Java的基本开发,那么下面,就从controller层到数据库层,把示例的代码展示一下,具体的就不再详细解释了.
Person.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 package <groupId>.<artifactId>.modules.demo.domain;import java.io.Serializable;import java.util.Optional;import com.fasterxml.jackson.annotation.JsonIgnore;import <groupId>.<artifactId>.ApplicationContextHolder;import <groupId>.<artifactId>.modules.demo.mapper.PersonMapper;import lombok.Data;import lombok.extern.slf4j.Slf4j;@Data @Slf4j public class Person implements Serializable { private static final long serialVersionUID = 6425423112311587456L ; private Long id; private String name; private Integer age; private String email; private Integer sex; @JsonIgnore private PersonMapper mapper; public void enable () { this .mapper = ApplicationContextHolder.applicationContext.getBean(PersonMapper.class); } public Boolean save () { try { int result = 0 ; if (this .id != null ){ result = this .mapper.update(this ); }else { result = this .mapper.save(this ); } return result > 0 ; } catch (Exception e) { log.error("保存person对象异常:{}" , e.getMessage(), e); } return false ; } public Boolean del () { try { this .mapper.delete(this ); return true ; } catch (Exception e) { log.error("删除person对象异常:{}" , e.getMessage(), e); } return false ; } public Optional<Person> load () { return Optional.ofNullable(this .mapper.findById(this .id)); } }
PersonController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 package <groupId>.<artifactId>.modules.demo.controller;import java.util.Optional;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.DeleteMapping;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.PutMapping;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import <groupId>.<artifactId>.modules.demo.domain.Person;import <groupId>.<artifactId>.modules.demo.service.IPersonService;@RestController @RequestMapping("/api/v1/person") public class PersonController { @Autowired private IPersonService service; @PostMapping(value = "/") public Boolean save (@RequestBody Person person) { person.enable(); return person.save(); } @DeleteMapping(value="/{id}") public Boolean del (@PathVariable Long id) { Person p = new Person(); p.enable(); p.setId(id); return p.del(); } @PutMapping("/{id}") public Boolean update (@PathVariable Long id, @RequestBody Person person) { person.enable(); person.setId(id); return person.save(); } @GetMapping("/{id}") public Person get (@PathVariable Long id) { Person p = new Person(); p.enable(); p.setId(id); Optional<Person> result = p.load(); if (result.isPresent()){ return result.get(); } return null ; } @GetMapping("/") public Iterable<Person> find () { return service.list(); } }
IPersonService.java
1 2 3 4 5 6 7 8 9 10 11 12 package <groupId>.<artifactId>.modules.demo.service;import <groupId>.<artifactId>.modules.demo.domain.Person;import <groupId>.<artifactId>.modules.demo.vo.PersonQuery;public interface IPersonService { Iterable<Person> list () ; Iterable<Person> find (PersonQuery p) ; }
PersonService.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 package <groupId>.<artifactId>.modules.demo.service.impl;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import <groupId>.<artifactId>.modules.demo.domain.Person;import <groupId>.<artifactId>.modules.demo.mapper.PersonMapper;import <groupId>.<artifactId>.modules.demo.service.IPersonService;import <groupId>.<artifactId>.modules.demo.vo.PersonQuery;@Service public class PersonService implements IPersonService { @Autowired private PersonMapper mapper; @Override public Iterable<Person> list () { return this .mapper.findAll(); } @Override public Iterable<Person> find (PersonQuery p) { return mapper.findAll(); } }
PersonQuery.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 package <groupId>.<artifactId>.modules.demo.vo;import lombok.Data;@Data public class PersonQuery { private Long id; private String name; private Integer sex; private String email; private Integer pageNumber; private Integer pageSize; }
PersonMapper.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 package <groupId>.<artifactId>.modules.demo.mapper;import java.util.List;import org.apache.ibatis.annotations.Mapper;import <groupId>.<artifactId>.modules.demo.domain.Person;@Mapper public interface PersonMapper { int save (Person person) ; int delete (Person person) ; int update (Person person) ; Person findById (Long id) ; List<Person> findAll () ; }
Personmapper.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace ="<groupId>.<artifactId>.modules.demo.mapper.PersonMapper" > <sql id ="table-name" > PERSON</sql > <sql id ="id-column" > ID</sql > <sql id ="columns" > NAME, AGE, EMAIL, SEX </sql > <insert id ="save" parameterType ="Person" > insert into <include refid ="table-name" /> (<include refid ="columns" /> ) values (#{name}, #{age}, #{email}, #{sex}) </insert > <delete id ="delete" parameterType ="long" > delete <include refid ="table-name" /> where id=#{id} </delete > <update id ="update" parameterType ="Person" > update <include refid ="table-name" /> <set > <if test ="name != null and name != ''" > NAME=#{name}, </if > <if test ="age != null" > AGE=#{age}, </if > <if test ="email != null and email != ''" > EMAIL=#{email}, </if > <if test ="sex != null" > SEX=#{sex}, </if > </set > where id=#{id} </update > <select id ="findById" parameterType ="long" resultType ="Person" > select <include refid ="id-column" /> ,<include refid ="columns" /> from <include refid ="table-name" /> where id = #{id} </select > <select id ="findAll" resultType ="Person" > select <include refid ="id-column" /> ,<include refid ="columns" /> from <include refid ="table-name" /> </select > </mapper >
启动测试 首先,在启动类上添加@EnableWebMvc注解,启动webmvc. 然后,就可以右键启动类,启动应用了.
测试时需要使用postman,因为api定义完全参考了restful的规范,部分接口浏览器中无法模拟.
总结 代码是我一行行敲入的,总体感觉很流畅,智能提示|必要快捷键|调试|快捷输入一应俱全,使用起来和专业的Java IDE丝毫不差,真的说现在的超级编辑器果然不是吹的.
这里大篇幅描述了一个示例工程的代码,其实还有很多好用的快捷键需要一点点的探索熟悉,还有之前安装的每一个插件都有他们自己的能力,需要去了解. 当然,还有很多没有了解到的插件也是一个宝库.看到这里,你是不是想赶紧动手试试!