文章主要记录下PHP转Java开发的一些心得~
经验心得
1,Java基础知识
https://www.runoob.com/java/java-tutorial.html
菜鸟教程,先把基础知识点多过几遍;
2,Stream API
https://www.runoob.com/java/java8-streams.html
Java 8 引入的一个新特性;
函数式编程风格;
流Stream;
数据循环时,常使用他;
3,Hutool工具类库
https://www.hutool.cn
小而全的Java工具类库;
提供了大量Java常用的工具类、方法;
可以仔细看下他的文档,了解Java开发中常用的一些方法;
4,限制 / 自由,规范 / 随意
写Java代码有很多限制/规范,不能像PHP那样灵活/随意;
下面是一个PHP获取文章的示例,使用Laravel查询构建器:
public function getArticle($id)
{
$article = DB::table("article")->where($id)->first();
return jsonSuccess($article);
}
// $article = ['id' => 1000000, 'title' => '测试标题'];
这个示例在Java中,为了规范,要提前定义好数据表实体类、视图对象类、接收参数对象类(可选):
// 数据库表实体类
package com.lh1010.repository.entity;
import lombok.Data;
@Data
@TableName("aduty_article")
public class Article {
@TableId(type = IdType.AUTO)
private Long id;
private String title;
}
// 视图对象类
package com.lh1010.vo;
import lombok.Data;
@Data
public class ArticleVo {
private Long id;
private String title;
}
// 接收参数对象类
package com.lh1010.vo;
import lombok.Data;
@Data
public class ArticleParamsVo {
private long id;
private String title;
private String k;
// 分页相关
private int pageNum;
private int PageSize;
}
// 控制器
@PostMapping("/getArticle")
public Result getArticle(@RequestBody ArticleParamsVo articleParamsVo) throws Exception {
Article article = articleMapper.getArticle(articleParamsVo.getId());
ArticleVo articleVo = new ArticleVo();
BeanUtil.copyProperties(article, articleVo);
return Result.success(articleVo);
}
// Service
// TODO
5,冗长繁琐,团队协作
在中小型项目上,Java是冗长和繁琐的;
比如定义一个简单的数据类可能需要编写getter、setter、equals、hashCode等方法;
比如一个文章模块的开发,按照规范,可能就会涉及到以下多个文件:
ArticleController.java:路由、入口文件、响应
ArticleService.java:业务逻辑
ArticleMapper.java:数据库CRUD
entity/Article.java:数据库表实体类
ArticleMapper.xml:写sql的
vo/ArticleVo.java:对外输出数据结构类
vo/ArticleParamsVo.java:搜索参数实体类
vo/ArticleImportVo.java:导入数据实体类
vo/ArticleExportVo.java:导出数据实体类
PHP的MVC模式与Java Sping Boot项目架构类似。
PHP项目一般设置为3-4层:
控制器Controller -> 业务逻辑层Repository -> 视图View;
控制器Controller -> 业务逻辑层Repository -> 数据模型Model -> 视图View;
中小型企业项目还是无脑php;大团队项目可考虑Java风格;
语言差异
PHP:动态类型语言,适合快速开发和中小型项目,语法灵活,但缺乏严格的类型检查和大型项目的管理能力。
Java:静态类型语言,适合大型项目和复杂系统,具有强大的类型检查和面向对象特性,但开发速度相对较慢。
依赖管理
PHP:使用Composer进行依赖管理,composer.json文件定义依赖。
Java Spring Boot:使用Maven或Gradle进行依赖管理,pom.xml或build.gradle文件定义依赖。
路由和控制器
PHP:路由通常在框架的配置文件中定义,控制器处理请求并返回响应。
Java Spring Boot:使用@RestController和@RequestMapping注解定义路由和控制器,Spring Boot会自动处理请求和响应。
项目架构
PHP:通常使用MVC模式,项目结构相对简单。
Java Spring Boot:基于Spring框架,采用依赖注入、面向切面编程等特性,项目结构更加模块化,通常分为Controller、Service、Repository等层。
PHP MVCR
控制器 Controller
负责响应用户请求、准备数据,以及决定如何展示数据。
仓库 Repository
逻辑处理层,处理逻辑。
有些项目会选择在模型 Model 与控制器 Controller 之间加一层逻辑处理的模块,我习惯使用 R(Repository:仓库、储藏室)命名(网上也有说使用 I 命名)。
通俗点讲,就是保持了 Model 的共用性、整洁性和 Controller 的整洁性,在 Repository 中处理较为复杂的逻辑。
模型 Model
连接和操作数据库数据。
视图 View
负责渲染数据,通过 HTML 方式呈现给用户。
Java Sping Boot 架构
controller 控制器
src/main/java/com/lh1010/controller/*
路由、入口文件、响应
service 业务逻辑层
src/main/java/com/lh1010/service/*
业务逻辑层,负责处理应用程序中的业务需求。
业务逻辑处理:Service层负责封装业务逻辑,包括数据校验、数据处理、业务规则等。它接收来自Controller层的请求,执行相应的业务逻辑,并调用数据访问层(如Mapper层或DAO层)进行数据的增删改查操作。
数据传递:Service层作为Controller层和数据访问层之间的桥梁,负责数据的传递和处理。它将Controller层接收到的请求参数转换为业务逻辑处理所需的数据格式,并将处理结果返回给Controller层。
业务逻辑复用:通过封装业务逻辑,Service层实现了业务逻辑的复用。不同的Controller层可以调用同一个Service层的方法来处理相似的业务逻辑,提高了代码的可维护性和可重用性。
事务管理:Service层还可以处理事务管理,确保业务逻辑的正确性和完整性。在Spring Boot中,可以通过@Transactional注解在Service层的方法上声明事务,Spring框架会自动为这些方法提供事务支持。
vo 视图对象
src/main/java/com/lh1010/vo/*
视图对象、表现层对象、View Object
api表单提交字段格式验证。
数据封装:将后端处理的数据按照前端展示的需求进行封装,隐藏后端数据结构的复杂性。
数据安全:通过只包含前端需要的数据,可以避免不必要的数据泄露,提升数据安全性。
解耦:有助于前端和后端代码的解耦,前端只需关心VO层提供的数据结构,而后端可以自由地改变数据模型或处理逻辑,而不会影响到前端的展示。
entity 实体类
src/main/java/com/lh1010/repository/entity/*
与数据库表相对应的Java类。
与数据库交互时的数据模型。
Entity类通常是POJO的一个子集。所有的Entity类都可以被视为POJO,但并非所有的POJO都是Entity类。
mapper 数据访问层
src/main/java/com/lh1010/repository/mapper/*
数据库CRUD
解耦:Mapper层将业务逻辑与数据访问逻辑分离,提高了代码的模块化程度和可维护性。
简化数据库操作:通过定义接口和简单的XML文件或注解,开发者可以轻松地实现对数据库的操作,而无需编写复杂的SQL语句或JDBC代码。
提高开发效率:使用Mapper层可以显著提高开发效率,因为开发者可以专注于业务逻辑的实现,而不是数据库层面的细节。
sql
src/main/resources/sql/*
SQL语句
数据类型
PHP:弱类型(动态类型)语言,变量的数据类型不需要显式声明,PHP 会根据上下文自动推断数据类型。
Java:强类型(静态类型)语言,变量的数据类型必须显式声明,且类型在编译时检查。Java 的数据类型分为两大类:原始数据类型和引用数据类型。
PHP万能$可包容任意类型,技术人员不用过于关心数据类型,专心处理业务逻辑即可。
$array = [1, 2, 3, 4];
$array = ["张三", '李四', '王五'];
$array = [
["张三", '李四', '王五'],
["张三100", '李四101', '王五101'],
["张三102", '李四102', '王五102'],
];
$array = [
'key' => ["张三", '李四', '王五'],
'key100' => ["张三100", '李四101', '王五101'],
'key101' => ["张三102", '李四102', '王五102'],
];
在Java中,每一个变量、方法、类都需要定义他的类型。
String a = "123";
Integer a = 123;
public String demoFun() {
return "123";
}
public Result getList() {
return Result.success(appService.getList());
}
常用类型
List
// List
List<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
System.out.println(list.get(0)); // 输出: Apple
Map
// Map
Map<String, Integer> map = new HashMap<>();
map.put("Apple", 52);
map.put("Banana", 89);
System.out.println(map.get("Apple")); // 输出: 52
Set
// Set
Set<String> set = new HashSet<>();
set.add("Apple");
set.add("Banana");
set.add("Apple"); // 重复添加不会有任何效果
System.out.println(set.size()); // 输出: 2
聚合使用
// List<Map<String, String>>
List<Map<String, String>> testList = new ArrayList<>();
Map<String, String> map1 = new HashMap<>();
map1.put("姓名", "张三");
map1.put("年龄", "25");
Map<String, String> map2 = new HashMap<>();
map2.put("姓名", "李四");
map2.put("年龄", "30");
// 将内层Map添加到外层List中
testList.add(map1);
testList.add(map2);
// List<Map<String, Object>>
List<Map<String, Object>> listTemp = new ArrayList<>();
for (ArticleVo article : articleList) {
Map<String, Object> mapTemp = new HashMap<>();
mapTemp.put("站点", article.getSite());
mapTemp.put("展示码", article.getSellerSku());
mapTemp.put("售价", article.getArice());
listTemp.add(mapTemp);
}
// 嵌套对象 实体
List<articleExportVo> exportVos = new ArrayList<>();
exportVos.add(exportVo);
操作数据库
PHP:常用PDO或ORM(如Eloquent)进行数据库操作。
Spring Boot:使用Spring Data JPA或MyBatis进行数据库操作,JPA提供了强大的ORM功能,简化了数据库操作。
Stream API
https://www.runoob.com/java/java8-streams.html
函数式编程风格;
流Stream;
Java 8 引入的一个新特性;
List<String> fruits = Arrays.asList("香蕉", "猕猴桃", "草莓");
// 使用 Stream
List<String> longFruits = fruits.stream()
.filter(fruit -> fruit.length() > 2) // 筛选条件:长度大于2
.collect(Collectors.toList()); // 收集结果到新的列表
// 使用传统方式
List<String> longFruits = new ArrayList<>();
for (String fruit : fruits) {
if (fruit.length() > 2) { // 假设我们检查长度大于2
longFruits.add(fruit);
}
}