Spring Framework

所有的Java云平台都能够使用基于JAR的打包方式,WAR文件只在一些云平台上能够运行。

Pom.xml 更换 Maven 源

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>org.springframework.quoters</groupId>
<artifactId>quoters-incorporated</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

<name>quoters-incorporated</name>
<description>REST service to support the guides</description>

<developers>
<developer>
<id>gturnquist</id>
<name>Greg Turnquist</name>
<email>gturnquist at vmware.com</email>
<organization>VMware, Inc.</organization>
<roles>
<role>Project Lead</role>
</roles>
</developer>
</developers>

<organization>
<name>VMware, Inc.</name>
<url>https://spring.io</url>
</organization>

<licenses>
<license>
<name>Apache License, Version 2.0</name>
<url>https://www.apache.org/licenses/LICENSE-2.0</url>
<comments>
Copyright 2011 the original author or authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied.
See the License for the specific language governing permissions and
limitations under the License.
</comments>
</license>
</licenses>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<!-- 配置阿里云仓库 -->
<repositories>
<repository>
<id>aliyun-repos</id>
<url>https://maven.aliyun.com/repository/public</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>aliyun-repos</id>
<url>https://maven.aliyun.com/repository/public</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>

Tight Coupling 紧耦合

在Spring框架以前,使用排序算法需要将算法实例化

public class ComplexBusinessService {
SortAlgorithm sortAlgorithm = new BubbleSortAlgorithm;
}
public class BubbleSortAlgorithm implements SortAlgorithm {...}

Good code has loose coupling.

移除依赖项的实例化可以移除紧耦合

public class ComplexBusinessService {
SortAlgorithm sortAlgorithm; // = new BubbleSortAlgorithm();

public ComplexBusinessService(SortAlgorithm sortAlgorithm) { // 创建构造函数
this.sortAlgorithm = sortAlgorithm;
}

public classBubbleSortAlgorithm implements SortAlgorithm {...}

Spring Framework instantiates objects and populates the dependencies.

@Component

@Component // 告诉Spring管理这两个类的实例
public class ComplexBusinessService {

@Autowired // 告诉Spring这是依赖项
SortAlgorithm sortAlgorithm;
}
@Component
public class BubbleSortAlgorithm implements SortAlgorithm {...}
// Spring的工作:
SortAlgorithm sortAlgorithm = new BubbleSortAlgorithm();
ComplexBusinessService businessService =
new ComplexBusinessService(sortAlgorithm);

Dependency Injection

Spring理解你放在类顶部的不同注释,它确保它管理的所有对象的实例都是使用正确填充的依赖项创建的。

术语

  • Beans:Spring管理的不同对象
  • Autowiring:Spring识别依赖关系、它的匹配项并填充的过程。
  • Dependency Injection:将算法作为依赖项注入到复杂业务中。
  • Inversion Of Control:从需要依赖关系的类中获取Control,并将框架控制权交给Spring
  • IOC Container
  • Application Context:创建和管理所有Bean的上下文。典型的IOC容器。

Beans

  • What are the beans? @Component
  • What are the dependencies of a bean? @Autowired
  • Where to search for beans? SpringApplication
    Features:
  • Singleton: One instance per Spring Context
  • Prototype: New bean whenever requested @Scope("prototype")/ @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
  • request: One bean per HTTP request
  • session: One bean per HTTP session

@Primary

If you have two components on the class path of the same type then use @Primary.

// It also decides which Algo to use.
private SortAlgorithm bubbleSortAlgorithm;
// However, if quickSortAlgorithm is marked as @Primary, then @Primary has higher priority.

@Qualifier

Use @Qualifier(“name”) to name and choose the algo you want to use.

However, use name is much clearer than use @Qualifier. @Qualifier is more likely a rename tool.

Constructor/Setter Injection

All mandatory(necessary) dependencies should be autowired using Constructor Injection. Other(Optional) was recommended to use Setter Injection.

Modularity of Spring

One of the important things about Spring is that it’s not one big framework. Spring is built in a very modular way. It enables you to use specific models.

Why Spring popular

  1. With porperly usage of Dependency Injection, we are able to write test unit easily.
  2. No plumbing(not core) code. 在内部写好了许多Exceptions,使用Spring的程序员几乎不需要自己写Exception Handling。
  3. Modularity.(Flexible to other framework)
  4. Stay up with the trends. like Spring Cloud.

Eclipse Skill

<Ctrl+Space> Auto Completion
<Ctrl+1> File Operation
<C-S-L> List Shortcuts
<C-S-R> Resource Finding
<C-S-T> Type Finding
F3 Goto Declaration
F4 Type Hierarchy
<A-S-S> Code Generation

Maven

Convention over Configuration
mvn compile: Compile source files
mvn test compilemvn clean: Delete target directorymvn test: Run unit testsmvn package: Create a jarmvn help:effective-pommvn dependency:tree`

Gradle

Cross-platform: C/C++, JavaScript, Python…
Completely Programmable
Deliver Faster(Cache)

DAO: Data Accessed Object

Servlet

A very simple Java class which can take request in, and can take respond back with a response.

  1. extends javax.servlet.http.HttpServlet
  2. @WebServlet(urlPatterns = “/login.do”)
  3. doGet(HttpServletRequest request, HttpServletResponse response) throws IOException

实践

@WebServlet(urlPatterns = "/login.do")
public class LoginServlet extends HttpServlet {
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
request.getRequestDispatcher("/webapp/your/path/to/login.jsp").forward(request, response);

}
}
<!-- /pom.xml -->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.in28minutes</groupId>
<artifactId>in28Minutes-first-webapp</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>

<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<version>6.0</version>
<scope>provided</scope>
</dependency>
</dependencies>

<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<verbose>true</verbose>
<source>1.8</source>
<target>1.8</target>
<showWarnings>true</showWarnings>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<path>/</path>
<contextReloadable>true</contextReloadable>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

<!-- webapp/WEB-INF/web.xml -->
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">

<display-name>To do List</display-name>

<welcome-file-list>
<welcome-file>login.do</welcome-file> <!-- 首页默认后缀名 -->
</welcome-file-list>

</web-app>

# 启动服务
mvn tomcat7:run

Passing Parameters

http://your.site?parameter=value&param2=value
String param = request.getParameter("parameter");
request.setAttribute("parameter", param);
<body>
Hello, ${param}! <!-- Expression Language -->
</body>

Scriptlet: Java Code in JSP

<body>

<%
java.util.Date date = new java.util.Date();
%>
<div>Current date is <%=date%></div>

</body>

JSP is a view. It should only show Information. There shouldn’t have any business logic.

Disadvantage of GET

Any router can see the URL. Never use GET to pass your password. It’s unsecure and it is the reason why there is POST.

POST

<form action="/login.do" method="post">
  Enter your name
<input type="text" name="name" />
<input type="submit" value="Login" />
</form>
public class LoginServlet extends HttpServlet {

private UserValidationService service = new UserValidationService();

protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
String name = request.getParameter("name");
String password = request.getParameter("password");

boolean isUserValid = service.isUserValid(name, password);

if (isUserValid) {
request.setAttribute("name", name);
request.setAttribute("password", password);
request.getRequestDispatcher("/WEB-INF/views/welcome.jsp").forward(request, response);  
} else {
request.setAttribute("errMsg", "Invalid Credentials!");
request.getRequestDispatcher("WEB-INF/views/login.jsp").forward(request, response);
}
}
}

public class UserValidationService {

public boolean isUserValid(String user, String password) {
if (user.equals("account") && password.equals("password"))
return true;
return false;
}
}

Spring MVC

<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.2.2.RELEASE</version>
</dependency>

Controller

@Controller
public class LoginController {
@RequestMapping(value = "/login")
@ResponseBody
public String sayHello() {
return "Hello World!";
}
}

Model

@RequestMapping(value = "/login", method = RequestMethod.POST) // Only handle POST
public String handleLoginRequest(@RequestParam String name,
@RequestParam String password, ModelMap model) {
model.put("name", name);
model.put("password", password); // request.setAttribute("password", password);
return "welcome";
}