如何成为一个码农,这是一个问题。
一般来说,要想成为一名程序员,首先要做的第一件事就是选择。人的精力是有限的,没有多少人可以在多个方向同时取得巨大的成就。当然,大佬除外。而对于我们这些凡人老说,想要将事情做好就得确认自己的方向,这便是选择。
选择基本决定了将来的方向,比如人们常说的搞c++会秃头,搞java会减寿等等。很少有人能在决定了方向之后又重新选择另一条道路,这要求人能有足够的勇气跳出自己的舒适区去谋求未知的未来。这对于我等凡人来说实在有些困难。
所以,对于大多数人来说,选择很重要。对于那些不想要踏入java苦海的人来说,看到这里就足够了。
java是一门十分流行的语言,是这个世界上使用人数最多的程序语言之一。这让java的拓展库十分强大。而这么庞大的拓展库让java的开发变得便利,大大减少了实现一个功能的时间。但同时,也让java程序的编写变得更加的重复化和规则化。使用java来实现功能不再是挠头苦想该怎么去实现一个功能,而变成了遇到问题就上网搜为什么会报错。
于此同时,java的学习也变得不仅仅是学习java语言本身。就现在的环境而言,光是会java却对于其他拓展库一窍不通还是很难找到工作的。java的学习某种意义上已经开始和各种拓展库挂钩。
在这里,本次的项目会使用vue+springboot作为最核心的拓展库。
idea。
1.安装jdk。
步骤:https://www.runoob.com/java/java-environment-setup.html。
2.安装node。
步骤:https://www.runoob.com/nodejs/nodejs-install-setup.html。
3.安装mysql。
步骤:https://www.runoob.com/mysql/mysql-install.html。
4.安装vue-cli。
步骤:https://cli.vuejs.org/zh/guide/installation.html。
进入cmd。(windows键+r,输入cmd,回车)
通过cmd命令跳转到目标位置,即你所想要前端项目在的那个位置。
输入vue create hello-world执行。
遇到选择默认回车。创建项目完成后,idea打开该项目。
点击下方的terminal,输入npm run serve然后执行。
打开一个浏览器,地址处输入localhost:8080回车。
可以看到页面上出现了这样一个样式。值得庆贺,一切的工作已经完成了一半(然而并不是)。
idea点击file-new-project新建项目
next
将包名、项目名等按照自己的意思改一改,然后继续next
springboot集成了很多quickStart,免去了很多加依赖的功夫,在创建项目的时候就可以在这里加上。
继续next。
选择路径。finish!
后端项目创建完成。值得庆贺,vue+springboot已经创建完成了!(然而并不是)
在真正开始写代码之前,我们还有一些工作需要做。
第一个便是配置maven。
idea点击file-settings
然后在搜索框输入maven,找到maven配置页面。
虽然说idea自己集成了maven,但是这在很多时候并不适合我们的需求。比如进入了公司后不同的项目组有着不同的maven设置,甚至于连接的地址也不尽相同。
又或者说公司使用的maven版本并不是3.6.1之类的。
总而言之,让我们自己搞一个maven来用。
首先这是地址:maven
进入网站后下拉到最下,找到Maven Releases History,点击右边的archives,去下载历史版本。当然,如果想用最新版也可以直接点击下载。
点击3.6.1-binaries/-apache-maven-3.6.1-bin.zip 下载
下载完成后将压缩文件解压到适合的位置。
随后,可以进入解压缩的maven文件夹下,打开conf文件夹,再打开setting文件。(提一句,setting文件这种xml文件可以试着用notepad++打开,很方便的一款小软件。)
在
中间加上
nexus-aliyun
central
Nexus aliyun
http://maven.aliyun.com/nexus/content/groups/public
这是干啥的呢?看名字就知道,这是阿里云,很多依赖连接国外的网站下载速度会很慢,连接国内的阿里云就会快很多。
除此之外,还可以ctrl+f搜索一下localRepository。
e:/project/maven/repository
修改一下,或者已经被注释了的也可以新加一个。
这个地址按照自己的需求来修改。
那么这又是干啥的呢?
这就是maven的仓库,那些下载下来的依赖当然不会放在桌面上,这个地址便是依赖存放的位置。
maven配置改得差不多了,可以和我们的项目勾上了。
回到idea项目。
配置maven。ok~!
看起来,我们的准备已经很完善了。(然而并不是)
作为一个完整的项目,我们需要持久化的数据。我们需要一个数据库来存放我们项目的数据!
所以让我干吧。
选择mysql作为我们的数据库。
作为一名合格的码农,我们必须要学会偷懒。不会偷懒的码农是不合格的。
在遇到一个问题的第一瞬间,我们的脑海里应该想的是,有没有什么偷懒的办法。
所以理所当然的,如果让我自己去create table,insert into什么的我自然是不愿意的。有偷懒的方法我为什么不用?当然,也会有人认为自己去写sql有利于稳固知识。放心,对于真正进入工作的同学们来说,很多时候crud能写到你想吐。现在咱们就先偷偷懒吧。
nvicat,毫无疑问是个好软件。Navicat Premium也是个好软件。我们往往只需要简单的百度一下,就能够找到学习的资源。嗯,网络真是个好东西。
简而言之,打开我们的nvicat!
点击:连接-mysql
连接上后就可以在左侧栏位看到该连接。
点进去,右键新建一个数据库。
然后再紧跟着新建一张表。
我们的数据库就这么简单的搭建好了。
id可以设置为自动递增,可以省去一些功夫。
搞到现在,可能会有些人问:教练,咱们可以开始写代码了吗?
代码这种事情没必要忙。
其实某种意义上来说代码才是java里面最简单的内容。毕竟大量重复的操作会让你的代码越来越熟练,写个一年半载的之后,闭着眼睛写代码都不成问题。
然而项目的搭建,配置的修改之类的玩意。由于实际工作中使用的频率很低,反而会更容易出错。
更何况实际进入了工作之后,轮到你搭建项目的机会也不多。咱们自己搞的时候多熟悉熟悉也不是坏事。
首先,咱们搭建出来的后端项目应该是这样的:
找到application.properties
然后把它改为.yml。yml文件格式和properties文件格式有一些区别。但都不影响配置。只不过yml文件格式感觉起来更好用一些。
加上配置。
server:
port: 8088
spring:
datasource:
name: test
url: jdbc:mysql://127.0.0.1:3306/test?serverTimezone=GMT%2B8&useSSL=FALSE
username: root
password: 123456
mybatis:
mapper-locations: classpath:mapper/*.xml
server既是服务,port是端口,这项配置的意思是我们这个项目服务的端口是8088,要访问的话记得朝着端口发消息。
spring既是spring框架,datasource代表数据来源,即数据库。name不需要解释,url是访问数据库的路径。
其中jdbc:mysql://127.0.0.1:3306是访问的地址,/test是表示要访问的数据库名。即我们刚刚创建的那个数据库。?后的内容则是这个访问的配置。
mybatis配置,mapper-locations的配置是mapper的位置。
classpath相当于application.yml本身所在的路径,mapper/*.xml则表示了配置文件同级目录的mapper文件夹下以xml为文件名后缀的文件。
所以我们的mapper文件也就应该放在这个位置,直接新建一个mapper文件夹。
接下来,我们要给前端加‘依赖’了!
作为一名程序员,往往在遇到问题的第一瞬间,要想一想有没有其他人已经有了解决这个问题的方案。那么自己就不用再复杂地重复了。
当然,作为一名码农,我们肯定不会自己去费时费力地写什么button、table之类的html和css。
能用已有的为什么还要自己写?
所以说让我们引入element-ui,额,或者ant-design-vue。
不得不说的是,作为两个都很好用的前端框架,两者都是不错的选择。国内似乎element-ui的知名度要更高一些。但是个人而言,感觉ant-design-vue好像好用一点点。比如说在form组件上,ant-design有个label-col,wrapper-col可以用于调整form-item的显示比例。
只不过,ant-design-vue只支持vue3.0。现在的话,使用2.0的情况可能要多一些。
所以,咱们在这里还是先使用element-ui。
安装element-ui。
https://element.eleme.cn/#/zh-CN/component/installation
在terminal中执行npm i element-ui -S
然后在main.js中加上
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
就这么简单,element-ui的已经安装完毕。
接下来,我们继续加‘依赖’。
Axios。
Axios 是一个基于 promise 的 HTTP 库。它的作用很简单,就是和后端交流。
毕竟我们的前端项目和后端项目是两个项目,两者直接并没有直接的联系,想要将两个项目联系起来自然需要交流的方法。而http方法就是我们web开发的最合适的方法。
而axios,则是将我们的http集成为了一个可用性很高的组件。使用axios完全可以省去大量的http的操作。
在terminal中执行npm install axios。
在main.js中加上如下。
import Axios from "axios";
Vue.prototype.$axios = Axios
Axios.defaults.baseURL = '/api'
Axios的使用过程中存在着一个问题,跨域。
什么是跨域?
浏览器从一个域名的网页去请求另一个域名的资源时,域名、端口、协议任一不同,都是跨域。
而我们的前端项目和后端项目显然不可能注册在同一个端口。所以自然而然的存在着跨域。
跨域会导致什么?
1、无法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB
2、无法接触非同源网页的 DOM
3、无法向非同源地址发送 AJAX 请求(可以发送,但浏览器会拒绝接受响应)
因此,我们的axios的post请求或者get请求都会被拒绝响应。
那么,如何解决跨域问题?
实际上有很多方法,比如修改header为允许所有来源访问,允许post、get访问的方式,又或者修改请求的地址。
就比如我们现在使用的。
Axios.defaults.baseURL = '/api'
在axios请求上增加baseURL:‘/api’。
然后在前端根目录增加一个配置文件:vue.config.js。
module.exports = {
devServer: {
proxy: {
'/api': {
// 此处的写法,目的是为了 将 /api 替换成 http://localhost:8088
target: 'http://localhost:8088',
secure: false, // 如果是https接口,需要配置这个参数
// 允许跨域
changeOrigin: true,
ws: true,//是否代理websockets
pathRewrite: {
'^/api': ''
}
}
}
}
}
这样,就会在在本地会创建一个虚拟服务端,然后发送请求的数据,并同时接收请求的数据,这样服务端和服务端进行数据的交互就不会有跨域问题。
‘依赖’的配置到此基本告一段落,接下来就是快乐的代码时间了。
首先,将原有的vue代码删去。
加上data、methods。
data,在vue的api文档中说明如下:
Vue 实例的数据对象。Vue 会递归地把 data 的 property 转换为 getter/setter,从而让 data 的 property 能够响应数据变化。对象必须是纯粹的对象 (含有零个或多个的 key/value 对):浏览器 API 创建的原生对象,原型上的 property 会被忽略。大概来说,data 应该只能是数据 - 不推荐观察拥有状态行为的对象。
一旦观察过,你就无法在根数据对象上添加响应式 property。因此推荐在创建实例之前,就声明所有的根级响应式 property。
实例创建之后,可以通过vm.$data 访问原始数据对象。Vue 实例也代理了 data 对象上所有的 property,因此访问 vm.a 等价于访问 vm.$data.a。
以 _ 或 $ 开头的 property 不会被 Vue 实例代理,因为它们可能和 Vue 内置的 property、API 方法冲突。你可以使用例如 vm.$data._property 的方式访问这些 property。
当一个组件被定义,data 必须声明为返回一个初始数据对象的函数,因为组件可能被用来创建多个实例。如果 data 仍然是一个纯粹的对象,则所有的实例将共享引用同一个数据对象!通过提供 data 函数,每次创建一个新实例后,我们能够调用 data 函数,从而返回初始数据的一个全新副本数据对象。
如果需要,可以通过将 vm.$data 传入 JSON.parse(JSON.stringify(…)) 得到深拷贝的原始数据对象。
以上内容看起来或许有些复杂,但是简单来说的话,就是data里面最好就是放一些数据,data下面的数据可以直接被vue实例调用,因为它递归地给这些数据对象生成了getter和setter。
至于组件,可以看做是java里面的接口,又或者c++里的多继承,父类里面的数据就相当于组件里data声明的数据。只不过这个数据是静态数据,多个继承类里会调用到同一个数据。而要应对这一问题,就需要将data里的数据对象设定为一个函数。就好比我们所使用的data(){return{}}。这样的话每一个调用组件的实例都会调用函数生成一个新的对象,这个静态数据也就变为了非静态。
如果是java基础不好的同学,也不需要太在意这些问题,可以在之后有时间慢慢研究。(毕竟在实际工作中基本都是一样的写法。)
继续,接下来是methods。
methods就是普通的存放函数的位置,在methods中声明的methods能够通过vue实例直接访问。
也就是说,如果注册了一个组件,也就相当于声明一个类,那么可以通过这个组件的实例,或者说相当于这个类的实例,直接调用这个组件里的函数,或者说相当于类里的函数。
是不是感觉有些异曲同工之妙?实际上很多语言基本都是有着大致相同的设计思想,只要学会了一门编程语言,学起其他的语言起来也会显得事半功倍。
然后用element-ui加上一些简单的前端功能。
首先是一个form。
form是一个经常用到重要组件,很多功能都会用到form。主要是用于将数据提交。当然,这都是按照需求而言。具体使用还需要按照实际的情况而定。
在script中,也要相应的加上对应的data和method。
formData与form中绑定的对应。submitData方法则使用axios将formData中的数据传递到后端。
resetForm则将form表单中填入的数据进行清空。
formData不需要太多解释,数据都是这类的写法。
axios方法则需要解释一二。
首先,在此前main.js中,我们加上了一行代码:
Vue.prototype.$axios = Axios
这行代码的意义,将Axios赋值到vue实例的属性中,命名为$axios。
这样我们就可以在vue的实例中直接使用Axios。
submitData () {
let data = this.formData // 将data数据写入变量
this.$axios({ // 调用axios方法发动http请求
method: 'post', // 访问方式 post
url: '/user/insertBaseUser', // 访问路径
data // 访问数据
}).then(()=>{
this.formData = {} // 访问结束后清空formData中的数据
this.resetForm('form') // 清空表单数据
})
},
resetForm (formName) { // element-ui提供的清空表单方法
this.$refs[formName].resetFields();
}
除了新增数据,我们至少也应该讲数据展示出来,让我们可以看到新增数据是否成功。
所以我们加上一个table。
查询
前一个searchForm是将查询的条件捕捉起来。绑定了searchFormData,与之前的新增相似。
而table则是按照element的格式使用,绑定数据tableData。
在script方面,为searchFormData和tableData声明好数据格式:
随后加上click点击事件的响应函数,往后端发送请求。
searchData () {
let data = this.searchFormData
this.$axios({
method: 'post',
url: '/user/queryBaseUser',
data
}).then(res=>{
this.tableData = res.data
})
},
promise接受到后端传回的数据,将其赋值到tableData即可。
到此,前端已经实现了一个最基础的功能,可以去将后端的相应支持也实现了。
后端的代码编写,按照分层的格式进行编写。
首先在application文件的同层创建controller、service、dao、dto等文件夹。
这是springMVC的分层设计。具体的可以下去自己搜索了解。
这里首先在dto文件夹创建一个BaseUserDTO文件。
在这个文件中,我们要将数据库的数据结构等效搬到java这里。此外,还需要为这个类增加对应private元素增加相应的getter和setter。在这里使用lombok给省略掉了。
要使用lombok的话,就需要在pom文件中加上相应的依赖。
org.projectlombok
lombok
1.16.18
provided
接下来,在resource的mapper文件夹中创建mapper.xml:BaseUserMapper。
insert into base_user(id,name,username,password,coin)
values (#{id,jdbcType=INTEGER},
#{name,jdbcType=VARCHAR},
#{username,jdbcType=VARCHAR},
#{password,jdbcType=VARCHAR},
#{coin,jdbcType=INTEGER})
mapper中查询sql是mybatis的动态sql,根据入参的不同来改变sql的条件。这里的where 1=1 也可以替换为:
mapper.xml文件创建完毕后,在java的dao文件夹中创建dao,BaseUserMapper。与之前的xml文件同名。
@Mapper
public interface BaseUserMapper {
int insertBaseUser(BaseUserDTO baseUserDTO);
List selectUser(BaseUserDTO baseUserDTO);
}
使用@mapper注释。
随后在service文件夹下创建service接口和其实现类。
service接口:
public interface BaseUserService {
public int insertBaseUser(BaseUserDTO baseUserDTO);
public List queryBaseUser(BaseUserDTO baseUserDTO);
}
service实现类:
@Service("BaseUserService")
public class BaseUserServiceImpl implements BaseUserService {
@Autowired
private BaseUserMapper baseUserDAO;
@Override
public int insertBaseUser(BaseUserDTO baseUserDTO) {
return baseUserDAO.insertBaseUser(baseUserDTO);
}
@Override
public List queryBaseUser(BaseUserDTO baseUserDTO) {
return baseUserDAO.selectUser(baseUserDTO);
}
}
使用service注释,将service名也写入。使用autowired将dao引入使用。
随后便是在controller文件夹下创建controller文件。
@RestController
@RequestMapping("/user")
public class BaseUserController {
@Autowired
private BaseUserService baseUserService;
@RequestMapping("/insertBaseUser")
public int insertBaseUser(@RequestBody BaseUserDTO baseUserDTO) {
int i = baseUserService.insertBaseUser(baseUserDTO);
return i;
}
@RequestMapping("/queryBaseUser")
public List queryBaseUser(@RequestBody BaseUserDTO baseUserDTO) {
List baseUserDTOS = baseUserService.queryBaseUser(baseUserDTO);
return baseUserDTOS;
}
}
至此,项目实现了基本的功能。
将两个项目都启动起来试一试。
可以看到结果还是能用的,具体到真实的项目中可能会复杂一些,前端也需要优化,但总体基础都是类似的。所以到这里为止,至少我们已经掌握了一个码农所需要的一些基础知识。往后也是继续添砖加瓦便是。