idea总过期,eclipse“笨重”,你有第三选项

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;

/**
* aggregate: Person
*/
@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);
}


/**
* 保存
* @return
*/
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;
}

/**
* 删除
* @return
*/
public Boolean del() {
try{
this.mapper.delete(this);
return true;
} catch (Exception e) {
log.error("删除person对象异常:{}", e.getMessage(), e);
}
return false;
}

/**
* 通过id查询
* @return
*/
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丝毫不差,真的说现在的超级编辑器果然不是吹的.

这里大篇幅描述了一个示例工程的代码,其实还有很多好用的快捷键需要一点点的探索熟悉,还有之前安装的每一个插件都有他们自己的能力,需要去了解. 当然,还有很多没有了解到的插件也是一个宝库.看到这里,你是不是想赶紧动手试试!

,
© 2023 PLAYAROUND All Rights Reserved. 本站访客数人次 本站总访问量
Theme by hiero