后端开发入门1

学习路线来自Handy前辈的规划
技术栈暂定为SpringBoot+MySql。一段话前面加的星号*表示这段话是我个人的理解。

一、理论知识

1. 复习Java基础知识。

略。
(接口interface,多线程,TCP编程,Daemon,Thread/Runnable,异常处理,注解annotation)

2. 理解前后端分离开发和不分离开发的区别。

前置知识:

脚本、脚本语言

脚本是为了重复一个设定好的规程。与编译型语言不同,脚本语言通常是解释型的,因此便于根据需求修改。在前端开发中,脚本语言一般是JS(JavaScript)。——知乎:如何用通俗易懂的语言解释脚本(script)是什么?
按我的理解,脚本就是小型的(至少最初是小型的?)、直接解释执行所以易修改的程序。

JSP

Jakarta Server Pages/JavaServer Pages的缩写。部署在服务器上,响应客户端的请求,并根据请求动态生成Web网页。以Java作为脚本语言,为HTTP请求提供服务,并能与服务器上其他Java程序共同处理业务需求。——维基百科 - JSP

JSP实际上是把Java代码嵌入HTML代码中。例如:

<html>
<head>
    <title>Hello World - JSP</title>
</head>
<body>
    <%-- JSP Comment --%>
    <h1>Hello World!</h1>
    <p>
    <%
         out.println("Your IP address is ");
    %>
    <span style="color:red">
        <%= request.getRemoteAddr() %>
    </span>
    </p>
</body>
</html>

在.jsp文件中,<%%>之间的代码是它与HTML最根本的区别。这些代码有三种:

  • <%----%>之间是注释。
  • <%=%>之间是一个变量,这个语句直接输出一个变量的值。
  • 其他情况就是普通的Java语句。这也是Java成为JSP的脚本语言的原因。

传统Java Web开发中,前端程序员完成HTML代码,后端程序员将其转为JSP再进行开发。如果后端遇到bug等问题,则难以与前端交流,因为前端看不懂后端用的JSP,而后端看不懂前端用的HTML;而且前端无法独自调试,因为页面的上线需要由后端程序员完成。
如果前端只负责数据展示和用户交互,后端只负责处理数据,前后端程序员约定好他们唯一的交流——接口的文档(参数、数据类型),然后独立并行开发,就能实现前后端解耦合,避免上述问题。——还搞不明白前后端分离?

*按我的理解,这与封装类似。两端都只需要处理接口处来的数据,而不需要管对方的细节,正如同调用封装好的函数不需要知道它的实现方式一样。当然,正如同有时候需要了解封装函数的内部细节一样,前后端可能也需要了解对方。

3. 理解JSON在前后端分离开发中的作用。

JSON

JavaScript Object Notation的缩写,即JavaScript对象表示法,用来传输由属性值或序列性的值组成的数据对象。虽然是JS的子集,但是是独立于语言的文本格式,即数据格式与语言无关。——维基百科 - JSON
JSON的文法:——json.org

*按我的理解,JSON是前后端交互的数据的形式,如同调用封装函数时的参数和返回值一样。对一端而言,另一端看起来只是大量JSON的流。

*由于JSON是语言无关的,并且现代编程语言基本都能支持array/vector/list/sequence等等与JSON中的array类似的数据形式之一,所以JSON很适合作为不同程序之间交互数据的形式。

4. 理解Tomcat/SpringMVC/Spring/SpringBoot/Servlet的关系。

Servlet

本质上,Servlet最狭义、最原始的意思是用Java语言实现的一个接口;广义地,Servlet指实现了这个接口的类。
——维基百科 - Java Servlet
既然是接口,它实际上就是一种规范,使得实现它的类都遵循这种规范。
——进击的算法
除了Servlet之外,还有ServletContext, ServletRequest, ServletResponse等诸多接口提供规范。
——简书 - servlet/tomcat等容器/springMVC之间的关系
既然是类,它也是可以运行在机器(服务器)上的程序。
——Introduction to Servlets and Servlet Containers

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package javax.servlet;
//在最新的Servlet API版本(Jakarta Servlet 5.0.0 M1)里,
//这个包被移动到了jakarta.servlet。

import java.io.IOException;

public interface Servlet {
    void init(ServletConfig var1) throws ServletException;

    ServletConfig getServletConfig();

    void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;

    String getServletInfo();

    void destroy();
}

功能上,servlet是一个组件。它的功能很简单:接收请求,处理请求,发回响应。理论上,servlet可以通过任何客户端-服务器协议来对话,但最常处理的请求是HTTP协议的,所以servlet一词常常是对HTTP servlet的简称。
Servlet常被用来给一个web服务器添加动态内容,这些内容通常是HTML,但有时也可能是XML或者JSON。当输出HTML时,servlet的语句常常是这样:

PrintWriter pw = resp.getWriter();
pw.write("<html>");
pw.write("<body>");
pw.write("<h1>Welcome, " + name + "!</h1>");
pw.write("</body>");
pw.write("</html>");
pw.flush();

所以我们说,servlet把HTML语句嵌入Java代码中。
这和JSP正好相反。那么servlet和JSP之间是否有某种关系?
有。
JSP需要先编译成Java程序才能执行。比如上面举例JSP时的代码会被Tomcat编译为下面的样子:

package org.apache.jsp;
import ...

public final class hello_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent,
               org.apache.jasper.runtime.JspSourceImports {

    ...

    public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
        throws java.io.IOException, javax.servlet.ServletException {
        ...
        out.write("<html>\n");
        out.write("<head>\n");
        out.write("    <title>Hello World - JSP</title>\n");
        out.write("</head>\n");
        out.write("<body>\n");
        ...
    }
    ...
}

这实际上就是servlet。

Servlet处理来自客户端的请求,但并不直接与客户端互动。相反地,它(们)由容器管理,通过容器和web服务器进而和客户端互动。

容器

是一个组件和更底层的支持这个组件的功能之间的接口。——Java EE Containers
书中代言:

[A CONTAINER provides] an execution environment that is responsible for adding the technical concerns to the COMPONENTS…Conceptually, it wraps the COMPONENTS, thus giving clients the illusion of of tightly-integrated functional and technical concerns.
——Server Component Patterns by M.Volter, et al.

意思大概是说:容器把一些部件给包起来,为这些部件提供运行环境,对外提供一种功能和技术高度整合的假象。

Servlet容器是Java EE服务器中很常见的一种容器。它的内部运行着servlet,外部与web服务器对接。
——StackOverflow - Definition of a Java Container
*容器像是房间,而servlet是房间中的职员。


——Java EE Containers

Servlet处理HTTP请求时的一个典型的事件序列如下:

  1. 客户端(例如一个web浏览器)访问web服务器,发出一个HTTP请求。
  2. web服务器收到请求,交给servlet容器。此处的容器可以和主机web服务器运行在同一个进程中,或者同一个主机上的不同进程中,或者不同主机上。
  3. 根据servlets的具体配置,servlet容器决定要调用哪个servlet,然后用代表着请求和响应的对象调用它。
  4. servlet根据请求对象查明用户是谁、请求里可能送来了哪些HTTP POST参数,以及其他相关数据,然后做其他事,最后生成数据发回客户端(通过响应对象)。
  5. servlet处理完请求后,容器妥善处置servlet,然后把控制权交给主机web服务器。

上面这段翻译自官方说明Jakarta Servlet Specification。顾名思义,该网站也对一个servlet应该实现的功能做了规范。

*第4步显然隐藏了许多细节,那些细节暂时不是我能考虑的……不过显然和上面代码中定义的void service(ServletRequest var1, ServletResponse var2)有关。

待解决问题:容器使用servlet的过程;servlet的生命周期。

Tomcat

全称Apache Tomcat,是一个免费、开源的对Java Servlet, JSP, Java Expression Language和WebSocket技术的实现,也是最常用的servlet容器。

如前所述,Tomcat被用于管理servlet并为之提供接口。具体地,它代替程序员执行TCP编程、HTTP编解码等繁重的底层工作,解析客户端发起的请求,组装出HttpRequest,创建HttpRespoonse,将它们交给程序员编写的servlet处理。

需要注意的是,Tomcat代替servlet接收请求,但并不发回响应。响应是servlet自己发回的。

本来应该在此处继续了解Spring/SpringBoot/Spring MVC,但我看了一会发现,首先要知道框架是什么。

框架

框架之于应用开发,如同库之于功能实现。当大家需要砍很多树的时候,锯子(库)应运而生;当大家需要造很多桌子的时候,工厂(框架)应运而生。
框架既是一种规范,规定开发某种软件的基本组件;也是帮助程序员实现这种规范的工具,提供并实现最基础的软件架构。
但正如同桌子工厂难以制造椅子,锯子不能拧螺丝一样,String类的函数不能建立哈希表,框架使得工作的灵活性减少。
YouTube - What is the difference between frameworks and libraries?

*这个视频里还说“人调用库,框架调用人”,没太明白这句话是什么意思。

Spring

Spring framework(Spring框架)是最受欢迎的Java应用开发框架。它提供的功能中有三种是主要的:

  • 应用上下文(application context)与依赖注入(dependency injections)。这两个功能帮助程序员管理服务和对象之间的联系,在可以共享同一个实例时避免创建新的实例。
  • 数据访问(data access)。有98.7%的Java应用需要建立数据库连接,因此提供这一功能的框架能大大提高工作效率。
  • Spring MVC。更容易地开发web应用。

——YouTube - What is the Spring framework really all about?

*事实上,除了这三者之外,Spring框架还提供一些其他功能,如事务管理;除了Spring框架之外,Spring还有很多其他服务,如Spring Data/Spring Cloud/Spring Security等几十种,在官网Spring Projects上有列举。但我一时没法学这么多……姑且认为Handy前辈指的是Spring框架吧。

MVC是Java Web开发的一种模式,指的是在Web服务器上建立Model(模型层,如Java Bean)、View(视图层,如JSP)、Controller(控制器)这三个耦合度低、逻辑清晰的部分。
Spring MVC则是实现了MVC设计模式的一个Web框架,是Spring框架的一个部分。

*在组合使用Tomcat和Spring MVC之后,对于Tomcat而言,整个Spring MVC就像是一个servlet;而对于Spring MVC而言,Tomcat的意义只在于上图中的1.HTTP请求和8.HTTP响应,就像是浏览器一样,因为Tomcat创建了请求和响应各一个对象供Spring MVC来交互。

待解决问题:处理器,控制器。

Spring Boot

一个开源的基于Spring框架的微框架。
Spring框架提供了依赖注入,因而提供灵活性,但代价是开发者要给每个部件设置大量的XML配置语句。Spring Boot则相反,采用自动配置(可以手动重写),尽量减少代码长度,让开发、测试和部署更加便捷。随之而来的是开发者对程序的控制力的下降,这是Spring Boot的一个局限性。
——Stackify - What is Spring Boot?
Spring Boot中内置的web容器就是Tomcat。

*回到开始的问题。这几者的关系大概是Spring Boot>Spring>Tomcat/Spring MVC(大于表示包含),Tomcat管理Spring MVC,Spring MVC是一种/实现了servlet。

5. 理解Spring Boot,重点理解一个请求从接收到返回会经过哪些流程,以及Spring Boot的注解。

REST API

REST是Representational State Transfer的缩写,意为表现层状态转换。是基于HTTP的一种软件架构风格(而非标准)。这种风格的Web API即为REST API/RESTful API,其具有以下特点:

  • 由客户端、服务器、资源组成的客户端-服务器架构,请求通过HTTP处理。
  • 无状态通信。请求里没有客户端的信息,并且每个请求都独立。
  • 缓存。
  • 统一接口。
  • 分层系统。客户端不知道自己是否连接到了服务器,因为中间可能有很多层服务器实现缓存等机制。
  • 按需代码。服务器可以发送给客户端可执行代码,来扩展客户端的功能。

——What is a REST API?

请求处理流程

在这里插入图片描述
——Spring MVC流程图

  1. 一个Tomcat服务器运行中。
  2. 客户端发送请求到Tomcat,给出URL。
  3. 一般情况下,Tomcat根据配置文件web.xml找到URL对应的servlet或者filter,并委托其处理该请求。但在基于Spring MVC的Java应用中,所有请求都被移交给同一个servlet,即DispathcerServlet,因为它处理的URL格式是*,也就是所有URL。
  4. 在Spring MVC内部,DispatcherServlet作为前端总控制器,把不同的请求移交给不同类型的控制器处理。
    4.1. 请求首先进入DispatcherServletdoService方法。
    4.2. doService中调用doDispatch方法。
    4.3. doDispatch中,遍历所有的handlerMapping来寻找可以处理该请求的控制器(亦即处理器,handler),并移交请求。
    4.4. 具体的处理器映射由注解决定。各种控制器类都带有有参数的注解@RequestMapping以表明它处理哪些请求。例如:
@Controller
@RequestMapping("/appointments")
public class AppointmentController{
	@GetMapping
	public Map Get(){
		return appointmentBook.getAppointmentsForToday();
	}

	@PostMapping
	public String add(@Valid AppointmentForm appointment, BindingResult result){
		if(result.hasErrors()){
			return "appointments/new";
		}
		appointmentBook.addAppointment(appointment);
		return "redirect:/appointments";
	}
}

该控制器会处理任何带有"/appointments"的URI的请求,再根据请求类型调用不同的方法来处理。对于GET请求,它调用Get()方法。对于POST请求同理。

  1. 控制器处理完请求后,向servlet返回一个模型与视图(ModelAndView)。
  2. servlet将模型交给视图解析器(view resolvers,例如JSP)。
  3. 解析器渲染模型,返回视图,发送给客户端作为响应。

——How Spring MVC Framework works? How HTTP Request is processed?
——springboot请求处理流程
——Spring MVC flow with Example

关于Spring Boot的注解:

Bean

JavaBean指的是符合如下条件的类:

  • 有无参构造函数。
  • 可序列化。
  • 提供设置和获得属性值的方法,即setter和getter方法。
    根据Java白皮书,JavaBean是可重复使用的软件组件。一个bean能把许多对象封装进同一个,于是我们可以从多个地方访问到这个对象,并且还提供了便捷的维护。
    ——JavaTPoint - JavaBean
    *“把许多对象封装进同一个”这句话我是真不太懂,然而维基百科和JavaTPoint都是这么说的。我在StackOverflow上查了一下,发现有人有一样的疑问,但回答都模棱两可,只有一条解释最通的评论说这句话的重点在于“封装”而非“许多”。这就很好理解了。

Spring中的bean则泛指各种组件。

*也许是因为Spring里的组件都封装得很好吧。

IoC

即Inversion of Control,控制反转。如果没有IoC,程序的控制完全在开发者手中。这固然提供很大的自由度,但在不同对象需要使用同一个组件时,常常需要重复创建,也就是说对象的创建、配置与使用过于耦合。
反转控制后,控制权由IoC容器掌握。容器能自动地创建和配置组件,并且管理其生命周期。在有对象需要使用组件时注入,在没有对象需要使用组件时销毁。
那么自然有必要告诉容器组件之间的依赖关系。最简单的方式是在XML文件中描述。
Spring的IoC容器支持字段注入、构造方法注入、方法注入。
Spring的IoC容器具有无侵入性,即容器中的组件不需要使用和Spring有关的特定接口。

Spring Boot的注解

主要有以下几种。

核心Spring框架注解
  • @Required:类级注解。被注解的bean在配置时必须要被设置指定属性,否则抛出异常BeanInitializationException
  • @Autowired:不需要在XML中写明依赖关系,该注解就可以让Spring把被注解的组件注入此处的方法/构造方法/字段。
  • @Configuration:类级注解。被注解的类是配置类。
  • @Component:类级注解。被注解的类是一个组件(可能不清楚在哪个层)。与@ComponentScan配合使用。
  • @Repository:类级注解。被注解的类是一个持久层(Data Access Object, DAO)组件,直接访问数据库。
  • @Service:类级注解。被注解的类是一个服务层组件。
  • @Controller:类级注解。被注解的类是一个控制层组件。常被用来提供web页面,配合@RequestMapping使用。以上三种都是特别的@Component
  • @RequestMapping:类/方法级注解。用于映射web请求。
  • @ComponentScan:标注在启动容器类前面,使得启动容器自动搜索当前包及其所有子包,创建所有被注解了@Component的bean的实例,并根据@Autowired装配。
  • @Bean:方法级注解。XML中<bean>标签的替代。被注解的方法给Spring容器产生一个bean。
Spring Boot注解
  • @SpringBootApplication:启动类的注解,默认加上。相当于
@EnableAutoConfiguration
@ComponentScan
@Configuration

包含了自动配置和自动扫描。

——Spring Boot Annotations
——Spring/Spring Boot常用注解总结

6.理解Maven在Java项目中的作用与用法。

Maven:是一个软件(主要是Java程序)项目管理和自动构建工具,使用名为pom.xml的项目对象模型文件来配置。

maven一词原意为【某领域的专家,致力于向其他人传授相关知识】。该词来自犹太语meyvn,意为【专家、行家】,而这个词又来自希伯来语מבין‎ mēvīn,意为’person with understanding, teacher’
——维基百科 - Maven

Maven的首要目的是让开发者在最短时间里理解一个项目的完整状态。为实现这一目标,Maven处理以下问题:

  • 简化构建过程。虽然使用Maven并没有消除了解底层机制的需要,但Maven依然为开发者屏蔽了许多细节。
  • 提供标准化的构建系统。Maven使用项目对象模型(project object model, POM)和一系列插件来构建项目。一旦你熟悉了一个Maven项目,你就明白了所有Maven项目的构建过程。
  • 提供高质量的项目信息。Maven提供的项目信息非常有用,其中一部分来自你的POM,一部分来自你的项目源码。
  • 鼓励更好的开发实践。
    ——What is Maven

POM:是Maven的基本工作单元,是一个包含项目信息和配置细节的XML文件。在执行一个任务时,Maven在当前目录下寻找POM,读取POM,获得所需信息,然后执行任务。

POM中可以指定一些配置,比如项目依赖,可用插件,构建概要,等到。POM也可以指定项目版本、描述、开发者等信息。

Super POM是Maven的默认POM。除非特别设置,所有POM都继承自Super POM。

一个POM中最少要有以下信息:

  • project 根。
  • modelVersion 应该被设置为4.0.0。
  • groupId 当前项目的组的id。
  • artifactId 当前项目(artifact)的id。
  • version 指定组下的项目的版本。
    下面是一个例子(minimal POM):
<project>
  <modelVersion>4.0.0</modelVersion>
 
  <groupId>com.mycompany.app</groupId>
  <artifactId>my-app</artifactId>
  <version>1</version>
</project>

POM要求groupId, artifactId和version都设置好,这三个值唯一确定项目名,形式为<groupId>:<artifactId>:<version>。如上面例子中的项目名为com.mycompany.app:my-app:1
如果配置细节没有设置,则按照默认值。如打包类型,如果POM中没有指定,则使用默认值jar
POM中还包括如下元素:依赖,开发者与贡献者,插件列表,插件执行,插件配置,资源。
POM能实现如下功能:

  • 项目继承。parent项可以引入一个父项目,其同样需要上述三元组指定。额外的,可以用relativePath参数指定相对路径;如果项目与父项目的groupId, version相同,则可以省略不写。
  • 项目整合。module项可以引入一个模组,其参数值为模组相对当前文件夹的路径。
  • 项目依赖。dependencies项可以引入若干项目,每个以一个dependency项指定。
  • 变量。文件中任何一个单值的字段都可以被作为变量引用,如${project.groupId}等。除了project.之外,也可以pom.作为前缀。有一些特别的变量:project.basedir, project.baseUri, maven.build.timestamp, ${mavenVersion}等。
    ——Introduction to the POM

下面是一个更完整的例子:

<project>
  <!-- model version is always 4.0.0 for Maven 2.x POMs -->
  <modelVersion>4.0.0</modelVersion>
  <!-- project coordinates, i.e. a group of values which uniquely identify this project -->
  <groupId>com.mycompany.app</groupId>
  <artifactId>my-app</artifactId>
  <version>1.0</version>
  <!-- library dependencies -->
  <dependencies>
    <dependency>
      <!-- coordinates of the required library -->
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <!-- this dependency is only used for running and compiling tests -->
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

——维基百科 - Apache Maven

Maven的一个生命周期(lifecycle)包含若干阶段(phase),每个阶段包含若干目标(goal)。运行mvn <lifecycle>命令时,Maven按顺序执行给定的生命周期(不指定则为default)中的所有阶段中的所有目标。也可以指定多个生命周期。
常用的生命周期有clean, clean compile, clean test, clean package等。
每个目标由插件参数两部分按照<plugin>:<parameter>的格式组成。如阶段compile中唯一的目标compiler:compile,阶段test中的两个目标compiler:testCompile, surefile:test等。
插件也可以自定义。

*Maven可以把项目发布到本地/Maven中央仓库/GitHub Packages。第三个是最可能用于我的示例的,但我被给到的连接似乎的GithHub库而非Packages,所以似乎无法用Maven上传。

7.复习关系型数据库SQL语法,重点理解如何设计一个关系。

略。

二、搭建开发环境

  • IDE:idea。
  • 在Windows上安装MySQL。
  • MySQL连接工具:Navicat Premium。
  • 前后端调试工具:postman。
  • Git。

三、例子:简单的登录注册

SpringBoot+Mysql做登陆接口
SpringBoot+MyBatis做注册接口

*本文的参考远远不止给出了超链接的那些文章,不给链接的原因主要有两个。1. 很多文章的内容大同小异,我是综合它们做好的笔记,将它们的链接全部给出既费力又没有什么意义。2. 提供了很多参考但很分散,就在下面统一写出吧。

*实际上就一个:廖雪峰的官方网站。其中的讲述非常丰富并且易于理解,可惜时间所限,我不会的东西又太多……无法细细学习。

  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值