Java 是一种广泛使用的编程语言,有很多方面的技术专长可以涵盖。以下是一份可能的 Java 技术专长总结:
- 核心语言特性:
- 熟练掌握 Java 语言的基本语法和核心特性。
- 对面向对象编程(OOP)的概念有深入理解,包括类、对象、继承、封装和多态。
- Java 标准库:
- 熟悉并能有效使用 Java 标准库中的核心类和接口。
- 对集合框架、I/O 操作、多线程编程等有深入了解。
- Java EE(Enterprise Edition):
- 了解 Java 企业级开发,包括 Servlet、JSP、EJB 等技术。
- 熟悉 Java EE 容器(如 Tomcat、WildFly)的使用。
- Spring 框架:
- 精通 Spring 框架,包括 Spring Core、Spring MVC 和 Spring Boot。
- 能够使用依赖注入(DI)和面向切面编程(AOP)进行企业级应用开发。
- 持久层框架:
- 对 Hibernate 或 MyBatis 等持久层框架有经验。
- 熟悉数据库设计和 SQL 查询优化。
- RESTful Web Services:
- 熟练设计和开发基于 REST 架构的 Web 服务。
- 使用 JAX-RS 或 Spring MVC 等实现 RESTful 服务。
- 前端开发:
- 了解 JavaScript、HTML 和 CSS。
- 使用前端框架(如 Angular、React 或 Vue.js)与后端集成。
- 消息队列和异步编程:
- 使用消息队列(如 RabbitMQ 或 Apache Kafka)实现异步通信。
- 熟悉 Java 的多线程编程和并发控制。
- 微服务架构:
- 了解微服务架构的概念和实践。
- 使用 Spring Cloud 或类似的框架构建和管理微服务。
- 测试:
- 熟悉单元测试和集成测试。
- 使用 JUnit 或 TestNG 进行测试驱动开发。
- 构建和部署:
- 使用 Maven 或 Gradle 进行项目构建。
- 配置和管理持续集成和持续部署(CI/CD)流水线。
- 安全性:
- 理解常见的安全问题,如跨站脚本(XSS)、跨站请求伪造(CSRF)等。
- 使用框架和最佳实践确保应用程序的安全性。
- 监控和日志:
- 配置和使用监控工具,如 Prometheus、Grafana。
- 实施有效的日志记录和异常处理。
- 容器化和云计算:
- 使用 Docker 容器化应用程序。
- 在云平台(如 AWS、Azure、Google Cloud)上部署和管理应用程序。
- 性能调优:
- 了解 JVM 的工作原理,进行性能调优。
- 使用性能分析工具,如 VisualVM 或 YourKit。
在saveArticle方法的代码中,返回代码是这样的:
if (archive == null) {
return ResponseEntity.badRequest().build();
}
else {
URI uri = ServletUriComponentsBuilder.fromCurrentRequest()
.path("/{id}")
.buildAndExpand(archive.getTitle())
.toUri();
return ResponseEntity.created(uri)
.body(archive);
}
也就是正常时候回返回一个json的文章数据。出错的时候会返回badRequest().build()出来的东西。到了客户端后,其实浏览器就直接跑到ajax的error方法中去了。在error中处理出错的信息,都只有网络信息看的到。无法精确表达我们真正的出错信息。
所以,这里第一步就是改造和统一服务器Api的返回信息。
工程Model目录下,建立新的java类文件,全名ResponseMessage.java。全部代码如下:
package DefaultMain.Model;
public class ResponseMessage {
private int code;
private String message;
private Object data;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
这个是网络api比较通用的手法,一个code,表示返回码,通常成功会给一个值,其他的值可能就是各种出错信息码。一个message,表示对应的返回信息。一个data,是事实上的数据,客户端需要根据不同的api才知道具体对应的是什么。
在我们的教程中,code这个值是0的时候表示成功,先预留。其他的看情况再说,即使是真的项目,也是慢慢添加,没有人事先知道有多少码要添加。
有了这个基础,后面就是改造文章编辑的后台和前台。不过文章的数据结构是第一个要改造的。因为原先并没有已发布的标识。
改造Article类
仅仅是加入一个boolean类型的变量:published。再加上它对应的getter和setter,最后代码如下:
package DefaultMain.Model;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.DBRef;
import javax.validation.constraints.NotBlank;
import java.util.List;
public class Article {
@Id
private String id;
@NotBlank(message = "title cannot be empty")
private String title;
@NotBlank(message = "content cannot be empty")
private String content;
@DBRef
private Catalog catalog;
@DBRef
private List<Tag> tagList;
private boolean published;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Catalog getCatalog() {
return catalog;
}
public void setCatalog(Catalog catalog) {
this.catalog = catalog;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public List<Tag> getTagList() {
return tagList;
}
public void setTagList(List<Tag> tagList) {
this.tagList = tagList;
}
public boolean isPublished() {
return published;
}
public void setPublished(boolean published) {
this.published = published;
}
}
改造ArticleApi类
保存和即将实现的发布仅仅是写入数据的时候,差了一个字段的值。这样似乎只要拷贝原来的saveArticle方法稍微改下就能做出发布的方法。既然是拷贝都出来了,马上就想到这个必须用一个方法复用,所以,写一个方法在该类中:
private ResponseEntity<?> writeArticle(Article article) {
Article archive;
for (int i = 0; i < article.getTagList().size(); ++i) {
String name = article.getTagList().get(i).getName();
if (tagService.exists(name)) {
//已经存在的tag,通过得到id绑定
List<Tag> tags = tagService.findByName(name);
article.getTagList().get(i).setId(tags.get(0).getId());
}
else {
//还不存在的tag,需要先创建一个,然后再绑定
Tag t = new Tag();
t.setId(null);
t.setName(name);
t.setCreateTime(Utility.getNowTime());
t = tagService.create(t);
article.getTagList().get(i).setId(t.getId());
}
}
if (article.getId().isEmpty()) {
//MongoRepository的API决定了,只有id是null的时候,才会返回给数据库的id给我们
article.setId(null);
archive = articleService.create(article);
}
else {
archive = articleService.update(article);
}
ResponseMessage message = new ResponseMessage();
if (archive == null) {
message.setCode(-1);
message.setMessage("create or update article error.");
}
else {
message.setCode(0);
message.setMessage("success");
message.setData(archive);
}
URI uri = ServletUriComponentsBuilder.fromCurrentRequest().build().toUri();
return ResponseEntity.created(uri).body(message);
}
这个方法不带注解,是给类的其他方法用的私有方法。代码细节基本跟原来的saveArticle方法相同,除了返回的时候用上了刚写的统一返回。
有了该方法,就可以把saveArticle方法改成如下:
@PostMapping("/api/savearticle")
public ResponseEntity<?> saveArticle(@Valid @RequestBody Article article) {
article.setPublished(false);
return writeArticle(article);
}
然后,我们再在该类里面添加一个api方法用于发布:
@PostMapping("/api/publishrticle")
public ResponseEntity<?> publishArticle(@Valid @RequestBody Article article) {
article.setPublished(true);
return writeArticle(article);
}
好了。后台代码就修改完成。不过还测试不了,因为前端代码没有发布功能,而且因为我们对返回值的结构改动,原来的功能也会出错,得改!
newarticle.js
因为后台的返回数据结构导致的改动,现在只有saveArticle()方法,而且集中在netPostJson方法的两个回调上,所以我这里只贴出netPostJson的整体:
netPostJson(url, data, function(data) {
if (data.code === 0) {
Toast.fire({
type: 'success',
title: '保存成功'
});
if (id == "") {
$('#article-id').attr('value', data.data.id);
}
}
else {
Toast.fire({
type: 'error',
title: data.message
});
}
}, function(xhr) {
Toast.fire({
type: 'error',
title: "Ajax 发生错误: " + xhr.responseText
});
});
相比较原来,现在会先查看返回值中的code,只有0的时候表示是真的成功。否则,则会显示出服务器返回的错误的信息。
最后就是真正的向后台发起发布请求。也是因为只有一个属性不同,其他功能都相同。所以只要改造一下原来的saveArticle方法,给一个参数,指定是“保存”还是“发布”即可。不多细节上的东西不能少:比如后台数据返回后的提示,还有调用的是不同的api。
最后的saveArticle方法是这样:
function saveArticle(onlySave) {
var title = $('#article-title').val();
var catalog = $("#catlog-selection").val();
var content = window.editor.getData();
var id = $('#article-id').attr('value').trim();
var tagList = $('#tags-container').find('.token-autocomplete-token');
if (title == null || title.trim() == '') {
console.log("题目不能是空的");
return;
}
if (catalog == null || catalog.trim() == '') {
console.log("分类不能是空的");
return;
}
if (content == null || content.trim == '') {
console.log("内容不能是空的");
return;
}
if (tagList.length == 0) {
console.log("标签不能是空的");
return;
}
var tags = [];
for (var i = 0; i < tagList.length; ++i) {
var tag = {};
tag.name = tagList[i].getAttribute('data-text');
tags.push(tag);
}
var data = {'title': title, 'content': content, 'catalog': { 'id': catalog }, 'tagList': tags, 'id': id};
var url = document.location.origin;
if (onlySave) {
url += '/api/savearticle';
}
else {
url += '/api/publisharticle';
}
netPostJson(url, data, function(data) {
if (data.code === 0) {
Toast.fire({
type: 'success',
title: '成功'
});
if (id == "") {
$('#article-id').attr('value', data.data.id);
}
}
else {
Toast.fire({
type: 'error',
title: data.message
});
}
}, function(xhr) {
Toast.fire({
type: 'error',
title: "Ajax 发生错误: " + xhr.responseText
});
});
}
还差不一步,调用该方法的地方得相应改动!
改动newArticle.ftl
找到“保存”这样的字眼的行,改成:
<button class="btn btn-secondary" onclick="saveArticle(true)">保存</button>
这一行紧邻的下一行,改成:
<button class="btn btn-success" onclick="saveArticle(false)">发布</button>
标签:return,title,技术,public,article,分享,data,id
From: https://blog.51cto.com/u_16483295/9029655