快乐成长


每天进步一点点



把学习变为一种快乐,快乐长能长久,才能坚持,才能降低学习成本,带给您学习乐趣。 每天进步点点, 一直是我们的愿望,欢迎您光临!!

为了给您增加学习乐趣,并且学到有意思,简单高效的,有用的学习,为零基础的朋友们录制了趣味编程视频,欢迎您浏览,谢谢!

月度归档:2020年01月

Java清除控制台

JAVA 中如何清除console的输出

JenningLang 2016-10-26 18:34:22 15728 收藏 3
展开
首先给上答案连接,请看最多赞的答案

http://stackoverflow.com/questions/2979383/java-clear-the-console

一般的帖子里会给出这样的答案

Runtime.getRuntime().exec("cls");
1
然而 Windows 亲自测试这个命令无法运行,会报出如下错误(在Eclipse和CMD中都会这样):

Cannot run program "cls": CreateProcess error=2, 系统找不到指定的文件。
1
出错的原因是有如下两点

在标准的 Windows 安装中并没有叫 cls.exe 或者 cls.com 的可执行程序,而 Runtime.exec 命令正是因为这个原因无法被调用,可以看错误信息“系统找不到制定的文件”。我们所熟知的 cls 命令是 Windows 命令行解释器内嵌的命令(说白了就是 cmd.exe 程序中的命令,而不是 Windows 的命令)

当通过 Runtime.exec 命令进入一个进程后,其标准输出(就是 Runtime.exec 所执行命令的输出)被重定向到了一个新的管道(pipe),这个管道对于原来的 Java 进程也是可见的。但是 cls 命令的输出被重定向没有什么意义,因为 Java 进程所运行的那个窗口并不是执行 cls 命令的窗口(这一条并非出错的原因,但是下面解决办法的原理)

为了解决这一问题,我们必须先启动命令行解释器(cmd.exe)并且告诉 cmd 我们想执行一个清屏操作(/c cls)(这里的 /c 的作用我是这样理解的,实际执行了 cmd /c cls 后,我们看见的命令行已经不是原来的命令行了,而是新打开的命令行,因为这命令的意思是打开一个命令行,清屏并关闭原来的命令行),这样才能使用 cmd 内建的命令;此外,我们也必须将 cmd 的输出通道和 Java 进程的输出通道直接相连接,这个功能从 Java 7 开始被支持,其函数是 inheritIO(),具体代码如下:

import java.io.IOException;

public class CLS {
public static void main(String args[]) throws IOException, InterruptedException {
// ...
new ProcessBuilder("cmd", "/c", "cls").inheritIO().start().waitFor(); // 清屏命令
// ...
}
}

关于上面的几句命令我是这样理解的

new ProcessBuilder("cmd", "/c", "cls")
1
就是新建一个 ProcessBuilder,其要执行的命令是 cmd.exe,参数是 /c 和 cls

.inheritIO()
1
这个函数上面介绍了,就是将 ProcessBuilder 对象的输出管道和 Java 的进程进行关联,这个函数的返回值也是一个 ProcessBuilder,但是建立了关联之后的 ProcessBuilder。

.start()
1
开始执行 ProcessBuilder 中的命令

.waitFor()
1
等待 ProcessBuilder 中的命令执行完毕(我猜测可能如果不执行这个等待命令,可能会出现清屏代码后面的输出被清掉的情况,没尝试过)

这样一来当 Java 进程被直接连接到控制台,而没有被重定向,清屏功能就可以实现了。

经过实际测试,在Eclipse 的控制台输出里是不行的(从以上的原理中可以知道其原因,因为这个命令连接到的是 cmd 而不是Eclipse 的控制台),打包成 jar 包,运行 java -jar ***.jar 就可以了(不过偶尔清屏还可以,想实现刷新效果还是差了点,晃眼睛。。。)

PS:其他的还有一个方法没有测试过,代码如下

System.out.print("\033[H\033[2J");
System.out.flush();
1
2
据说这个代码在基于 UNIX 的机子上都能行,不过没试过。在 Linux 上我也没试过如下代码

Runtime.getRuntime().exec("clear");
1
但感觉上应该没问题

---------------------------------------------

java控制台的清屏

ptrlink 2008-09-04 12:25:00 14025 收藏
展开
最近写了个java的定时器程序,因为在C/C++中有system("cls")可以进行清屏,然而在java中却从来没发现过相关功能的方法,在网上搜了很久也没找到成功的解决方案,所有的方案都是带有喜剧性的,1.Runtime.getRuntime().exec("cmd /c cls");但这种是建立子线程,不能控制当前屏幕的清屏,2.就更搞笑了,System.out.println("/n /n /n /n /n /n /n /n /n /n /n /n /n /n /n /n");当然这种方法在某些情况下达到了目的,不过总觉得怪怪的,有点不尽人意3.System.out.println(" /b /b /b /b /b /b /b /b /b /b /b");这个就更搞笑了,呵呵,大家说呢;

 

所以我自己思考了一个方案:

 

要java在windows下的cmd下实现清屏,我想了个方案,就是通过JNI调用一个库文件(.dll),这个dll中包含一个实现清屏功能(system(“cls”))的导出函数。在java程序中加入代码调用这个库,即可实现当前屏幕的清屏。(--JNI的使用,以及dll的制作在百度随便搜索即可找到,这里请恕不多谈^_^--)

 

实现步骤:

1.写一个dll.h

 

#ifndef _Included_Cls
#define _Included_Cls
#ifdef __cplusplus
extern "C"
{
#endif
JNIEXPORT void JNICALL Java_Cls_clear
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif

2.再写一个dllmain.c

 

#include "jni.h"
#include "dll.h"
#include "stdlib.h"
JNIEXPORT void JNICALL Java_Cls_clear(JNIEnv *env, jobject obj)
{
system("cls");
}

 

3.用vc++建立一个dll工程(我的工程名为clsTest)

导入dllmain.c 和dll.h以及jdk下include目录下的jni.h和include/win32下的jni_md.h 共四个文件

然后build 这个dll工程,将生成的clsTest.dll放入到你的java.library.path中的其中一个目录下

查看java.libray.path用代码System.out.print(System.setProperty("java.library.path","."));

我是根据我的配置将clsTest.dll放到C:/Program Files/Java/jdk1.6.0/jre/bin下

4.测试

新建一个测试类Test.java

 

public class Test{
public native void clear();//左方的native是通知Java這個函数会使用到外部函数

static {
System.loadLibrary("clsTest"); //左方的代码代表我要载入clsTest.dll的动态链接

}

public static void main(String[] args) {
final Test a=new Test();

Runnable k=new Runnable(){
public void run(){
for(int i=0;i<20;i++){
System.out.println(i);
try {
Thread.sleep(1000);
a.clear();
} catch (Exception e) {
}

}
}
};
k.run();//执行线程
}
}
5.在cmd下 javac Test.java

java Test

即可看到运行效果^_^~

 

注:该解决方案只解决控制台程序的刷屏,且必须是系统控制台,而eclipse等其它IDE的控制台是无法用这种方式进行清屏的,如果要实现,必须使用入侵IDE的进程,因为在eclipse的内置控制台右击邮件有个clear功能,实际上就是个setText(null)事件,入侵IDE就是要在外部制造这个事件,其它IDE要也差不多。

同样,java的这种刷屏解决方案也适用于linux,不同是其链接库文件是.so,总之原理是差不多的。

-------------------

Java: Clear the console
Ask Question
Asked 9 years, 11 months ago
Active 3 days ago
Viewed 578k times

135
46
Can any body please tell me what code is used for clear screen in Java? For example in C++

system("CLS");
What code is used in Java for clear screen?

Thanks!

java console clear
shareimprove this questionfollow
edited Jun 5 '10 at 11:59

Martijn Courteaux
60.9k4141 gold badges181181 silver badges271271 bronze badges
asked Jun 5 '10 at 6:14

sadia
1,50544 gold badges1515 silver badges1717 bronze badges
1
stackoverflow.com/questions/606086/… – Vanuan Feb 2 '11 at 20:07
add a comment
11 Answers
Active
Oldest
Votes

107

Since there are several answers here showing non-working code for Windows, here is a clarification:

Runtime.getRuntime().exec("cls");
This command does not work, for two reasons:

There is no executable named cls.exe or cls.com in a standard Windows installation that could be invoked via Runtime.exec, as the well-known command cls is builtin to Windows’ command line interpreter.
When launching a new process via Runtime.exec, the standard output gets redirected to a pipe which the initiating Java process can read. But when the output of the cls command gets redirected, it doesn’t clear the console.
To solve this problem, we have to invoke the command line interpreter (cmd) and tell it to execute a command (/c cls) which allows invoking builtin commands. Further we have to directly connect its output channel to the Java process’ output channel, which works starting with Java 7, using inheritIO():

import java.io.IOException;

public class CLS {
public static void main(String... arg) throws IOException, InterruptedException {
new ProcessBuilder("cmd", "/c", "cls").inheritIO().start().waitFor();
}
}
Now when the Java process is connected to a console, i.e. has been started from a command line without output redirection, it will clear the console.

shareimprove this answerfollow
edited Mar 13 '16 at 5:03

Jeffrey Bosboom
11.3k1313 gold badges6464 silver badges8383 bronze badges
answered Oct 27 '15 at 22:40

Holger
207k2626 gold badges301301 silver badges572572 bronze badges
Why this not work for me? I running the program on windows CMD but the screen its not cleared – Alist3r Mar 22 '16 at 14:23
add a comment

82

You can use following code to clear command line console:

public static void clearScreen() {
System.out.print("\033[H\033[2J");
System.out.flush();
}
For further references visit: http://techno-terminal.blogspot.in/2014/12/clear-command-line-console-and-bold.html

shareimprove this answerfollow
edited Dec 30 '17 at 1:47

Mamun
50.3k99 gold badges2525 silver badges3939 bronze badges
answered Aug 30 '15 at 11:19

satish
1,08377 silver badges33 bronze badges
2
Care to add to this at all? What is this string and do you need to flush if autoflush is enabled? – cossacksman Nov 3 '15 at 0:24
7
They are ANSI escape codes. Specifically clear screen, followed by home. But why is 'home' necessary? – jdurston Nov 12 '15 at 20:01
1
@jdurston omitting home will not reset the cursor back to the top of the window. – Hugo Zink Sep 21 '16 at 11:35
1
Doesn't work in Eclipse, but work in Linux terminal. One vote for you – Anh Tuan Nov 7 '16 at 9:15
6
This only works if the terminal emulator in which Java runs, supports ANSI escape codes. Windows NT/XP/7/8/10 CMD doesn't – Thorbjørn Ravn Andersen Sep 17 '17 at 23:16
show 9 more comments

17

This is how I would handle it. This method will work for the Windows OS case and the Linux/Unix OS case (which means it also works for Mac OS X).

public final static void clearConsole()
{
try
{
final String os = System.getProperty("os.name");

if (os.contains("Windows"))
{
Runtime.getRuntime().exec("cls");
}
else
{
Runtime.getRuntime().exec("clear");
}
}
catch (final Exception e)
{
// Handle any exceptions.
}
}
Note that this method generally will not clear the console if you are running inside an IDE.

shareimprove this answerfollow
edited Apr 25 at 4:18

Basheer AL-MOMANI
9,82966 gold badges7272 silver badges7171 bronze badges
answered Jun 9 '13 at 23:04

Dyndrilliac
63888 silver badges1515 bronze badges
10
On Windows 8.1: java.io.IOException: Cannot run program "cls": CreateProcess error=2, The system cannot find the file specified – Ben Leggiero Oct 21 '14 at 20:30
1
@BenLeggiero That error occurs if for some reason the cls command isn't found by the JVM within some directory from the PATH environment variable. All this code does is call the Windows or Unix system command based on the default system configuration to clear the command prompt or terminal window respectively. It should be exactly the same as opening a terminal window and typing "cls" followed by the Enter key. – Dyndrilliac Oct 21 '14 at 22:34
22
There is no cls executable in Windows. It is an internal command of cmd.exe. – a_horse_with_no_name Mar 26 '15 at 13:35
7
As said by others, doesn’t work at all, not only because Windows has no cls executable, but also because the output of subprocesses gets redirected. – Holger Oct 27 '15 at 22:55
2
This answer is also a topic on meta see: meta.stackoverflow.com/questions/308950/… – Petter Friberg Oct 28 '15 at 20:35
show 3 more comments

15

If you want a more system independent way of doing this, you can use the JLine library and ConsoleReader.clearScreen(). Prudent checking of whether JLine and ANSI is supported in the current environment is probably worth doing too.

Something like the following code worked for me:

import jline.console.ConsoleReader;

public class JLineTest
{
public static void main(String... args)
throws Exception
{
ConsoleReader r = new ConsoleReader();

while (true)
{
r.println("Good morning");
r.flush();

String input = r.readLine("prompt>");

if ("clear".equals(input))
r.clearScreen();
else if ("exit".equals(input))
return;
else
System.out.println("You typed '" + input + "'.");

}
}
}
When running this, if you type 'clear' at the prompt it will clear the screen. Make sure you run it from a proper terminal/console and not in Eclipse.

shareimprove this answerfollow
answered Jan 19 '13 at 1:50

prunge
19.1k33 gold badges6565 silver badges7272 bronze badges
add a comment

14

A way to get this can be print multiple end of lines ("\n") and simulate the clear screen. At the end clear, at most in the unix shell, not removes the previous content, only moves it up and if you make scroll down can see the previous content.

Here is a sample code:

for (int i = 0; i < 50; ++i) System.out.println();
shareimprove this answerfollow
answered Nov 24 '12 at 15:23

blackløtus
79511 gold badge77 silver badges1414 bronze badges
12
A faster way to accomplish this is printing a single string of 50 \r\n with a single println, since there's a noticeable delay between println calls. – Ben Leggiero Oct 22 '14 at 20:01
7
How do you know how many lines the console is configured to display? Might work in most cases, but not all. – Cypher Oct 28 '15 at 20:47
4
The biggest difference between this and a proper clear is that in the latter, the new output will be at the top of the screen and not the bottom. – ndm13 Jul 12 '16 at 1:50
5
System.out.println(new String(new char[50]).replace("\0", "\r\n")); will do the job faster and better. – Aaron Esau Dec 30 '17 at 0:28
1
@AaronEsau starting with JDK 11, you can use System.out.println(System.lineSeparator().repeat(50)); – Holger Nov 13 '19 at 17:30
show 1 more comment

12

Create a method in your class like this: [as @Holger said here.]

public static void clrscr(){
//Clears Screen in java
try {
if (System.getProperty("os.name").contains("Windows"))
new ProcessBuilder("cmd", "/c", "cls").inheritIO().start().waitFor();
else
Runtime.getRuntime().exec("clear");
} catch (IOException | InterruptedException ex) {}
}
This works for windows at least, I have not checked for Linux so far. If anyone checks it for Linux please let me know if it works (or not).

As an alternate method is to write this code in clrscr():

for(int i = 0; i < 80*300; i++) // Default Height of cmd is 300 and Default width is 80
System.out.print("\b"); // Prints a backspace
I will not recommend you to use this method.

shareimprove this answerfollow
edited Dec 31 '17 at 4:45

Community♦
111 silver badge
answered Jul 14 '16 at 5:04

Abhishek Kashyap
1,63511 gold badge99 silver badges1818 bronze badges
add a comment

7

Try the following :

System.out.print("\033\143");
This will work fine in Linux environment

shareimprove this answerfollow
edited Oct 14 '16 at 10:48
answered Oct 14 '16 at 10:42

Bhuvanesh Waran
43599 silver badges2222 bronze badges
add a comment

6

Runtime.getRuntime().exec(cls) did NOT work on my XP laptop. This did -

for(int clear = 0; clear < 1000; clear++)
{
System.out.println("\b") ;
}
Hope this is useful

shareimprove this answerfollow
answered Jun 14 '14 at 17:35

user3648739
9311 silver badge11 bronze badge
if you could set the buffer index location to start this would be the sole easiest approach – DevilInDisguise Feb 5 '16 at 18:12
If the process was to get interrupted, I imagine you'd see lag with some print.out being removed before others. – TrevorLee Sep 3 '19 at 13:26
add a comment

2

This will work if you are doing this in Bluej or any other similar software.

System.out.print('\u000C');
shareimprove this answerfollow
edited Oct 11 '17 at 10:45

Community♦
111 silver badge
answered Apr 2 '16 at 6:26

Abhigyan Singh
7599 bronze badges
add a comment

1

You can use an emulation of cls with for (int i = 0; i < 50; ++i) System.out.println();

shareimprove this answerfollow
answered Jan 10 '15 at 5:09

Epic
1051111 bronze badges
2
Its just a hint, maybe someone want to clear the screen, Actually – Sarz Jan 30 '15 at 10:48
@Sarz: and actually "clearing the screen" doesn't make proper sense by itself, either – Gyom Feb 6 '15 at 13:07
add a comment

-2

You need to use JNI.

First of all use create a .dll using visual studio, that call system("cls"). After that use JNI to use this DDL.

I found this article that is nice:

http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=5170&lngWId=2

shareimprove this answerfollow
answered Sep 30 '14 at 16:47

Denny
9777 bronze badges
That's work to me. I have a real project using JNI to clear the screen in JAVA. – Denny Apr 30 '15 at 14:36
add a comment
Highly active question. Earn 10 reputation in order to answer this question. The reputation requirement helps protect this question from spam and non-answer activity.
Not the answer you're looking for? Browse other questions tagged java console clear or ask your own question.

来源:互联网

数据库管理系统-快速入门-ER图模型

什么是ER模型?

ER或(实体关系模型 Entity Relational Model)是一个高级概念数据模型图。 实体 - 关系模型基于现实世界实体的概念以及它们之间的关系。

ER建模可帮助您系统地分析数据需求,以生成设计良好的数据库。 因此,在实现数据库之前完成ER建模被认为是最佳实践。

 
Sample ER Diagram

ER模型的历史

ER图是一种可视化工具,有助于表示ER模型。 1971年Peter Chen提出建立可用于关系数据库和网络的统一约定。 他的目标是使用ER模型作为概念建模方法。

什么是ER图?

实体关系图显示存储在数据库中的实体集的关系。 换句话说,我们可以说ER图可以帮助您解释数据库的逻辑结构。 初看起来,ER图看起来与流程图非常相似。 但是,ER图包含许多专用符号,其含义使该模型独一无二。

  • ER模型允许您绘制数据库设计
  • 易于使用的图形工具,用于建模数据
  • 广泛用于数据库设计
  • 数据库逻辑结构的GUI表示
  • 识别系统中存在的实体以及这些实体之间的关系

为什么要使用ER图?

  • 定义与实体关系建模相关的术语
  • 预览所有表的连接方式,每个表上的字段
  • 帮助描述实体,属性,关系
  • ER图可以转换为关系表,允许您快速构建数据库
  • 数据库设计人员可以使用ER图作为在特定软件应用程序中实现数据的蓝图
  • 借助ERP图,数据库设计人员可以更好地理解数据库中包含的信息
  • 允许ERD与用户的数据库逻辑结构进行通信

ER图的组成部分

该模型基于三个基本概念:

实体
属性
关系

Components of the ER Diagram

例如,在大学数据库中,我们可能有学生,课程和讲师的实体。 学生实体可以具有Rollno,Name和DeptID等属性。 他们可能与课程和讲师有关系。

什么是实体?

它可能是一个物理的东西,或者仅仅是关于企业或现实世界中发生的事件的事实。

实体可以是地点,人物,对象,事件或概念,它将数据存储在数据库中。 实体的特征必须具有属性和唯一键。 每个实体都由一些代表该实体的“属性”组成。

实体示例:

  • 人:员工,学生,病人
  • 地点:商店,建筑
  • 对象:机器,产品和汽车
  • 事件:销售,注册,续订
  • 概念:帐户,课程

实体的表示法

实体集:

学生:实体集是一组类似的实体。 它可能包含属性共享相似值的实体。 实体由其属性表示,也称为属性。 所有属性都有各自的值。 例如,学生实体可以具有姓名,年龄,类别作为属性。

实体示例:

大学可能有一些部门。 所有这些部门都聘请了各种讲师并提供了几个课程。学生在特定课程中注册并注册各种课程。 来自特定部门的讲师参加每门课程,每位讲师都会教授不同的学生群体。

关系

关系只不过是两个或多个实体之间的联系。 例如,汤姆在化学系工作。

实体参与关系。 我们经常可以识别动词或动词短语的关系。

例如:

  • 你正在参加这个讲座
  • 我正在讲课
  • 只是loke实体,我们可以根据关系类型对关系进行分类:
  • 一名学生参加讲座
  • 讲师正在讲课。

弱实体

弱实体是一种没有键属性的实体。 可以通过考虑另一个实体的主键来唯一地识别它。

 
Weak Entities

在一个例子中,“Trans No”是ATM中一组交易中的鉴别器。

让我们通过将它与强实体进行比较来了解更多有关弱实体的信息

强实体集弱实体集
强实体集始终具有主键。它没有足够的属性来构建主键。
它由矩形符号表示。它由双矩形符号表示。
它包含由下划线符号表示的主键。它包含一个部分键,由虚线下划线符号表示。
强实体集的成员称为主实体集。弱实体集的成员称为从实体集。
主键是其有助于识别其成员的属性之一。在弱实体集中,它是强实体集的主键和部分键的组合。
在ER图中,使用菱形符号显示两个强实体集之间的关系。通过使用双菱形符号显示的一个强实体和弱实体组之间的关系。
设置关系的强实体的连接线是单一的。连接弱实体集以识别关系的线是双倍的。

属性

它是实体类型或关系类型的单值属性。

 
Attributes

例如,讲座可能有属性:时间,日期,持续时间,地点等。

属性由椭圆表示

**属性类型****描述**
**简单的属性**简单属性不能再进一步划分。 例如,学生的联系电话。 它也被称为原子价值。
**复合属性**可以分解复合属性。 例如,学生的全名可以进一步分为名字,名字和姓氏。
**派生属性**此类属性不包括在物理数据库中。 但是,它们的值来自数据库中存在的其他属性。 例如,不应直接存储年龄。 相反,它应该来自该员工的出生日期。
**多值属性**多值属性可以包含多个值。 例如,学生可以拥有多个手机号码,电子邮件地址等。

基数

定义两个实体或实体集之间关系的数字属性。

不同类型的主要关系是:

一对一的关系
一对多的关系
愿与一个人的关系
多对多关系

 
Cardinality
  • 一对一的关系:

来自实体集合X的一个实体可以与实体集合Y的至多一个实体相关联,反之亦然。

示例:一名学生可以注册多个课程。 但是,所有这些课程只有一行回到那个学生。

  • 一对多的关系

来自实体集合X的一个实体可以与实体集合Y的多个实体相关联,但是来自实体集合Y的实体可以与至少一个实体相关联。

例如,一个班级由多个学生组成。

  • 多对一

来自实体集合X的多于一个实体可以与实体集合Y的至多一个实体相关联。然而,来自实体集合Y的实体可以与实体集合X中的多于一个实体相关联,也可以不与之相关联。

例如,许多学生属于同一个班级。

  • 多对多:

来自X的一个实体可以与来自Y的多个实体相关联,反之亦然。

例如,作为一个群体的学生与多个教师相关联,并且教师可以与多个学生相关联。

ER-图表符号

ER-图表是描述数据如何相互关联的数据的直观表示。

  • 矩形:此符号表示实体类型
  • 椭圆:符号 代表属性
  • 菱形:这个符号 代表关系类型
  • 线:它将属性与实体类型和实体类型与其他关系类型相关联
  • 主键:属性带下划线
  • 双椭圆:表示多值属性
 
ER- Diagram Notations

创建ERD的步骤

 
Steps to Create an ERD

让我们用一个例子来研究它们:

在大学里,学生就读于课程。 必须将学生分配到至少一门或多门课程。 每门课程由一位教授授课。 为了保持教学质量,教授只能提供一门课程

实体识别

我们有三个实体

  • 学生
  • 课程
  • 教授
关系识别

我们有以下两种关系

  • 学生被分配了一门课程
  • 教授开设了一门课程
基数识别

对于他们的问题陈述,我们知道,

  • 可以为学生分配多个课程
  • 教授只能提供一门课程
识别属性

您需要研究组织当前维护的文件,表单,报告和数据,以识别属性。 您还可以与各利益相关方进行面谈,以确定实体。 最初,识别属性而不将其映射到特定实体非常重要。

一旦有了属性列表,就需要将它们映射到已识别的实体。 确保要将属性与一个实体配对。 如果您认为属性应属于多个实体,请使用修饰符使其唯一。

映射完成后,识别主键。

对于课程实体,属性可以是持续时间,学分,作业等。为了方便起见,我们只考虑了一个属性。

创建ERD

ERD图的更现代的表示

 
Create the ERD

制定有效的ER图的最佳实践

  • 消除任何冗余实体或关系
  • 确保所有实体和关系都已正确标记
  • ER图可能有各种有效的方法。 您需要确保ER图支持您需要存储的所有数据
  • 确保每个实体仅在ER图中出现一次
  • 命名每个关系,实体和属性都在图表中表示
  • 永远不要将关系彼此联系起来
  • 使用颜色突出显示ER图的重要部分

小结

  • ER模型是高级数据模型图
  • ER图是一种可视化工具,有助于表示ER模型
  • 实体关系图显示存储在数据库中的实体集的关系
  • ER图可帮助您定义与实体关系建模相关的术语
  • ER模型基于三个基本概念:实体,属性和关系
  • 实体可以是地点,人物,对象,事件或概念,它将数据存储在数据库中
  • 关系只不过是两个或多个实体之间的联系
  • 弱实体是一种没有其关键属性的实体,实体类型或关系类型的单值属性,可以帮助您定义两个实体或实体集之间关系的数字属性
  • ER-图表是描述数据如何相互关联的数据的直观表示
  • 在绘制ER图时,您需要确保所有实体和关系都已正确标记。
 来源:https://www.jianshu.com/p/151b0443602f

深入理解Spring MVC

初始工程

这篇文章中将使用最新的Spring Framework 5框架。主要关注的是Spring的经典Web技术栈,这套技术从最开始的Spring版本就开始支持,并且知道现在仍然是构建Spring Web应用的主要方式。
使用Spring Boot和其他starter来设置初始工程。xml配置如下:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.1</version>
    <relativePath/>
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
</dependencies>
测试项目

为了理解Spring Web MVC是如何工作的,可以先实现一个简单的Login功能的。创建一个由@Controller来修饰的类InternalController,这个类包含一个Get的映射。
hello()函数没有参数。返回一个由Spring解释的视图名字的字符串。(在本例中是login.html

import org.springframework.web.bind.annotation.GetMapping;

@GetMapping("/")
public String hello() {
    return "login";
}

为了处理用户登陆逻辑,创建另一个接受POST请求的带有Login数据的方法。然后根据处理结果返回成功或者失败页面。 注意,login()函数接受一个领域对象作为参数,返回的是ModelAndView对象。

@PostMapping("/login")
public ModelAndView login(LoginData loginData) {
    if (LOGIN.equals(loginData.getLogin()) 
      && PASSWORD.equals(loginData.getPassword())) {
        return new ModelAndView("success", 
          Collections.singletonMap("login", loginData.getLogin()));
    } else {
        return new ModelAndView("failure", 
          Collections.singletonMap("login", loginData.getLogin()));
    }
}

ModelAndView保存了两个不同的对象:

  • Model: 用来渲染页面用的键值对的map
  • View: 填充Model数据的模版页面。

将它们合并起来是为了方便,这样controller的方法就可以同时返回这两个了。 使用Thymeleaf作为模版引擎来渲染页面。

Java Web应用的基础-Servlet

当你在浏览器里键入http://localhost:8080/,然后按回车键,请求到达服务器的时候到底发生了什么?是如何在浏览器中看到这个web请求的数据的? 因为这个项目是一个简单的Spring Boot应用,所以可以通过Spring5Application来运行。 Spring Boot默认使用Apache Tomcat运行程序,运行成功后可能会看到如下的日志:

2017-10-16 20:36:11.626  INFO 57414 --- [main] 
  o.s.b.w.embedded.tomcat.TomcatWebServer  : 
  Tomcat initialized with port(s): 8080 (http)
  
2017-10-16 20:36:11.634  INFO 57414 --- [main] 
  o.apache.catalina.core.StandardService   : 
  Starting service [Tomcat]

2017-10-16 20:36:11.635  INFO 57414 --- [main] 
  org.apache.catalina.core.StandardEngine  : 
  Starting Servlet Engine: Apache Tomcat/8.5.23

因为Tomcat是一个Servlet容器,所以几乎所有的HTTP请求都是由Java Servlet处理的。自然的Spring Web的入口就是一个Servlet。 Servlet是所有Java Web应用的核心组件;它非常的低成,并且没有暴露任何具体的编程模式,例如MVC。 一个HTTP的Servelt只能接受HTTP请求,处理请求后返回响应。 现在使用Servlet 3.0的API,可以不再使用XML配置,直接可以使用Java配置。

Spring MVC的核心-DispatcherServlet

作为Web开发者,我们希望抽象出以下枯燥和样板的任务,而关注于有用的业务逻辑

  • 将HTTP请求映射到响应处理函数
  • 将HTTP请求数据和header解析成数据传输对象(DTOs)或者领域对象
  • model-view-controller 互相交互
  • 从DTO,领域对象等生成响应

Spring的DispatcherServlet提供了以上的功能,是Spring WEB MVC框架的核心,是应用接受所有请求的核心组件。 稍后就会了解到DispatcherServlet可扩展性非常强。例如:它允许你加入现有或者新的适配器来适应不同的任务:

  • 将请求映射到处理它的类或者函数(由HandlerMapping实现)
  • 使用特定模式来处理请求,例如一个普通的Servlet,一个复杂的MVC 工作流,或者只是一个方法。(由HandlerAdapter实现)
  • 通过名字解析试图对象,允许你使用不同的模版引擎,例如:XML,XSLT或者其他视图技术(由ViewResolver实现)
  • 默认使用Apache Comons 的文件上传组件解析文件上传,或者也可以自己实现。
  • LocalResolver实现本地化,包括cookie,session,HTTP的Accept Header,或者其他由用户定义的本地化。
处理HTTP请求

首先让我们重新审视一下在刚刚建立的应用中是如何处理HTTP请求的。 DispatcherServlet有一个很长的继承层级。自顶向下理解每个单独的概念是非常有必要的。处理请求的函数将会更加有趣。理解HTTP请求在本地开发模式处理和远程处理是理解MVC架构非常重要的一步。

GenericServlet

GenericServlet时Servlet规范中的一部分,不直接处理HTTP。它定义了service()方法,来接受请求和返回响应。 注意,ServletRequestServletResponse并不是绑定到HTTP协议的。

public abstract void service(ServletRequest req, ServletResponse res) 
  throws ServletException, IOException;

服务器所有的请求,包括简单的GET请求都会调用这个方法。

HttpServlet

正如其名,HttpServelt是Servlet 规范中关于HTTP请求的实现。 更确切的说,HttpServlet是一个实现了service()的抽象类。通过将不同的HTTP请求类型分开,由不同的函数处理,实现大约如下所示:

protected void service(HttpServletRequest req, HttpServletResponse resp)
    throws ServletException, IOException {

    String method = req.getMethod();
    if (method.equals(METHOD_GET)) {
        // ...
        doGet(req, resp);
    } else if (method.equals(METHOD_HEAD)) {
        // ...
        doHead(req, resp);
    } else if (method.equals(METHOD_POST)) {
        doPost(req, resp);
        // ...
    }
HttpServletBean

在这个继承关系中HttpServletBean是第一个Spring的类。从web.xml或者WebApplicationInitialzer获取的初始参数来注入bean。 在应用中的请求分别调用doGet,doPost等方法来处理不同的HTTP请求。

FrameworkServlet

FrameworkServlet实现了ApplicationContextAware,集成Web的Application Context。不过它也可以创建自己的Application Context。 正如上述所言,父类HttpServletBean通过将初始参数作为bean的属性注入。因此如果contex的类名在contextClass这个初始参数中,那么就有这个参数创建application context的实例,否则默认使用XmlWebApplicationContext。 由于XML配置现在已经过时了。Spring Boot默认使用AnnotationConfigWebApplicationContext来配置DispatcherServlet。不过这个是很容易修改的。 例如,想要在Spring MVC中使用Groovy的application context,可以将下列配置在web.xml中

  dispatcherServlet
        org.springframework.web.servlet.DispatcherServlet
        contextClass
        org.springframework.web.context.support.GroovyWebApplicationContext

相同的配置也可以在WebApplicationInitializer中配置。

DispatcherServlet: 统一处理请求

HttpServlet.service()通过HTTP的动词类型来处理路由不同的请求到不同的方法,这个在底层的servlet实现的很好。但是,在SpringMVC的抽象层次中,不能仅靠方法类型来路由请求。 同样的,FrameworkServlet的另一个主要功能就是将不同的处理使用processRequest()组合在一起。

@Override
protected final void doGet(HttpServletRequest request, 
  HttpServletResponse response) throws ServletException, IOException {
    processRequest(request, response);
}

@Override
protected final void doPost(HttpServletRequest request, 
  HttpServletResponse response) throws ServletException, IOException {
    processRequest(request, response);
}
DispatcherServlet: 丰富请求

最后,DispatcherServlet实现doService()方法。它向请求中加入了一些有用的对象,继续在web 的管道中传递下去,例如:web application context, locale resolver, theme resolver, theme source等

request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, 
  getWebApplicationContext());
request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());

同时,doService()加入了输入输出的Flash Map,Flash Map是将参数从一个请求传递到另一个请求的基本模式。在重定向中很有用。(例如在重定向之后向用户展示一段简单的信息)

FlashMap inputFlashMap = this.flashMapManager
  .retrieveAndUpdate(request, response);
if (inputFlashMap != null) {
    request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, 
      Collections.unmodifiableMap(inputFlashMap));
}
request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());

接着doService()将会调用doDispatch()方法来分发请求。

DispatcherServlet: 分发请求

dispatch()的主要目的就是知道一个合适的处理请求的处理器并且传递request/response参数。处理器可以是任何对象,并不局限于一个特定的接口。同样也意味着Spring需要找到如何使用这个处理器的适配器。 为了给请求找到合适的处理器,Spring会遍历实现HandlerMapping接口的注册的实现。有很多不同的实现可以满足我们各种需求。 SimpleUrlHandlerMapping使用URL将请求映射到处理bean中。例如:它可以通过Java.util.Properties注入它的映射信息:

/welcome.html=ticketController
/show.html=ticketController

RequestMappingHandlerMapping可能是最广泛使用的映射处理器。它将请求映射到@Controller类下的@RequestMapping修饰的方法上。这个就是上面那个例子中的hello()login()。 注意,上面两个方法分别是@GetMapping@PostMapping修饰的。这两个注解来源于@RequestMapping。 dispatch()同时也可以处理一些其他的HTTP的任务:

  • 如果资源不存在,对GET请求进行短路处理。
  • 对相应的请求使用multipart 解析。
  • 如果处理器选择异步处理请求,对请求进行短路处理。
处理请求

现在Spring确定了处理请求的处理器和处理器的适配器,是时候处理请求了。下面是HandlerAdapter.handle()的签名。比较重要的一点是处理器可以选择如何处理请求:

  • 直接将相应写入到response body 和 返回null
  • 返回一个ModelAndView对象由DispatcherServlet渲染。
@Nullable
ModelAndView handle(HttpServletRequest request, 
                    HttpServletResponse response, 
                    Object handler) throws Exception;

Spring提供了很多类型的处理器,下面是SimpleControllerHandlerAdapter如何处理Spring MVC的controller实例的(不要和@Controller搞混)。 注意,controller处理器返回ModelAndView对象并不是由起渲染的。

public ModelAndView handle(HttpServletRequest request, 
  HttpServletResponse response, Object handler) throws Exception {
    return ((Controller) handler).handleRequest(request, response);
}

第二个是SimpleServletHandlerAdapter它对一个普通的servlet适配。 servlet并不知道ModelAndView,完全自己处理请求,将返回写入到相应的body中。因此它的适配器就直接返回null。

public ModelAndView handle(HttpServletRequest request, 
  HttpServletResponse response, Object handler) throws Exception {
    ((Servlet) handler).service(request, response);
    return null;
}

在本例中,controller是由@RequestMapping修饰的POJO,因此处理器会使用HandlerMethod来封装它的方法。Spring使用RequestMappingHandlerAdapter来适配这种处理器类型。

处理参数,返回处理器函数的值

注意,一般来说controller并不会接收HttpServletRequestHttpServletResponse作为参数,但是它可以接收和返回很多中其他类型,例如:领域对象,路径参数等。 同样,也不强求一个controller返回一个ModelAndView实例。可以选择返回一个视图名称,ResponseEntity,或者是一个可以被转换成JSON的POJO。 RequestMappingHandlerAdapter可以保证从HttpServletRequest中解析方法需要的参数,同时创建ModelAndView对象返回。 下面这段代码就是RequestMappingHandlerAdapter中保证这件事情的:

ServletInvocableHandlerMethod invocableMethod 
  = createInvocableHandlerMethod(handlerMethod);
if (this.argumentResolvers != null) {
    invocableMethod.setHandlerMethodArgumentResolvers(
      this.argumentResolvers);
}
if (this.returnValueHandlers != null) {
    invocableMethod.setHandlerMethodReturnValueHandlers(
      this.returnValueHandlers);
}

argumentResolversHandlerMethodArgumentResolver实例中有不同实现。一共有30多种不同的参数解析器的实现。他们可以从请求参数将函数需要的参数解析出来。包括:url路径变量,请求体参数,请求头,cookies,session等。 returnValueHandlersHandlerMethodArgumentResolver实例中有不同实现。同样也有很多不同的返回值处理器来处理方法返回的结果,创建ModelAndView对象。 例如:当函数hello()返回一个string的时候,ViewNameMethodReturnValueHandler处理这个值。login()返回一个ModelAndView对象的时候,Sring使用ModelAndViewMethodReturnValueHandler处理这个值。

渲染视图

现在Spring已经处理了HTTP请求,获取了ModelAndView实例,现在它需要在用户浏览器渲染HTML页面了。它依赖于由Model和选择的模版组成的ModelAndView对象。 同样的,Spring也可以渲染JSON ,XML或者其他HTTP协议接受的类型。这些将在接下来的REST相关了解更多。 现在回去看一下DispatcherServletrender()首先使用LocaleResolver实例设置返回的Local。首先假设浏览器已经正确设置Accetp头。默认使用AcceptHeaderLocaleResolver来处理。 在渲染过程中,ModelAndView可以包含一个视图的名字或者是已经选择的视图,或者如果controller依赖于默认视图也可以没有。 既然hello()login()方法制定了字符串名字作为视图名称,所以需要使用viewResolvers来查找视图。

for (ViewResolver viewResolver : this.viewResolvers) {
    View view = viewResolver.resolveViewName(viewName, locale);
    if (view != null) {
        return view;
    }
}

ViewResolver的实现由很多,这里使用了由thymeleaf-spring5提供的ThymeleafViewResolver实现。解析器知道去哪里查找视图,并且提供相应的视图实例。 调用完render()之后,Spring就完成了将HTML页面渲染到用户浏览器的任务。

REST 支持

除了MVC的场景,我们可以使用狂减创建rest web service。 一个简单的场景,可以使用由@RequestBody修饰的POJO作为参数。由@ResponseBody修饰方法,指定方法的返回结果直接写入到响应体中。

import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;

@ResponseBody
@PostMapping("/message")
public MyOutputResource sendMessage(
  @RequestBody MyInputResource inputResource) {
    
    return new MyOutputResource("Received: "
      + inputResource.getRequestMessage());
}

感谢SpringMVC的扩展性,这样做也是可以的。 框架使用HttpMessageConverter将内部DTO转换成REST的表示。例如:MappingJackson2HttpMessageConverter的可以使用Jackson库将转换model和JSON。 为了简化创建REST API,Srping 引入了@RestController注解。默认使用@ResonseBody这样就不需要在每个方法中使用了。

import org.springframework.web.bind.annotation.RestController;

@RestController
public class RestfulWebServiceController {

    @GetMapping("/message")
    public MyOutputResource getMessage() {
        return new MyOutputResource("Hello!");
    }
}
结论

在这篇文章中,详细描述了Spring MVC处理HTTP请求的各个步骤。了解到Spring 框架是如何将各个组件组合在一起提供处理HTTP协议的。

 

来源:https://www.codemore.top/cates/Backend/post/2018-04-07/deep-in-spring-mvc/

Spring框架与Springmvc框架容器详解

spring框架与Springmvc框架概述

现在做为java开发的程序员,我相信基本上每个人都听说过Spring框架,而SpringMVC框架也逐渐的替代了原来的一些MVC框架,成为了Web层框架的佼佼者,但是SpringMVC框架其实本身也是Spring 框架的一个后续产品,这两个框架在结合到一起使用的时候Spring会有自己的IOC容器,而Springmvc也会有自己的ioc容器,两个框架一起使用的时候会有一些什么样的问题,或者两个框架的容器直接是一种什么样的关系,今天我们一起来讨论一下
spring框架与Springmvc框架整合使用的细节


Springmvc框架的基本使用
在理解spring框架与Springmvc框架一起使用时的两个容器关系之前,我们先对SpringMVC框架的使用步骤做一个简单介绍,以下是SpringMVC在使用的时候的基本代码
1. 在web项目的web.xml文件中配置Springmvc前端控制器
2. 在项目中创建springmvc的配置文件

3. 当做了前面两个配置之后就能直接在项目中创建Controller类和方法去接收请求

Springmvc的基本执行过程
当我们做了上面的一些事情之后,服务器在启动的时候就会去创建Springmvc的前端控制器(DispatcherServlet),这个Servlet一创建就会帮助我们去加载Springmvc的配置文件,从而初始化Springmvc的容器,创建所有的Controller。以后发送请求的时候,执行的过程会经过Springmvc的各个组件,大致流程如下图



spring框架与Springmvc框架整合使用


1. spring框架与Springmvc框架整合使用的思路
当我们在实际案例中去使用SpringMVC的时候由于我们需要在Controller中注入Service,所以我们必须要保证Controller对象创建之前Service对象要创建,而我们都知道Service最终都会交给Spring去管理,所以Spring的容器应该要先于Springmvc的容器创建才行
2.具体代码实现
代码实现很简单,想要web项目在加载Springmvc的配置之前先加载Spring的配置,只需要在web.xml文件中配置一下Spring的监听器和配置文件位置就可以

spring框架与Springmvc框架一起使用后两个容器的关系
spring框架与Springmvc框架一起使用后Spring会有Spring的容器,在Spring容器中会创建Service,Dao层的对象,当然也会有SpringMVC的容器,SpringMVC容器会创建Controller对象,那么当我们去发送请求到Controller中去的时候,Controller中会注入Service对象,SpringMVC容器中的Controller对象是如何去注入Spring容器中的service对象的,相信部分刚接触SpringMVC框架的学者会在这个地方有疑问,那么接下来我们就一起去跟着Spring和SpringMVC源码一起来揭秘一下这个问题:
Spring容器加载
首先我们都知道,服务器一启动会去去执行Spring监听器中的代码加载Spring配置文件初始化容器,我们先去看看这一部分Spring是如何去完成的。
通过这一部分源码我们发现,服务器已启动,listener中确实会帮我们去创建Spring容器,但是他还会做一件事情,就是将容器保存到ServletContext域对象中
SpringMVC容器加载
从Springmvc源代码中可以看到SpringMVC容器初始化的过程如下图:

SpringMVC的容器在初始化的时候,会把原来已经保存在ServletContext中的Spring容器设置成SpringMVC的父容器,也就是说Spring容器和SpringMVC容器直接是一种逻辑上的父子关系,SpringMVC容器是子容器,Spring容器是父容器,所以在SpringMVC容器中的Controller能注入Spring容器中的service对象
总结
通过前面的分析,这样我们在清楚了spring和springMVC的父子容器关系;所以在项目中当我们同时去使用Spring框架和Springmvc框架的时候,Springmvc中的Controller能够访问到Springmvc父容器(Spring容器)中的对象
来源:http://bbs.itheima.com/thread-443226-1-1.html

spring和springMVC父子容器的原理

转载自:https://my.oschina.net/jast90/blog/282773#

要想很好理解这三个上下文的关系,需要先熟悉spring是怎样在web容器中启动起来的。spring的启动过程其实就是其IoC容器的启动过程,对于web程序,IoC容器启动过程即是建立上下文的过程。

spring的启动过程:

  1. 首先,对于一个web应用,其部署在web容器中,web容器提供其一个全局的上下文环境,这个上下文就是ServletContext,其为后面的spring IoC容器提供宿主环境;
  2. 其次,在web.xml中会提供有contextLoaderListener。在web容器启动时,会触发容器初始化事件,此时contextLoaderListener会监听到这个事件,其contextInitialized方法会被调用,在这个方法中,spring会初始化一个启动上下文,这个上下文被称为根上下文,即WebApplicationContext,这是一个接口类,确切的说,其实际的实现类是XmlWebApplicationContext。这个就是spring的IoC容器,其对应的Bean定义的配置由web.xml中的context-param标签指定。在这个IoC容器初始化完毕后,spring以WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE为属性Key,将其存储到ServletContext中,便于获取;
  3. 再次,contextLoaderListener监听器初始化完毕后,开始初始化web.xml中配置的Servlet,这个servlet可以配置多个,以最常见的DispatcherServlet为例,这个servlet实际上是一个标准的前端控制器,用以转发、匹配、处理每个servlet请求。DispatcherServlet上下文在初始化的时候会建立自己的IoC上下文,用以持有spring mvc相关的bean。在建立DispatcherServlet自己的IoC上下文时,会利用WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE先从ServletContext中获取之前的根上下文(即WebApplicationContext)作为自己上下文的parent上下文。有了这个parent上下文之后,再初始化自己持有的上下文。这个DispatcherServlet初始化自己上下文的工作在其initStrategies方法中可以看到,大概的工作就是初始化处理器映射、视图解析等。这个servlet自己持有的上下文默认实现类也是mlWebApplicationContext。初始化完毕后,spring以与servlet的名字相关(此处不是简单的以servlet名为Key,而是通过一些转换,具体可自行查看源码)的属性为属性Key,也将其存到ServletContext中,以便后续使用。这样每个servlet就持有自己的上下文,即拥有自己独立的bean空间,同时各个servlet共享相同的bean,即根上下文(第2步中初始化的上下文)定义的那些bean。

说完了spring上下文的初始化过程,这三个上下文的关系应该就了解了。如还是不太清楚,我就爱莫能助了,只能自行看代码去了。

===============================================================================================================

最近在做项目时牵扯到有关父子上下文的概念。

何为父子上下文呢?

父上下文:

使用listener监听器来加载配置文件,如下:

?
1
2
3
<listener>   
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>   
</listener>

Spring 会创建一个WebApplicationContext上下文,称为父上下文(父容器),保存在 ServletContext中,key是WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE的值。

可以使用Spring提供的工具类取出上下文对象:WebApplicationContextUtils.getWebApplicationContext(ServletContext);

子上下文:

使用Spring MVC 来处理拦截相关的请求时,会配置DispatchServlet:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext-mvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

每个DispatchServlet会有一个自己的上下文,称为子上下文,它也保存在 ServletContext中,key 是"org.springframework.web.servlet.FrameworkServlet.CONTEXT"+Servlet名称。当一 个Request对象产生时,会把这个子上下文对象(WebApplicationContext)保存在Request对象中,key是 DispatcherServlet.class.getName() + ".CONTEXT"。

可以使用工具类取出上下文对象:RequestContextUtils.getWebApplicationContext(request);

父上下文(父容器)和子上下文(子容器)的访问权限:

子上下文可以访问父上下文中的bean,但是父上下文不可以访问子上下文中的bean。

父上下文使用与否

方案一,传统型:

父上下文容器中保存数据源、服务层、DAO层、事务的Bean。

子上下文容器中保存Mvc相关的Action的Bean.

事务控制在服务层。

由于父上下文容器不能访问子上下文容器中内容,事务的Bean在父上下文容器中,无法访问子上下文容器中内容,就无法对子上下文容器中Action进行AOP(事务)。

当然,做为“传统型”方案,也没有必要这要做。

 

方案二,激进型:

Java世界的“面向接口编程”的思想是正确的,但在增删改查为主业务的系统里,Dao层接口,Dao层实现类,Service层接口,Service层实现类,Action父类,Action。再加上众多的O(vo\po\bo)和jsp页面。写一个小功能 7、8个类就写出来了。 开发者说我就是想接点私活儿,和PHP,ASP抢抢饭碗,但我又是Java程序员。最好的结果是大项目能做好,小项目能做快。所以“激进型”方案就出现了-----没有接口、没有Service层、还可以没有众多的O(vo\po\bo)。那没有Service层事务控制在哪一层?只好上升的Action层。

本文不想说这是不是正确的思想,我想说的是Spring不会限制你这样做。

由于有了父子上下文,你将无法实现这一目标。解决方案是只使用子上下文容器,不要父上下文容器 。所以数据源、服务层、DAO层、事务的Bean、Action的Bean都放在子上下文容器中。就可以实现了,事务(注解事务)就正常工作了。这样才够激进。

总结:不使用listener监听器来加载spring的配置文件,只使用DispatcherServlet来加载spring的配置,不要父子上下文,只使用一个DispatcherServlet,事情就简单了,什么麻烦事儿也没有了。

Spring4新特性简述

Spring是一个java世界中极其流行的开源框架。Spring的初衷是降低企业级开发的复杂性,并试图通过POJO对象实现之前EJB这类重型框架才能实现的功能。Spring不仅仅对服务端开发有用,任何Java应用都可受益于Spring的简洁、易测试和低耦合等特性。

Spring框架中使用beansJavaBeans来表示应用程序中的组件,但这并不意味着该组件必须严格满足Java Bean的规范。
Spring做了很多事情,但是归根到底是一些基本的思路,而所有这些思路最终都导向Spring的使命:简化Java开发
Spring通过下列四种策略来简化Java开发:
基于POJO的轻量级、最小侵入式开发;
通过依赖注入和面向接口编程实现松耦合;
通过面向切面编程和惯例实现声明式编程;
通过面向切面编程和模板消除样板式代码
按照功能划分,这些模块可以分成六组,如下图所示:

这些模块几乎可以满足所有企业级应用开发的需求,但是开发人员并不需要完全使用Spring的这些模块,可以自由选择符合项目需求的第三方模块——Spring为一些第三方模块提供了交互接口。
CORE SPRING CONTAINER
Spring框架的核心模块,其他所有模块都基于该模块构建。Spring容器负责管理Spring应用中bean的创建、配置和管理。在这模块中有Spring bean factory,该接口提供了最基本的依赖注入(DI)功能;基于bean factory,该模块提供了集中Spring应用上下文的实现,可以供开发人员选择。
除了bean factory和application context,该模块还支持其他企业级服务,例如email、JNDI access、EJB integration和scheduling。
SPRING's AOP MODULE
Spring框架通过AOP模块提供面向切面编程的能力。通过AOP模块,一些系统层面的需求(事务、安全)可以与它们真正要作用到的模块相互解耦合。
DATA ACCESS AND INTEGRATION
Spring的JDBC和data-access object模块将数据库操作的一些样板式代码封装起来,免去了开发人员的很多工作量。这个模块还对数据库层的异常进行了封装,并向上提供含义更丰富的异常信息。
Spring并未实现自己的ORM框架,但是它提供了跟其他几个ORM框架整合的能力,例如Hibernate、Mybatis、Java Persistence AP等等,而且这些ORM框架都支持使用Spring提供的事务管理模块。
WEB AND REMOTING
Spring提供了自己的 WEB开发框架——Spring MVC,除此之外,这个模块还提供远程调用支持:Remote Method Invocation(RMI)、Hessian、Burlap和JAX-WS。
INSTRUMENTATION
不常使用
TESTING
可以与常用的JUNIT、Mockito、Spock等测试框架整合使用。
spring4新特性
spring4.x不仅支持Java8,而且向下兼容到JavaSE6/JavaEE6,并移出了相关废弃类,新添加如Java8的支持、Groovy式Bean定义DSL、对核心容器进行增强、对Web框架的增强、Websocket模块的实现、测试的增强等。
这里简单列举下实际中用得多的地方:
支持map,list注入

@Autowired
private Map<String,MyService> map;
@Autowired
private List<MyService> list;

对于map,会将所有类型为MyService的bean以bean的name为key注入到map
对于list,会注入所有MyService类型的bean
基于CGLIB的类代理不再要求类必须有空参构造器了:
这是一个很好的特性,使用构造器注入有很多好处,比如可以只在创建Bean时注入依赖,然后就不变了,如果使用setter注入,是允许别人改的.
WEB开发增强
为了方便Rest开发,通过新的@RestController指定在控制器上,这样就不需要在每个@RequestMapping方法上加@ResponseBody了。而且添加了一个AsyncRestTemplate,支持REST客户端的异步无阻塞支持.

 

@RestController
public class UserController {
  private UserService userService;

  @Autowired
  public UserController(UserService userService) {
      this.userService = userService;
  }
  @RequestMapping("/test")
  public User view() {
      User user = new User();
      user.setId(1L);
      user.setName("haha");
      return user;
  }
}

提供AsyncRestTemplate用于客户端非阻塞异步支持。
服务器端

 

@RestController
public class UserController {
    private UserService userService;
    @Autowired
    public UserController(UserService userService) {
        this.userService = userService;
    }
    @RequestMapping("/api")
    public Callable api() {
        System.out.println("=====hello");
        return new Callable() {
            @Override
            public User call() throws Exception {
                Thread.sleep(10L *1000);//暂停两秒
                User user =new User();
                user.setId(1L);
                user.setName("haha");
                return user;
            }
        };
    }
}

客户端

 

  public static void main(String[] args) {
        AsyncRestTemplate template =new AsyncRestTemplate();
//调用完后立即返回(没有阻塞)
        Listenable<Future> future = template.getForEntity("http://localhost:9080/spring4/api", User.class);
//设置异步回调
        future.addCallback(new ListenableFutureCallback > ()  {
            @Override
            public void onSuccess (ResponseEntity result) {
                System.out.println("======client get result : " + result.getBody());
            }
            @Override
            public void onFailure (Throwable t) {
                System.out.println("======client failure : " + t);
            }
        });
        System.out.println("==no wait");
    }

此处使用Future来完成非阻塞,这样的话我们也需要给它一个回调接口来拿结果; Future和Callable是一对,一个消费结果,一个产生结果。调用完模板后会立即返回,不会阻塞;有结果时会调用其回调.
Bean Validate新特性
支持跨参数验证(比如密码和确认密码的验证)和支持在消息中使用EL表达式,其他的还有如方法参数/返回值验证、CDI和依赖注入、分组转换等。
其他的一些改进:
1、核心部分基本上无变化,提供了DirectFieldAccessor用于直接字段访问、yaml配置、SpEL的字节码编译化、BackOff退避算法的基本实现、Base64Utils、SmartInitializingSingleton等;
2、在任务调度和事件机制上加入了异常处理部分;
3、cache部分加入jcache的集成、类级别的@CacheConfig的支持、CacheResolver;
4、mvc部分提供了一些视图解析器的mvc标签实现简化配置、提供了GroovyWebApplicationContext用于Groovy web集成、提供了Gson、protobuf的HttpMessageConverter、静态资源处理方面添加了resolver和transformer、提供了对groovy-templates模板的支持、JSONP的支持、对Jackson的@JsonView的支持等;
5、提供了页面自动化测试框架Spring MVC Test HtmlUnit;
6、test部分提供了更便利的@sql标签来执行测试脚本的初始化、MockRestServiceServer对AyncRestTemplate支持、MockMvcConfigurer来全局配置MockMvc;
7、提供了对Java8 Optional的支持(ObjectToOptionalConverter实现;可以在MVC中如@RequestParam等注解的绑定)、从Spring 4.1起Ehcache支持需要EhCache 2.5或更高版本、兼容Quartz 2.1.4、支持javax.annotation.Priority(等价于@Order)、JMS API的增强、SpringJUnit4ClassRunner需要 JUnit 4.9或更高版本支持。
总体来说没有大的变化,只是一些增强,因此我们升级是很容易的。

来源:https://www.jianshu.com/p/95bf60d34352

---------------------------

Spring 4.0 新功能和增强

Spring 框架第一个版本发布于 2004 年,自发布以来已历经三个主要版本更新: Spring 2.0 提供了 XML 命名空间和 AspectJ 支持;Spring 2.5 增加了注释驱动(annotation-driven)的配置支持; Spring 3.0增加了对 Java 5+ 版本的支持和 @Configuration 模型。

Spring 4.0 是最新的主要版本,并且首次完全支持 Java 8 的特性。你仍然可以使用老版本的 Java,但是最低版本的要求已经提高到 Java SE 6。我们也借主要版本更新的机会删除了许多过时的类和方法。

你可以在Spring Framework GitHub Wiki上查看 升级 Spring 4.0 的迁移指南。

改进的入门体验

新的 spring.io 网站提供了一整个系列的 "入门指南" 帮助你学习 Spring。你可以本文档的 1. Getting Started with Spring 一节阅读更多的入门指南。新网站还提供了Spring 之下其他额外项目的一个全面的概述。

如果你是一个 Maven 用户,你可能会对 BOM 这个有用的 POM 文件感兴趣, 这个文件已经与每个 Spring 的发布版发布。

移除不推荐的包和方法

所有过时的包和许多过时的类和方法已经从Spring4中移除。如果你从之前的发布版升级Spring,你需要保证已经修复了所有使用过时的API方法。

查看完整的变化: API差异报告。

请注意,所有可选的第三方依赖都已经升级到了最低2010/2011(例如Spring4 通常只支持 2010 年的最新或者现在的最新发布版本):尤其是 Hibernate 3.6+、EhCache 2.1+、Quartz 1.8+、Groovy 1.8+、Joda-Time 2.0+。但是有一个例外,Spring4依赖最近的Hibernate Validator 4.3+,现在对Jackson的支持集中在2.0+版本 (Spring3.2支持的Jackson 1.8/1.9,现在已经过时)。

Java 8(以及6和7)支持

Spring4 支持 Java8 的一些特性。你可以在 Spring 的回调接口中使用 lambda 表达式 和 方法引用。支持java.time (JSR-310)的值类型和一些改进过的注解,例如 @Repeatable。你还可以使用 Java8 的参数名称发现机制(基于-parameters编译器标志)。

Spring 仍然兼容老版本的 Java 和 JDK:Java SE 6(具体来说,支持JDK6 update 18 )以上版本,我们建议新的基于 Spring4 的项目使用Java7或Java8。

Java EE 6 和 7支持

Java EE 6 或以上版本是 Spring4 的底线,与 JPA2.0 和 Servlet3.0规范有着特殊的意义。为了保持与 Google App Engine 和旧的应用程序服务器兼容,Spring4 可以部署在 Servlet2.5 运行环境。但是我们强烈的建议您在 Spring 测试和模拟测试的开发环境中使用 Servlet3.0+。

如果你是WebSphere 7的用户,一定要安装JPA2.0功能包。在WebLogic 10.3.4或更高版本,安装附带的JPA2.0补丁。这样就可以将这两种服务器变成Spring4兼容的部署环境。

从长远的观点来看,Spring4.0 现在支持 Java EE 7 级别的适用性规范:尤其是 JMS 2.0, JTA 1.2, JPA 2.1, Bean Validation 1.1 和JSR-236 并发工具类。像往常一样,支持的重点是独立的使用这些规范。例如在 Tomcat 或者独立环境中。但是,当把 Spring 应用部署到 Java EE 7 服务器时它同样适用。

注意,Hibernate 4.3 是 JPA 2.1 的提供者,因此它只支持 Spring4。同样适用用于作为 Bean Validation 1.1 提供者的 Hibernate Validator 5.0。这两个都不支持 Spring3.2。

Groovy Bean Definition DSL

Spring4.0 支持使用 Groovy DSL 来进行外部的 bean 定义配置。这在概念上类似于使用 XML 的 bean 定义,但是支持更简洁的语法。使用Groovy 还允许您轻松地将 bean 定义直接嵌入到引导代码中。例如:

  1. def reader = new GroovyBeanDefinitionReader(myApplicationContext)
  2. reader.beans {
  3. dataSource(BasicDataSource) {
  4. driverClassName = "org.hsqldb.jdbcDriver"
  5. url = "jdbc:hsqldb:mem:grailsDB"
  6. username = "sa"
  7. password = ""
  8. settings = [mynew:"setting"]
  9. }
  10. sessionFactory(SessionFactory) {
  11. dataSource = dataSource
  12. }
  13. myService(MyService) {
  14. nestedBean = { AnotherBean bean ->
  15. dataSource = dataSource
  16. }
  17. }
  18. }

有关更多信息,请参阅 GroovyBeanDefinitionReader javadocs

核心容器改进

有几种对核心容器的常规改进:

  • Spring 现在注入 Bean 的时候把 泛型类型当成一种形式的限定符。例如:如果你使用S pring DataRepository 你可以方便的插入特定的实现:@Autowired Repository<Customer> customerRepository
  • 如果你使用 Spring 的元注解支持,你现在可以开发自定义注解来公开源注解的特定属性。
  • 当自动装配到lists和arrays时,Beans 现* 在可以被 排序 了。支持@Order注解和Ordered接口两种方式。 @Lazy注解现在可以用在注入点以及@Bean定义上。
  • 引入@Description注解,开发人员可以使用基于Java 方式的配置。
  • 根据条件筛选 Beans的广义模型通过@Conditional注解加入。这和@Profile支持的类似,但是允许以编程式开发用户定义的策略。
  • 基于CGLIB的代理类不在需要默认的构造方法。这个支持是由 objenesis库提供。这个库重新打包到 Spring 框架中,作为Spring框架的一部分发布。通过这个策略,针对代理实例被调用没有构造可言了。
  • 框架现在支持管理时区。例如LocaleContext

常规Web改进

现在仍然可以部署到 Servlet 2.5 服务器,但是 Spring4.0 现在主要集中在 Servlet 3.0+ 环境。如果你使用Spring MVC 测试框架,你需要将 Servlet 3.0 兼容的 JAR 包放到 测试的 classpath 下。

除了稍后会提到的 WebSocket 支持外,下面的常规改进已经加入到Spring 的 Web 模块:

  • 你可以在Spring MVC应用中使用新的@RestController注解,不在需要给@RequestMapping的方法添加@ResponseBody注解。
  • AsyncRestTemplate 类已被添加进来,当开发 REST 客户端时,允许非阻塞异步支持。
  • 当开发 Spring MVC 应用时,Spring现在提供了全面的时区支持 。

WebSocket, SockJS, 和 STOMP 消息

一个新的 spring-websocket 模块提供了全面的基于 WebSocket 和在Web 应用的客户端和服务器之间双向通信的支持。它和 Java WebSocket API JSR-356 兼容,此外还提供了当浏览器不支持 WebSocket 协议时 (如 Internet Explorer < 10)的基于SockJS 的备用选项(如 WebSocket emulation)。

一个新的spring-messaging模块添加了支持 STOMP 作为 WebSocket 子协议用于在应用中使用注解编程模型路由和处理从 WebSocket 客户端发送的 STOMP 消息。由于@Controller现在可以同时包含@RequestMapping@MessageMapping方法用于处理 HTTP 请求和来自 WebSocket 连接客户端发送的消息。新的spring-messaging模块还包含了来自以前 Spring 集成项目的关键抽象,例如MessageMessageChannelMessageHandler和其他作为基于消息传递的应用程序的基础。

欲知详情以及较全面的介绍,请参见Chapter 20, WebSocket 支持一节。

测试改进

除了精简spring-test模块中过时的代码外,Spring 4 还引入了几个用于单元测试和集成测试的新功能。

  • 几乎 spring-test模块中所有的注解(例如:@ContextConfiguration@WebAppConfiguration@ContextHierarchy@ActiveProfiles等等)现在可以用作元注解来创建自定义的 composed annotations 并且可以减少测试套件的配置。
  • 现在可以以编程方式解决Bean定义配置文件的激活。只需要实现一个自定义的ActiveProfilesResolver,并且通过@ActiveProfiles的resolver属性注册。
  • 新的 SocketUtils 类被引入到了spring-core模块。这个类可以使你能够扫描本地主机的空闲的 TCP 和 UDP 服务端口。这个功能不是专门用在测试的,但是可以证明在你使用 Socket 写集成测试的时候非常有用。例如测试内存中启动的SMTP服务器,FTP服务器,Servlet容器等。
  • 从 Spring 4.0 开始,org.springframework.mock.web包中的一套mock是基于Servlet 3.0 API。此外,一些Servlet API mocks(例如:MockHttpServletRequestMockServletContext等等)已经有一些小的改进更新,提高了可配置性。

JMS 改进

Spring 4.1 引入了一个更简单的基础架构,使用 @JmsListener注解bean 方法来注册 JMS 监听端点。XML 命名空间已经通过增强来支持这种新的方式(jms:annotation-driven),它也可以完全通过Java配置(@EnableJmsJmsListenerContainerFactory)来配置架构。也可以使用 JmsListenerConfigurer注解来注册监听端点。

Spring 4.1 还调整了 JMS 的支持,使得你可以从spring-messaging在 Spring4.0 引入的抽象获益,即:

  • 消息监听端点可以有更为灵活的签名,并且可以从标准的消息注解获益,例如@Payload@Header@Headers和@SendTo注解。另外,也可以使用一个标准的消息,以代替javax.jms.Message作为方法参数。
  • 一个新的可用 JmsMessageOperations接口和允许操作使用Message抽象的JmsTemplate

最后,Spring 4.1提供了其他各种各样的改进:

  • JmsTemplate中的同步请求-答复操作支持
  • 监听器的优先权可以指定每个<jms:listener/>元素
  • 消息侦听器容器恢复选项可以通过使用 BackOff 实现进行配置
  • JMS 2.0消费者支持共享

缓存改进

Spring 4.1 支持JCache (JSR-107)注解使用Spring的现有缓存配置和基础结构的抽象;使用标准注解不需要任何更改。

Spring 4.1也大大提高了自己的缓存抽象:

  • 缓存可以在运行时使用CacheResolver解决。因此使用value参数定义的缓存名称不在是强制性的。
  • 更多的操作级自定义项:缓存解析器,缓存管理器,键值生成器
  • 一个新的@CacheConfig类级别注解允许在类级别上共享常用配置,不需要启用任何缓存操作。
  • 使用CacheErrorHandler更好的处理缓存方法的异常

Spring 4.1为了在CacheInterface添加一个新的putIfAbsent方法也做了重大的更改。

Web 改进

  • 现有的基于ResourceHttpRequestHandler的资源处理已经扩展了新的抽象ResourceResolverResourceTransformerResourceUrlProvider。一些内置的实现提供了版本控制资源的 URL(有效的 HTTP 缓存),定位 gzip 压缩的资源,产生 HTML5 AppCache清单,以及更多的支持。参见第17.16.7,“Serving of Resources(服务资源)”。
  • JDK 1.8 的java.util.Optional现在支持@RequestParam@RequestHeader@MatrixVariable控制器方法的参数。
  • ListenableFuture支持作为返回值替代DeferredResult所在的底层服务(或者调用AsyncRestTemplate)已经返回ListenableFuture
  • @ModelAttribute方法现在依照相互依存关系的顺序调用。见SPR-6299。
  • Jackson的@JsonView被直接支撑在@ResponseBodyResponseEntity控制器方法用于序列化不同的细节对于相同的 POJO(如摘要与细节页)。同时通过添加序列化视图类型作为模型属性的特殊键来支持基于视图的渲染。见Jackson Serialization View Support(Jackson序列化视图支持)
  • Jackson 现在支持 JSONP ,见 Jackson JSONP Support
  • 一个新的生命周期选项可用于在控制方法返回后,响应被写入之前拦截@ResponseBodyResponseEntity方法。要充分利用声明@ControllerAdvice bean 实现ResponseBodyAdvice。为@JsonView和 JSONP 的内置支持利用这一优势。参见第17.4.1,“使用HandlerInterceptor 拦截请求”。
  • 有三个新的HttpMessageConverter选项:
    • GSON - 比 Jackson 更轻量级的封装;已经被使用在 Spring Android
    • Google Protocol Buffers - 高效和有效的企业内部跨业务的数据通信协议,但也可以用于浏览器的 JSON 和 XML 的扩展
    • Jackson 基于 XML 序列化,现在通过 jackson-dataformat-xml 扩展得到了支持。如果 jackson-dataformat-xml 在 classpath, 默认情况下使用@EnableWebMvc<mvc:annotation-driven/>,这是,而不是JAXB2。
  • 如 JSP 等视图现在可以通过名称参照控制器映射建立链接控制器。默认名称分配给每一个@RequestMapping。例如FooController的方法与handleFoo被命名为“FC#handleFoo”。命名策略是可插拔的。另外,也可以通过其名称属性明确命名的@RequestMapping。在Spring JSP标签库的新mvcUrl功能使这个简单的JSP页面中使用。参见第17.7.2,“Building URIs to Controllers and methods from views”
  • ResponseEntity提供了一种 builder 风格的 API 来指导控制器向服务器端的响应的展示,例如,ResponseEntity.ok()。
  • RequestEntity 是一种新型的,提供了一个 builder 风格的 API 来引导客户端的 REST 响应 HTTP 请求的展示。
  • MVC 的 Java 配置和 XML 命名空间:
    • 视图解析器现在可以配置包括内容协商的支持,请参见17.16.6“视图解析”。
    • 视图控制器现在已经内置支持重定向和设置响应状态。应用程序可以使用它来配置重定向的URL,404 视图的响应,发送“no content”的响应,等等。有些用例这里列出。
    • 现在内置路径匹配的自定义。参见第17.16.9,“路径匹配”。
  • Groovy 的标记模板支持(基于Groovy的2.3)。见GroovyMarkupConfigurer 和各自的ViewResolver和“视图”的实现。

WebSocket STOMP 消息 改进

  • SockJS(Java)客户端支持.查看 SockJsClient 和在相同包下的其他类.
  • 发布新的应用上下文实践 SessionSubscribeEvent 和 SessionUnsubscribeEvent, 用于STOMP客户端的订阅和取消订阅.
  • 新的"websocket"级别.查看 Section 25.4.14, “WebSocket Scope”.
  • @SendToUser 仅仅靠一个会话就可以命中, 而不一定需要一个授权的用户.
  • @MessageMapping 方法使用 . 来代替 / 作为目录分隔符。查看 SPR-11660.。
  • STOMP/WebSocket 监听消息的收集和记录。查看25.4.16, “Runtime Monitoring”.。
  • 显著优化和改善在调试模式下依然保持日志的可读性和简洁性。
  • 优化消息创建,包含对临时消息可变性的支持和避免自动消息ID和时间戳的创建。查看MessageHeaderAccessor 的java文档。
  • 在WebSocket会话建立之后的1分钟没有任何活动,则关闭STOMP/WebSocket连接。

测试改进

  • Groovy脚本现在能使用ApplicationContext配置,在TestContext框架中整合测试。the section called “Context configuration with Groovy scripts”
  • 现在通过新的TestTransaction接口,使用编程化来开始结束测试管理事务。the section called “Programmatic transaction management”
  • 现在SQL脚本的执行可以通过SqlSqlConfig注解申明在每一个类和方法中。the section called “Executing SQL scripts”
  • 测试属性值可以通过配置@TestPropertySource注解来自动覆盖系统和应用的属性值。the section called “Context configuration with test property sources”。
  • 默认的TestExecutionListeners现在可以自动被发现。the section called “Automatic discovery of default TestExecutionListeners” 。
  • 自定义的TestExecutionListeners现在可以通过默认的监听器自动合并。the section called “Merging TestExecutionListeners”。
  • 在TestContext框架中的测试事务方面的文档已经通过更多解释和其他事例得到改善。the section called “Transaction management”。
  • MockServletContextMockHttpServletRequest和其他servlet接口mocks等诸多改善。
  • AssertThrows重构后,Throwable代替Exception
  • Spring MVC测试中,使用JSONPath选项返回JSON格式可以使用JSON Assert来断言,非常像之前的XML和XMLUnit。
  • MockMvcBuilder现在可以在MockMvcConfigurer的帮助下创建。MockMvcConfigurer的加入使得Spring Security的设置更加简单,同时使用于任何第三方的普通封装设置或则仅仅在本项目中。
  • MockRestServiceServer现在支持AsyncRestTemplate作为客户端测试。
  • 发布新的应用上下文实践SessionSubscribeEvent和 SessionUnsubscribeEvent,用于STOMP客户端的订阅和取消订阅.
  • 新的"websocket"级别.查看[Section 21.4.13, “WebSocket Scope”.](http://docs.spring.io/spring/docs/current/spring-framework-

核心容器改进

  • 如 @bean 注释,就如同得到发现和处理 Java 8 默认方法一样,可以允许组合配置类与默认@bean 接口方法。
  • 配置类现在可以声明 @import 作为常规组件类,允许引入的配置类和组件类进行混合。
  • 配置类可以声明一个 @Order 值,用来得到相应的处理顺序(例如重写 bean 的名字),即使通过类路径扫描检测。
  • @Resource 注入点支持 @Lazy 声明,类似于 @autowired, 用于接收用于请求目标 bean 的懒初始化代理。
  • 现在的应用程序事件基础架构提供了一个基于注解的模型以及发布任意事件的能力。
    • 任何受管 bean 的公共方法使用 @EventListener 注解来消费事件。
    • @TransactionalEventListener 提供事务绑定事件支持。
  • Spring Framework 4.2引入了一流的支持声明和查找注释属性的别名。新 @AliasFor 注解可用于声明一双别名属性在一个注释中或从一个属性在一个声明一个别名定义注解在元注释一个属性组成。
    • 下面的注解已加了 @AliasFor 为了支持提供更有意义的 value 属性的别名: @Cacheable, @CacheEvict, @CachePut, @ComponentScan, @ComponentScan.Filter, @ImportResource, @Scope, @ManagedResource, @Header, @Payload, @SendToUser, @ActiveProfiles, @ContextConfiguration, @Sql, @TestExecutionListeners, @TestPropertySource, @Transactional, @ControllerAdvice, @CookieValue, @CrossOrigin, @MatrixVariable, @RequestHeader, @RequestMapping, @RequestParam, @RequestPart, @ResponseStatus, @SessionAttributes, @ActionMapping, @RenderMapping, @EventListener, @TransactionalEventListener
    • 例如,spring-test 的 @ContextConfiguration 现在声明如下:
  1. public@interface ContextConfiguration {
  2. @AliasFor("locations")
  3. String[] value() default {};
  4. @AliasFor("value")
  5. String[] locations() default {};
  6. // ...
  7. }
  1. * 同样, 组合注解(composed annotations)从元注解覆盖的属性,现在可以使用 @AliasFor 进行细粒度控制哪些属性是覆盖在一个注释的层次结构。事实上,现在可以声明一个别名给元注释的 value 属性。
  2. * 例如,开发一个组合注解用于一个自定义的属性的覆盖
  1. @ContextConfigurationpublic@interface MyTestConfig {
  2. @AliasFor(annotation = ContextConfiguration.class, attribute = "value")
  3. String[] xmlFiles();
  4. // ...
  5. }
* 
  1. 见 [Spring Annotation Programming Model](http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#annotation-programming-model)
  • 许多改进Spring的搜索算法用于寻找元注解。例如,局部声明组合注解现在喜欢继承注解。
  • 从元注解覆盖属性的组合注解,可以被发现在接口和 abstract, bridge, & interface 方法就像在类,标准方法,构造函数,和字段。
  • Map 表示的注解属性(和 AnnotationAttributes 实例)可以 synthesized (合成,即转换)成一个注解。
  • 基于字段的数据绑定的特点(DirectFieldAccessor)与当前的基于属性的数据绑定关联(BeanWrapper)。特别是,基于字段的绑定现在支持集合,数组和 Map 的导航。
  • DefaultConversionService 现在提供开箱即用的转化器给 Stream, Charset, Currency, 和 TimeZone. 这些转换器可以独立的添加到任何 ConversionService
  • DefaultFormattingConversionService 提供开箱即用的支持 JSR-354 的 Money & Currency 类型 (前提是 'javax.money' API 出现在 classpath): 这些被命名为 MonetaryAmount 和 CurrencyUnit。支持使用 @NumberFormat
  • @NumberFormat 现在作为元注解使用
  • JavaMailSenderImpl 中新的 testConnection() 方法用于检查与服务器的连接
  • ScheduledTaskRegistrar 用于暴露调度的任务
  • Apache commons-pool2 现在支持用于 AOP CommonsPool2TargetSource 的池化
  • 引入 StandardScriptFactory 作为脚本化 bean 的 JSR-223 的基本机制,通过 XML 中的 lang:std 元素暴露。支持如 JavaScript 和 JRuby。(注意:JRubyScriptFactory 和 lang:jruby现在不推荐使用了 , 推荐用 JSR-223)

数据访问改进

  • javax.transaction.Transactional 现在可以通过 AspectJ 支持
  • SimpleJdbcCallOperations 现在支持命名绑定
  • 完全支持 Hibernate ORM 5.0: 作为 JPA 供应商 (自动适配)和原生的 API 一样 (在新的 org.springframework.orm.hibernate5 包中涵盖了该内容)
  • 嵌入式数据库可以自动关联唯一名字,并且 <jdbc:embedded-database> 支持新的 database-name 属性。见下面“测试改进”内容

JMS 改进

  • autoStartup 属性可以通过 JmsListenerContainerFactory 进行控制
  • 应答类型 Destination 可以配置在每个监听器容器
  • @SendTo 的值可以用 SpEL 表达式
  • 响应目的地可以通过 JmsResponse 在运行时计算
  • @JmsListener 是可以可以重复的注解用于声明多个 JMS 容器在相同的方法上 (若你还没有用上 Java8 请使用新引入的 @JmsListeners)。

Web 改进

  • 支持 HTTP Streaming 和 Server-Sent Events , se见 “HTTP Streaming”
  • 内建支持 CORS ,包括全局 (MVC Java 配置和 XML 命名空间) 和本地 (如 @CrossOrigin) 配置。见 26 章, CORS 支持
  • HTTP 缓存升级
    • 新的 CacheControl 构建器; 插入 ResponseEntity, WebContentGenerator, ResourceHttpRequestHandler
    • 改进的 ETag/Last-Modified 在 WebRequest 中支持
  • 自定义映射注解使用 @RequestMapping 作为 元数据注解
  • AbstractHandlerMethodMapping 中的 public 方法用于运行时注册和注销请求映射
  • AbstractDispatcherServletInitializer 中的 Protected createDispatcherServlet 方法用来进一步自定义 DispatcherServlet 实例
  • HandlerMethod 作为 @ExceptionHandler方法的方法参数,特别是方便 @ControllerAdvice 组件
  • java.util.concurrent.CompletableFuture 作为 @Controller 方法返回值类型
  • 字节范围(Byte-range)的请求支持在 HttpHeaders,用于静态资源
  • @ResponseStatus 发现嵌套异常。
  • 在 RestTemplate 中的 UriTemplateHandler 扩展端点
    • DefaultUriTemplateHandler 暴露 baseUrl 属性和路径段的编码选项
    • 扩展端点可以使用插入任何 URI 模板库
  • OkHTTP 与 RestTemplate 集成
  • 自定义 baseUrl 在 MvcUriComponentsBuilder 选择方法。
  • 序列化/反序列化异常消息现在记录为 WARN 级别
  • 默认的 JSON 前缀改变了从{}&&改为更安全的)]}’,
  • 新的 RequestBodyAdvice 扩展点和内置的实现支持 Jackson 的 在 @RequestBody 的 @JsonView
  • 当使用 GSON 或 Jackson 2.6 +,处理程序方法的返回类型是用于提高参数化类型的序列化,比如List<Foo>
  • 引入的 ScriptTemplateView 作为 JSR-223 的脚本化 web 视图机制为基础,关注 JavaScript 视图模板 Nashorn (JDK 8)。

WebSocket 消息改进

  • 暴露展示信息关于用户的连接和订阅:
    • 新 SimpUserRegistry 公开为一个名为“userRegistry”的bean。
    • 共享在服务器集群的展示信息(见代理中继配置选项)
  • 解决用户目的地在集群的服务器(见代理中继配置选项)。
  • StompSubProtocolErrorHandler 扩展端点用来自定义和控制 STOMP ERROR 帧给用户
  • 全局 @MessageExceptionHandler 方法通过 @ControllerAdvice 组件
  • 心跳和 SpEL 表达式'selector'头用 SimpleBrokerMessageHandler 订阅
  • STOMP 客户端使用TCP 和 WebSocket; 见 25.4.13, “STOMP 客户端”
  • @SendTo 和 @SendToUser 可以包含目标变量的占位符。 Jackson 的 @JsonView 支持 @MessageMapping 和 @SubscribeMapping 方法返回值
  • ListenableFuture 和 CompletableFuture 是从 @MessageMapping 和 @SubscribeMapping 方法返回类型值
  • MarshallingMessageConverter 用于 XML 有效载荷

测试改进

  • 基于 JUnit 集成测试现在可以执行 JUnit 规则而不是SpringJUnit4ClassRunner。这允许基于 spring 的集成测试与运行JUnit 的 Parameterized 或第三方 运行器 MockitoJUnitRunner 等。详见 Spring JUnit 规则
  • Spring MVC Test 框架,现在支持第一类 HtmlUnit,包括集成 Selenium’s WebDriver,允许基于页面的 Web 应用测试而无需部署到 Servlet 容器。详见 14.6.2, “HtmlUnit 集成”
  • AopTestUtils 是一个新的测试工具,允许开发者获得潜在的目标对象的引用隐藏在一个或多个 Spring 代理。详见 13.2.1, “常见测试工具”
  • ReflectionTestUtils 现在支持 setting 和 getting static 字段,包括常量
  • bean 定义归档文件的原始顺序,通过 @ActiveProfiles 声明,现在保留为了支持用例,如 Spring 的 ConfigFileApplicationListener 引导加载配置文件基于活动归档文件的名称。
  • @DirtiesContext 支持新 BEFORE_METHOD BEFORE_CLASS,BEFORE_EACH_TEST_METHOD 模式,用于测试之前关闭ApplicationContext——例如,如果一些烦人的(即,有待确定)测试在一个大型测试套件的 ApplicationContext 的原始配置已经损坏。
  • @Commit 是新的注解直接可以用来代替 @Rollback(false)
  • @Rollback 用来配置类级别的默认回滚语义
    • 因此,现在 @TransactionConfiguration 弃用,在后续版本将被删除。
  • @Sql 现在支持内联 SQL 语句的执行通过一个新的 statements 属性
  • ContextCache 用于缓存测试之间的 ApplicationContext,而现在这是一个公开的 API ,默认的实现可以替代自定义的缓存需求
  • DefaultTestContext, DefaultBootstrapContext, 和 DefaultCacheAwareContextLoaderDelegate 现在是公开的类,支持子包,允许自定义扩展
  • TestContextBootstrapper 现在负责构建 TestContext
  • 在 Spring MVC Test 框架,MvcResult 详情可以被日志记录在 DEBUG 级别或者写入自定义的 OutputStream 或 Writer。详见 log(), print(OutputStream), 和 MockMvcResultHandlers 的 print(Writer) 方法
  • JDBC XML名称空间支持一个新的 <jdbc:embedded-database> 的 database-name 属性,允许开发人员为嵌入式数据库设置独特的名字——例如,通过一个 SpEL 表达式或 前活动bean定义配置文件所影响的占位符属性
  • 嵌入式数据库现在可以自动分配一个唯一的名称,允许常用的测试数据库配置在不同的 ApplicationContext 的测试套件中。 参见18.8.6“给嵌入式数据库生成惟一名称”的细节。

 

来源:https://blog.csdn.net/z1049186181/article/details/51446643