搜索词>>md5加密 耗时0.0630
  • jQuery之MD5加密插件使用及下载

    jQuery之MD5加密插件使用及下载,网络中md5进行简单加密的地方越来越多。这里讲解一个jQuery的md5插件jQuery之MD5加密插件使用及下载,网络中md5进行简单加密的地方越来越多。这里讲解一个jQuery的md5插件<br /> <br /> 首先准备工作:<br /> 1.下载jQuery<br /> 2.下载md5插件,<a href="http://www.leftso.com/resources/framework/jquery/plugins/md5/jQuery.md5.js" rel="nofollow" target="_blank">点击下载jQueryMD5插件</a><br /> <br /> 引入工具类: <pre> <code class="language-javascript"><script type="text/javascript" src="../libs/jQuery/jquery.js"></script> <script type="text/javascript" src="../libs/jQuery/plugins/md5/jQuery.md5.js"></script></code></pre> <br /> 使用方法: <pre> <code class="language-xml"><!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>MD5 demo</title> <script type="text/javascript" src="../libs/jQuery/jquery.js"></script> <script type="text/javascript" src="../libs/jQuery/plugins/md5/jQuery.md5.js"></script> </head> <body> <script type="text/javascript"> function getMD5Value (value) { var md5Str=$.md5(value); return md5Str; } </script> </body> </html></code></pre> <br /> 欢迎使用本站MD5在线加密工具,地址:<br /> <a rel="nofollow" href="http://www.leftso.com/tools/md5.html" target="_blank">http://www.leftso.com/tools/md5.html</a><br /> <img alt="欢迎使用本站MD5在线加密工具" class="img-thumbnail" src="/assist/images/blog/7e00155bcd394864b3cd6eeb4a070560.png" />
  • java语言MD5加密字符串,计算文件的MD5值

    java语言MD5加密字符串,计算文件的MD5值 <pre> <code class="language-java">package org.xqlee.utils.security; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.math.BigInteger; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; /** * * * <pre> * _________________________INFO_____________________________ * Description : [MD5加密工具类] * Encoding : [UTF-8] * Package : [org.xqlee.utils.md5] * Project : [utils] * Author : [] * CreateDate : [] * Updater : [] * UpdateDate : [] * UpdateRemark: [] * Company : [Shallink Electronic Information] * Version : [v 1.0] * __________________________________________________________ * </pre> */ public class MD5Util { /** * 加密一个输入字符串 * * @param visibleString * 输入一个可见的明码<br> * 类型:java.lang.String * @return 一个加密后的MD5值<br> * 通常用于密码加密 * @throws NoSuchAlgorithmException */ public static String getEnMD5String(String visibleString) throws NoSuchAlgorithmException { MessageDigest md5; // 生成一个MD5加密计算摘要 md5 = MessageDigest.getInstance("MD5"); // 计算md5函数 md5.update(visibleString.getBytes()); // digest()最后确定返回md5 hash值,返回值为8为字符串。因为md5 hash值是16位的hex值,实际上就是8位的字符 // BigInteger函数则将8位的字符串转换成16位hex值,用字符串来表示;得到字符串形式的 值 String pwdStr = new BigInteger(1, md5.digest()).toString(16); return pwdStr; } /** * 计算文件MD5值 * * @param file * 输入一个文件参数<br> * 类型:java.io.File * @return 该文件的MD5值<br> * 类型:java.lang.String * @throws IOException * IO异常 * @throws NoSuchAlgorithmException * MD5获取实例异常 */ public static String getMd5ForFile(File file) throws IOException, NoSuchAlgorithmException { FileInputStream in = null; in = new FileInputStream(file); MessageDigest md5 = MessageDigest.getInstance("MD5"); byte[] cache = new byte[2048]; int len; while ((len = in.read(cache)) != -1) { md5.update(cache, 0, len); } in.close(); BigInteger bigInt = new BigInteger(1, md5.digest()); return bigInt.toString(16); } } </code></pre>
  • java c++通用DES/AES对称加密算法(包含源代码)

    java c++通用DES加密算法(包含源代码),本来觉得DES、AES这种流行加密算法,使用起来应该很简单。但研究后发现有两个变数:1分块的方式。加密是逐块进行的。2.padding的方式。当数据的位数不及块的大小时,需要填充。<h2>一说明</h2> 本来觉得DES、AES这种流行加密算法,使用起来应该很简单。但研究后发现有两个变数: <ul> <li>分块的方式。加密是逐块进行的。分块方法有:CBC、ECB、CFB……</li> <li>padding的方式。当数据的位数不及块的大小时,需要填充。填充方式有:NoPadding、PKCS5Padding……</li> </ul> 如果加解密端采用不同的分块方式或padding方式,即使都是采用DES/AES算法,同样无法解密成功。上次需要C端和Java端进行密文传输,就跪在这一点上(那时候没时间研究)。<br /> 参考文章:<a href="http://my.oschina.net/u/267094/blog/174035" rel="external nofollow" target="_blank">Java AES算法和openssl配对</a> ,主要通过其了解openssl里比较高级的EVP系列API(其默认padding和java一样都是PKCS5Padding),节约了搜索时间。<br /> 贴代码了,以下代码测试通过了。Java和C++均可以正确解密对方的密文。<br /> 约定:分块和padding采用Java默认的 ECB + PKCS5Padding。 <h2>二 DES加解密</h2> <h3>Java端DES加解密</h3> <pre> <code class="language-java">import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; public class DESUtil { /** 默认算法格式 **/ static String default_transformation = "DES/ECB/PKCS5Padding"; /** * 根据key获取加密器 * * @param keyData * key 8byte * @return 加密器 * @throws Exception * 异常 */ private static Cipher getEncryptCipher(byte[] keyData) throws Exception { if (keyData.length != 8) { throw new Exception("Key Data Must 8 byte!"); } SecretKeySpec key = new SecretKeySpec(keyData, "DES"); // 指定分块ECB模式,填充PKCS5Padding模式 Cipher encryptCipher = Cipher.getInstance(default_transformation); // 初始化加密的容器 encryptCipher.init(Cipher.ENCRYPT_MODE, key); return encryptCipher; } /** * 根据key获取解码器 * * @return 解码器 * @throws Exception * 异常 */ private static Cipher getDecryptCipher(byte[] keyData) throws Exception { if (keyData.length != 8) { throw new Exception("Key Data Must 8 byte!"); } SecretKeySpec key = new SecretKeySpec(keyData, "DES"); Cipher decryptCipher = Cipher.getInstance(default_transformation); // 初始化解密的容器 decryptCipher.init(Cipher.DECRYPT_MODE, key); return decryptCipher; } /** * DES加密 * * @param data * 待加密数据 * @param keyData * key值 * @return 加密后的数据 * @throws Exception * 异常 */ public static byte[] encrypt(byte[] data, byte[] keyData) throws Exception { return getEncryptCipher(keyData).doFinal(data); } /** * DES解密 * * @param data * 加密后的数据 * * @param keyData * key值 * @return 解密数据 * @throws Exception * 异常 */ public static byte[] decrypt(byte[] data, byte[] keyData) throws Exception { return getDecryptCipher(keyData).doFinal(data); } /** * 测试 * * @param args */ public static void main(String[] args) { try { byte[] data = "测试123456".getBytes(); byte[] keyData = "12345678".getBytes(); System.out.println("原文:" + new String(data)); byte[] enData = encrypt(data, keyData); System.out.println("加密后:" + new String(enData)); byte[] deData = decrypt(enData, keyData); System.out.println("解密后:" + new String(deData)); } catch (Exception e) { e.printStackTrace(); } } } </code></pre> <strong><span style="color:#27ae60">说明:Java必须指定填充模式和padding模式。DES/ECB/PKCS5Padding,好与C++同步</span></strong><br /> 测试执行结果: <pre> <code class="language-html">原文:测试123456 加密后:�a���O���?I�]�Y 解密后:测试123456</code></pre> <h3>C++端DES加解密</h3> c++DES加密代码 <pre> <code class="language-cpp">#include <string> #include <iostream> #include <stdio.h> #include <assert.h> #include <openssl/objects.h> #include <openssl/evp.h> // 注意:参数和返回值全部是二进制数据 std::string desEncrypt(const std::string& source, const std::string& key) {     EVP_CIPHER_CTX ctx;     EVP_CIPHER_CTX_init(&ctx);     int ret = EVP_EncryptInit_ex(&ctx, EVP_des_ecb(), NULL, (const unsigned char*)key.data(), NULL);     assert(ret == 1);     unsigned char* result = new unsigned char[source.length() + 64]; // 弄个足够大的空间     int len1 = 0;     ret = EVP_EncryptUpdate(&ctx, result, &len1, (const unsigned char*)source.data(), source.length());     assert(ret == 1);     int len2 = 0;     ret = EVP_EncryptFinal_ex(&ctx, result+len1, &len2);      assert(ret == 1);     std::cout << len1 << "," << len2 << std::endl;     ret = EVP_CIPHER_CTX_cleanup(&ctx);     assert(ret == 1);     std::string res((char*)result, len1+len2);     delete[] result;     return res; } int main() {     std::string key("hellodes", 8);    // 二进制数据,而不是以0结尾的字符串     // 读取文件内容(简单起见认为文件内容<100K)     char buf[1024*100];     FILE* fp = fopen("src.txt", "rb");     int bytes = fread(buf, 1, 1024*100, fp);     fclose(fp);     std::string source(buf, bytes); // 二进制数据     // 加密     std::string enc = desEncrypt(source, key);     std::cout << "desEncrypt:" << source.length() << "->" << enc.length() << std::endl;     // 输出到文件     fp =  fopen("enc.bin", "wb");     fwrite(enc.data(), 1, enc.length(), fp);     fclose(fp); }</code></pre> c++DES解密 <pre> <code class="language-cpp">#include <string> #include <iostream> #include <stdio.h> #include <assert.h> #include <openssl/objects.h> #include <openssl/evp.h> // 注意:参数和返回值全部是二进制数据 std::string desDecrypt(const std::string& ciphertext, const std::string& key) {     EVP_CIPHER_CTX ctx;     EVP_CIPHER_CTX_init(&ctx);     int ret = EVP_DecryptInit_ex(&ctx, EVP_des_ecb(), NULL, (const unsigned char*)key.data(), NULL);     assert(ret == 1);     unsigned char* result = new unsigned char[ciphertext.length() + 64]; // 弄个足够大的空间     int len1 = 0;     ret = EVP_DecryptUpdate(&ctx, result, &len1, (const unsigned char*)ciphertext.data(), ciphertext.length());     assert(ret == 1);     int len2 = 0;     ret = EVP_DecryptFinal_ex(&ctx, result+len1, &len2);      assert(ret == 1);     std::cout << len1 << "," << len2 << std::endl;     ret = EVP_CIPHER_CTX_cleanup(&ctx);     assert(ret == 1);     std::string res((char*)result, len1+len2);     delete[] result;     return res; } int main() {     std::string key("hellodes", 8);    // 二进制数据,而不是以0结尾的字符串     // 读取文件内容(简单起见认为文件内容<100K)     char buf[1024*100];     FILE* fp = fopen("enc.bin", "rb");     int bytes = fread(buf, 1, 1024*100, fp);     fclose(fp);     std::string data(buf, bytes); // 二进制数据     // 加密     std::string dec = desDecrypt(data, key);     std::cout << "desDecrypt:" << data.length() << "->" << dec.length() << std::endl;     // 输出到文件     fp =  fopen("dec.txt", "wb");     fwrite(dec.data(), 1, dec.length(), fp);     fclose(fp); }</code></pre> <br /> 说明:DES、AES加密算法都是针对数据块,Java加解密函数参数使用byte数组。C++用std::string,那是因为这是C++中使用byte数组的最简单方式(std::string可以存储二进制数据,很多人没想到吧),缺点是拷贝内存的次数可能会略多些。如果想要优化拷贝效率,可以使用自己封装的Buffer类来代替std::string。 <h2>三 AES加解密</h2> <h3>Java端AES加解密</h3> <pre> <code class="language-java">import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; /** * DES加解密算法工具类 * * @author xqlee * */ public class AESUtil { /** 默认算法格式 **/ static String default_transformation = "AES/ECB/PKCS5Padding"; /** * 根据key获取加密器 * * @param keyData * key 8byte * @return 加密器 * @throws Exception * 异常 */ private static Cipher getEncryptCipher(byte[] keyData) throws Exception { if (keyData.length != 16) { throw new Exception("Key Data Must 8 byte!"); } SecretKeySpec key = new SecretKeySpec(keyData, "AES"); // 指定分块ECB模式,填充PKCS5Padding模式 Cipher encryptCipher = Cipher.getInstance(default_transformation); // 初始化加密的容器 encryptCipher.init(Cipher.ENCRYPT_MODE, key); return encryptCipher; } /** * 根据key获取解码器 * * @return 解码器 * @throws Exception * 异常 */ private static Cipher getDecryptCipher(byte[] keyData) throws Exception { if (keyData.length != 16) { throw new Exception("Key Data Must 8 byte!"); } SecretKeySpec key = new SecretKeySpec(keyData, "AES"); Cipher decryptCipher = Cipher.getInstance(default_transformation); // 初始化解密的容器 decryptCipher.init(Cipher.DECRYPT_MODE, key); return decryptCipher; } /** * AES加密 * * @param data * 待加密数据 * @param keyData * key值 * @return 加密后的数据 * @throws Exception * 异常 */ public static byte[] encrypt(byte[] data, byte[] keyData) throws Exception { return getEncryptCipher(keyData).doFinal(data); } /** * AES解密 * * @param data * 加密后的数据 * * @param keyData * key值 * @return 解密数据 * @throws Exception * 异常 */ public static byte[] decrypt(byte[] data, byte[] keyData) throws Exception { return getDecryptCipher(keyData).doFinal(data); } /** * 测试 * * @param args */ public static void main(String[] args) { try { byte[] data = "测试123456".getBytes(); byte[] keyData = "1234567887654321".getBytes(); System.out.println("原文:" + new String(data)); byte[] enData = encrypt(data, keyData); System.out.println("加密后:" + new String(enData)); byte[] deData = decrypt(enData, keyData); System.out.println("解密后:" + new String(deData)); } catch (Exception e) { e.printStackTrace(); } } } </code></pre> <h3>C++端AES加解密</h3> 加密: <pre> <code class="language-cpp">#include <string> #include <iostream> #include <stdio.h> #include <assert.h> #include <openssl/objects.h> #include <openssl/evp.h> // 注意:参数和返回值全部是二进制数据 std::string aesEncrypt(const std::string& source, const std::string& key) {     EVP_CIPHER_CTX ctx;     EVP_CIPHER_CTX_init(&ctx);     int ret = EVP_EncryptInit_ex(&ctx, EVP_aes_128_ecb(), NULL, (const unsigned char*)key.data(), NULL);     assert(ret == 1);     unsigned char* result = new unsigned char[source.length() + 64]; // 弄个足够大的空间     int len1 = 0;     ret = EVP_EncryptUpdate(&ctx, result, &len1, (const unsigned char*)source.data(), source.length());     assert(ret == 1);     int len2 = 0;     ret = EVP_EncryptFinal_ex(&ctx, result+len1, &len2);      assert(ret == 1);     std::cout << len1 << "," << len2 << std::endl;     ret = EVP_CIPHER_CTX_cleanup(&ctx);     assert(ret == 1);     std::string res((char*)result, len1+len2);     delete[] result;     return res; } int main() {     std::string key("helloaeshelloaes", 16);    // 二进制数据,而不是以0结尾的字符串     // 读取文件内容(简单起见认为文件内容<100K)     char buf[1024*100];     FILE* fp = fopen("src.txt", "rb");     int bytes = fread(buf, 1, 1024*100, fp);     fclose(fp);     std::string source(buf, bytes); // 二进制数据     // 加密     std::string enc = aesEncrypt(source, key);     std::cout << "aesEncrypt:" << source.length() << "->" << enc.length() << std::endl;     // 输出到文件     fp =  fopen("enc.bin", "wb");     fwrite(enc.data(), 1, enc.length(), fp);     fclose(fp); }</code></pre> 解密: <pre> <code class="language-cpp">#include <string> #include <iostream> #include <stdio.h> #include <assert.h> #include <openssl/objects.h> #include <openssl/evp.h> // 注意:参数和返回值全部是二进制数据 std::string aesDecrypt(const std::string& ciphertext, const std::string& key) {     EVP_CIPHER_CTX ctx;     EVP_CIPHER_CTX_init(&ctx);     int ret = EVP_DecryptInit_ex(&ctx, EVP_aes_128_ecb(), NULL, (const unsigned char*)key.data(), NULL);     assert(ret == 1);     unsigned char* result = new unsigned char[ciphertext.length() + 64]; // 弄个足够大的空间     int len1 = 0;     ret = EVP_DecryptUpdate(&ctx, result, &len1, (const unsigned char*)ciphertext.data(), ciphertext.length());     assert(ret == 1);     int len2 = 0;     ret = EVP_DecryptFinal_ex(&ctx, result+len1, &len2);      assert(ret == 1);     std::cout << len1 << "," << len2 << std::endl;     ret = EVP_CIPHER_CTX_cleanup(&ctx);     assert(ret == 1);     std::string res((char*)result, len1+len2);     delete[] result;     return res; } int main() {     std::string key("helloaeshelloaes", 16);    // 二进制数据,而不是以0结尾的字符串     // 读取文件内容(简单起见认为文件内容<100K)     char buf[1024*100];     FILE* fp = fopen("enc.bin", "rb");     int bytes = fread(buf, 1, 1024*100, fp);     fclose(fp);     std::string data(buf, bytes); // 二进制数据     // 加密     std::string dec = aesDecrypt(data, key);     std::cout << "aesDecrypt:" << data.length() << "->" << dec.length() << std::endl;     // 输出到文件     fp =  fopen("dec.txt", "wb");     fwrite(dec.data(), 1, dec.length(), fp);     fclose(fp); }</code></pre>
  • AES 使用JavaScript加密然后用Java解密

    引言AES代表高级加密系统,它是一种对称加密算法引言AES代表高级加密系统,它是一种对称加密算法。很多时候我们需要在客户端加密一些明文,例如密码,并将其发送到服务器,然后服务器将其解密以进一步处理.AES加密和解密更容易在Android客户端和Java服务器等相同的平台上实现,但有时在跨平台环境(如Javascript客户端和Java Server,如Spring mvc框架)中解密AES加密密码变得非常具有挑战性,因为如果任何系统默认值不匹配解密将失败。    在本文中,我们将使用spring mvc和angular js客户端创建一个应用程序。我们将有一个带有用户名和密码的表单输入的登录页面。在将密码发送到服务器之前,密码将使用CryptoJS在JavaScript中加密,并且相同的加密密码将在java中解密,并且会进行比较以匹配密码。我们将在javascript中生成salt和IV,然后生成从密码,salt和密钥大小中使用PBKDF2函数的密钥。之后,我们将使用密钥和IV对明文进行加密,并且这些密钥将在Java中进行解密。因此,基本上我们将开发一种可与Java进行可互操作的AES加密的机制,的JavaScript。    在继续进行之前,让我们明确一点,该机制仅在数据的有线传输期间(最有可能)增加了一种额外的安全性,但并未提供充分的证明安全性。如果您不使用SSL,则攻击者可以执行中间人攻击并通过为用户提供不同的密钥来窃取数据。项目结构我们这里有个spring  boot和angular js webapp项目。项目结构如下:​JavaScript中的Aes加密    对于JavaScript中的AES加密,我们已经导入了两个js文件 - crypto.js并且pbkdf2.js我们有AesUtil.js用于执行加密和解密的通用代码。这里this.keySize是4字节块的密钥大小。因此,要使用128位密钥,我们将位数除以32得到用于CryptoJS的密钥大小。 AesUtil.js:var AesUtil = function(keySize, iterationCount) { this.keySize = keySize / 32; this.iterationCount = iterationCount; }; AesUtil.prototype.generateKey = function(salt, passPhrase) { var key = CryptoJS.PBKDF2( passPhrase, CryptoJS.enc.Hex.parse(salt), { keySize: this.keySize, iterations: this.iterationCount }); return key; } AesUtil.prototype.encrypt = function(salt, iv, passPhrase, plainText) { var key = this.generateKey(salt, passPhrase); var encrypted = CryptoJS.AES.encrypt( plainText, key, { iv: CryptoJS.enc.Hex.parse(iv) }); return encrypted.ciphertext.toString(CryptoJS.enc.Base64); } AesUtil.prototype.decrypt = function(salt, iv, passPhrase, cipherText) { var key = this.generateKey(salt, passPhrase); var cipherParams = CryptoJS.lib.CipherParams.create({ ciphertext: CryptoJS.enc.Base64.parse(cipherText) }); var decrypted = CryptoJS.AES.decrypt( cipherParams, key, { iv: CryptoJS.enc.Hex.parse(iv) }); return decrypted.toString(CryptoJS.enc.Utf8); }密码加密在JavaScript中    该方法logMeIn()将在点击提交按钮后被调用。此方法将使用定义的通用代码AesUtil.js对密码进行加密并使POST请求验证密码。发送的密码将采用以下格式:iv::salt::ciphertext在服务器端,java将解密密码并在响应中发送解密密码显示在警告框中。var app = angular.module('demoApp', []); app.controller('loginController', ['$scope', '$rootScope', '$http', function ($scope, $rootScope, $http) { $scope.logMeIn = function(){ if(!$scope.userName || !$scope.password){ $scope.showMessage("Missing required fields.", false); return; } var iv = CryptoJS.lib.WordArray.random(128/8).toString(CryptoJS.enc.Hex); var salt = CryptoJS.lib.WordArray.random(128/8).toString(CryptoJS.enc.Hex); var aesUtil = new AesUtil(128, 1000); var ciphertext = aesUtil.encrypt(salt, iv, $('#key').text(), $scope.password); var aesPassword = (iv + "::" + salt + "::" + ciphertext); var password = btoa(aesPassword); var data = { userName: $scope.userName, password: password } $http.post('/login',data).then(function (response){ if(response.status === 200){ alert("Password is " + response.data.password); }else { alert("Error occurred"); } }) }; }]);Java中的AES解密首先让我们实现将拦截登录请求的控制器类。在这里,我们对密钥进行了硬编码。此密钥将由服务器唯一地生成并发送给客户端以用于每个登录请求。客户端将使用相同的密钥,而加密和服务器将使用相同的密钥进行解密。确保密钥长度为16,因为我们使用的是128位加密。请记住我们从客户端发送的加密文本的格式iv::salt::ciphertext。文本以相同的格式解密。我们已经有IV,盐和密文。import com.example.demo.model.Credentials; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletRequest; import java.util.HashMap; import java.util.Map; import java.util.UUID; @Controller public class WelcomeController { private static final Logger LOGGER = LoggerFactory.getLogger(WelcomeController.class); @RequestMapping(value={"/login"},method = RequestMethod.GET) public String loginPage(HttpServletRequest request){ LOGGER.info("Received request for login page with id - " + request.getSession().getId()); String randomKey = UUID.randomUUID().toString(); //String uniqueKey = randomKey.substring(randomKey.length()-17, randomKey.length() -1); String uniqueKey = "1234567891234567"; request.getSession().setAttribute("key", uniqueKey); return "index"; } @RequestMapping(value={"/login"},method = RequestMethod.POST) public @ResponseBody ResponseEntity login(@RequestBody Credentials credentials, HttpServletRequest request) { String decryptedPassword = new String(java.util.Base64.getDecoder().decode(credentials.getPassword())); AesUtil aesUtil = new AesUtil(128, 1000); Map map = new HashMap<>(); if (decryptedPassword != null && decryptedPassword.split("::").length == 3) { LOGGER.info("Password decrypted successfully for username - " + credentials.getUserName()); String password = aesUtil.decrypt(decryptedPassword.split("::")[1], decryptedPassword.split("::")[0], "1234567891234567", decryptedPassword.split("::")[2]); map.put("password", password); } return new ResponseEntity<>(map, HttpStatus.OK); } } 以下是用于AES加密和解密的java util类。您可以按照java中的AES加密和解密获得关于以下实现的更多详细说明。import org.apache.commons.codec.DecoderException; import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Hex; import javax.crypto.*; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.SecretKeySpec; import java.io.UnsupportedEncodingException; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.spec.InvalidKeySpecException; import java.security.spec.KeySpec; public class AesUtil { private final int keySize; private final int iterationCount; private final Cipher cipher; public AesUtil(int keySize, int iterationCount) { this.keySize = keySize; this.iterationCount = iterationCount; try { cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { throw fail(e); } } public String decrypt(String salt, String iv, String passphrase, String ciphertext) { try { SecretKey key = generateKey(salt, passphrase); byte[] decrypted = doFinal(Cipher.DECRYPT_MODE, key, iv, base64(ciphertext)); return new String(decrypted, "UTF-8"); } catch (UnsupportedEncodingException e) { return null; }catch (Exception e){ return null; } } private byte[] doFinal(int encryptMode, SecretKey key, String iv, byte[] bytes) { try { cipher.init(encryptMode, key, new IvParameterSpec(hex(iv))); return cipher.doFinal(bytes); } catch (InvalidKeyException | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException e) { return null; } } private SecretKey generateKey(String salt, String passphrase) { try { SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); KeySpec spec = new PBEKeySpec(passphrase.toCharArray(), hex(salt), iterationCount, keySize); SecretKey key = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES"); return key; } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { return null; } } public static byte[] base64(String str) { return Base64.decodeBase64(str); } public static byte[] hex(String str) { try { return Hex.decodeHex(str.toCharArray()); } catch (DecoderException e) { throw new IllegalStateException(e); } } private IllegalStateException fail(Exception e) { return null; } }测试AES加密和解密     DemoApplication.java作为Java应用程序运行,然后打到http:// localhost:8080。一旦出现登录页面,您可以输入用户名和密码,然后单击提交按钮,您可以在警报中看到解密的密码。​总结在这篇文章中,我们讨论了使用Java和Javascript进行可互操作的AES加密。我们使用Crypto.js库在javascript中执行此加密。提示:项目源码下载aes-encryption-javascript-java-master.zip
  • Spring boot hessian 通讯加密验证

    Spring boot hessian 通讯加密,Spring boot hessian RPC框架通讯之间的加密验证。实现安全的RPC访问<h2>引言</h2>     前面写了一篇<a rel="" target="_blank"href="http://www.leftso.com/blog/294.html" rel="" target="_blank" title="spring boot RPC 框架 Hessian">Spring boot RPC 框架 Hessian</a>。讲解了spring boot整合hessian的基本使用。这里主要围绕上一篇讲解的内容进行扩展讲解,hessian通讯的验证/加密实现安全的RPC访问。 <h2>一.自定义一个HessianServiceExporter</h2>     从上一篇博客<a rel="" target="_blank"href="http://www.leftso.com/blog/294.html" rel="" target="_blank" title="spring boot RPC 框架 Hessian">Spring boot RPC 框架 Hessian</a>中我们可以发现,hessian的server端是通过HessianServiceExporter发布hessian接口服务的。<br />     <br /> 目前hessian的server端项目结构图:<br /> <img alt="项目结构图" class="img-thumbnail" src="/assist/images/blog/4d20852096264d59b39b1dada4f5ba62.png" /><br /> 与上一篇对比,项目结构中多了一个类HessianServerProxyExporter。这个类主要是继承了HessianServiceExporter类并重写了handleRequest方法: <pre> <code class="language-java">package net.xqlee.project; import java.io.IOException; import java.util.Base64; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.remoting.caucho.HessianServiceExporter; import org.springframework.util.StringUtils; import org.springframework.web.util.NestedServletException; /** * 自定义hessian服务发布,可用于自定义验证服务 * * @author xqlee * */ public class HessianServerProxyExporter extends HessianServiceExporter { private static final Logger log = LoggerFactory.getLogger(HessianServerProxyExporter.class); @Override public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String authorization = request.getHeader("authorization"); if (StringUtils.isEmpty(authorization)) { throw new NestedServletException("Auth Is Empty!"); } log.info(authorization); String[] authArr = authorization.trim().split(" "); String auth = authArr[1]; auth = new String(Base64.getDecoder().decode(auth)); String[] namePwdArr = auth.split(":"); String pwd = namePwdArr[1]; // 验证密码 if (!"123456".equals(pwd)) { throw new NestedServletException("Auth Fail!"); } super.handleRequest(request, response); } } </code></pre> 验证的核心代码就在重写的方法里面,这里只是简单的进行了密码的认证。<br /> <br /> 为了使验证生效,我们需要重写类DemoSpringbootRpcHessianApplication: <pre> <code class="language-java">package net.xqlee.project; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import org.springframework.remoting.caucho.HessianServiceExporter; import net.xqlee.project.service.HelloWorldService; @SpringBootApplication public class DemoSpringbootRpcHessianApplication { @Autowired private HelloWorldService helloWorldService; public static void main(String[] args) { SpringApplication.run(DemoSpringbootRpcHessianApplication.class, args); } // 发布服务 @Bean(name = "/HelloWorldService") public HessianServiceExporter accountService() { // HessianServiceExporter exporter = new HessianServiceExporter(); HessianServerProxyExporter exporter=new HessianServerProxyExporter(); exporter.setService(helloWorldService); exporter.setServiceInterface(HelloWorldService.class); return exporter; } } </code></pre> 可以看到只是进行了简单修改,使用我们自己定义的HessianServerProxyExporter 来发布hessian服务,而不是默认的HessianServiceExporter。 <h2>二.hessian客户端设置用户密码</h2> 客户端的项目结构图没变,如下:<br /> <img alt="项目结构图" class="img-thumbnail" src="/assist/images/blog/f10a8296447a4a95996ff163b14e22e9.png" /><br /> 客户端比之前只是在访问hessian接口的时候多设置了用户名和密码: <pre> <code class="language-java">package net.xqlee.project; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import org.springframework.remoting.caucho.HessianProxyFactoryBean; import net.xqlee.project.service.HelloWorldService; @SpringBootApplication public class DemoSpringbootRpcHessianClientApplication { public static void main(String[] args) { SpringApplication.run(DemoSpringbootRpcHessianClientApplication.class, args); } @Bean public HessianProxyFactoryBean helloClient() { HessianProxyFactoryBean factory = new HessianProxyFactoryBean(); factory.setServiceUrl("http://localhost:8083/HelloWorldService"); factory.setServiceInterface(HelloWorldService.class); factory.setPassword("123456"); factory.setUsername("download"); return factory; } } </code></pre> <span style="color:#ff0000"><span style="background-color:#ffff00">注意:HessianProxyFactoryBean中必须同时设置用户名和密码才能生效。</span></span><br /> <br /> 通过访问客户端的服务,通过断点到hessian的服务端HessianServerProxyExporter类,我们可以看到是如何传递用户名和密码参数的:<br /> <img alt="hessian传递认证信息" class="img-thumbnail" src="/assist/images/blog/3b8f60ff3153416fbe45c618a0e7f319.png" /><br /> 可以看到传递到服务端是通过HTTP协议的header传递的。并且传递的Basic认证头。这个头后面跟的字符串就是用户名:密码的Base64字符串,通过base64解密我们可以得到:<br /> <img alt="base64解密" class="img-thumbnail" src="/assist/images/blog/17312f236a3d454bac688634453d200e.png" /><br /> 用户名:密码已经显示出来。同样后面的判断也能实现我们的通讯验证。<br /> <br /> <br /> <strong>提示:<br /> 实际使用中,传递的密码或者用户请通过其他非对称加密方式加密后传输,服务端进行解密更为安全。</strong><br /> <br /> <br /> <br />  
  • Spring MVC 5.0

    Spring框架5.0,spring mvc 5.0入门教程。DispatcherServlet的详细讲解配置以及spring mvc5.0的helloword程序<h2>引言</h2>   在本教程中,我们将学习Spring DispatcherServlet类,其职责以及如何使用示例进行配置。spring mvc 5.0基于Java配置 <h2>一.DispatcherServlet是什么</h2> <br />     <code>DispatcherServlet</code> 充当基于Spring的Web应用程序的前端控制器。 它提供了一个请求处理机制,其中实际工作由可配置的委托组件执行。 它从javax.servlet.http.HttpServlet继承,通常在web.xml文件中配置。<br /> <br />     Web应用程序可以定义任意数量的<code>DispatcherServlet</code> 实例。 每个servlet将在其自己的名称空间中运行,使用映射,处理程序等加载它自己的应用程序上下文。只有由ContextLoaderListener加载的根应用程序上下文(如果有)将被共享。 在大多数情况下,应用程序只有一个具有上下文根URL(/)的<code>DispatcherServlet</code> ,也就是说,到达该域的所有请求都将由它处理。<br /> <br />     <code>DispatcherServlet</code> 使用Spring配置类来发现它需要的委托组件,用于请求映射,视图解析,异常处理等。 <h2>二.DispatcherServlet它如何使用WebApplicationContext</h2>     在基于Spring的应用程序中,我们的应用程序对象位于一个对象容器中。 该容器在对象之间创建对象和关联,并管理其完整的生命周期。 这些容器对象被称为Spring管理的bean(或者简单的bean),在Spring世界中容器被称为应用程序上下文(通过类ApplicationContext)。<br /> <br />     WebApplicationContext是一个普通的ApplicationContext的扩展。 它是Web感知的ApplicationContext,即它具有Servlet上下文信息。 当DispatcherServlet被加载时,它查找WebApplicationContext的bean配置文件并初始化它。<br /> <br />     通过访问Servlet上下文,任何实现了ServletConextAware接口的spring bean都可以访问ServletContext实例,并且可以做很多事情。 例如,它可以获取上下文初始化参数,获取上下文根信息并获取Web应用程序文件夹中的资源位置。 <h2>三.基于XML配置的DispatcherServlet(作为参考理解主讲基于Java配置)</h2> 我们来看看典型的DispatcherServlet声明和初始化是怎样的。 <pre> <code class="language-xml"><web-app> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/dispatcher-servlet-context.xml</param-value> </context-param> <servlet> <servlet-name>dispatcher-servlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value></param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher-servlet</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> </web-app></code></pre> 在上面的代码中,dispatcher-servlet-context.xml文件将包含所有可用于DispatcherServlet的bean定义和关联。 这些bean定义将覆盖在全局范围内使用相同名称定义的任何bean的定义。 例如: <pre> <code class="language-xml"><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver" > <property name="prefix"> <value>/WEB-INF/views/</value> </property> <property name="suffix"> <value>.jsp</value> </property> </bean> </beans></code></pre> <h2>四.基于JAVA代码配置的DispatcherServlet </h2> 从Servlet 3.0开始,除了web.xml文件中的声明式配置,DispatcherServlet可以通过实现或扩展Spring提供的这三个支持类来编程配置  <ul> <li>WebAppInitializer接口</li> <li>AbstractDispatcherServletInitializer抽象类</li> <li>AbstractAnnotationConfigDispatcherServletInitializer抽象类</li> </ul> 在下面的类中,WebApplicationInitializer确保ApplicationSerializer类被SpringServletContainerInitializer(它本身自动引导)检测到并用来初始化任何Servlet 3容器。<br /> <br /> 引入spring mvc 5.0需要的相关依赖,pom.xml: <pre> <code class="language-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.leftso.project.demo</groupId> <artifactId>demo-spring5-springmvc5</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <properties> <failOnMissingWebXml>false</failOnMissingWebXml> <spring.version>5.0.1.RELEASE</spring.version> <jstl.version>1.2.1</jstl.version> <tld.version>1.1.2</tld.version> <servlets.version>3.1.0</servlets.version> <jsp.version>2.3.1</jsp.version> </properties> <dependencies> <!-- Spring MVC Dependency --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <!-- JSTL Dependency --> <dependency> <groupId>javax.servlet.jsp.jstl</groupId> <artifactId>javax.servlet.jsp.jstl-api</artifactId> <version>${jstl.version}</version> </dependency> <dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>${tld.version}</version> </dependency> <!-- Servlet Dependency --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>${servlets.version}</version> <scope>provided</scope> </dependency> <!-- JSP Dependency --> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>${jsp.version}</version> <scope>provided</scope> </dependency> </dependencies> <build> <sourceDirectory>src/main/java</sourceDirectory> <resources> <resource> <directory>src/main/resources</directory> </resource> </resources> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>2.3</version> <configuration> <failOnMissingWebXml>false</failOnMissingWebXml> </configuration> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.5.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> <configuration> <path>/</path> </configuration> </plugin> </plugins> </build> </project></code></pre> <br /> <br /> 通过Java的方式可以将上面的web.xml写一个配置类: <pre> <code class="language-java">public class ApplicationInitializer implements WebApplicationInitializer { @Override public void onStartup(ServletContext servletContext) throws ServletException { XmlWebApplicationContext appContext = new XmlWebApplicationContext(); appContext.setConfigLocation("/WEB-INF/dispatcher-servlet-context.xml"); ServletRegistration.Dynamic registration = servletContext .addServlet("rootDispatcher", new DispatcherServlet(appContext)); registration.setLoadOnStartup(1); registration.addMapping("/"); } }</code></pre> 基于Java 配置的完整配置<br /> <strong>例子一:</strong> <pre> <code class="language-java">package com.leftso.project.demo.config; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRegistration; import org.springframework.web.WebApplicationInitializer; import org.springframework.web.context.ContextLoaderListener; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.servlet.DispatcherServlet; public class ApplicationInitializer implements WebApplicationInitializer { @Override public void onStartup(ServletContext servletContext) throws ServletException { // 创建 Spring ROOT context AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext(); rootContext.register(AppConfig.class); // 管理ROOT context生命周期 servletContext.addListener(new ContextLoaderListener(rootContext)); // 创建spring的dispatcher ,servlet's Spring application context AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext(); dispatcherContext.register(DispatcherConfig.class); ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", new DispatcherServlet(dispatcherContext)); dispatcher.setLoadOnStartup(1); dispatcher.addMapping("/"); } } </code></pre> 在上面的代码中,<code>AppConfig</code> 和<code>DispatcherConfig</code> 类定义了将在Web应用程序上下文中的spring管理的bean。<br /> AppConfig: <pre> <code class="language-java">package com.leftso.project.demo.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import com.leftso.project.demo.TestService; @Configuration @ComponentScan(basePackages = { "com.leftso" }) public class AppConfig { // 该类主要是spring 父级容器配置,里面可以定义很多的bean就像在spring-context.xml中一样 // 例如: @Bean public TestService testService() { return new TestService(); } } </code></pre> DispatcherConfig: <pre> <code class="language-java">package com.leftso.project.demo.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; import org.springframework.web.servlet.view.InternalResourceViewResolver; import org.springframework.web.servlet.view.JstlView; @Configuration public class DispatcherConfig extends WebMvcConfigurationSupport { // 覆盖父类的配置进行spring mvc的其他详细配置,配置内容可参考xml的spring-mvc /** * * <pre> * [Function]: * JSP 视图解析器 * [Description]: * JSP 视图解析器 * </pre> * * @return JSP 视图解析器 */ @Bean public ViewResolver jspViewResolver() { InternalResourceViewResolver internalResourceViewResolver = new InternalResourceViewResolver(); internalResourceViewResolver.setViewClass(JstlView.class); internalResourceViewResolver.setSuffix(".jsp"); internalResourceViewResolver.setPrefix("/WEB-INF/views/"); internalResourceViewResolver.setOrder(4); return internalResourceViewResolver; } /** * 资源文件处理器 */ @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/resources/**").addResourceLocations("/resources/"); } } </code></pre> <p><strong>例子二:</strong><br /> 基于Java配置的Spring MVC 5.0的配置,spring mvc 5.0为我们提供了一个封装的抽象类,我们实现这个类并指定相关的配置Java就可以了非常方便:</p> <pre> <code class="language-java">package com.leftso.project.demo.config; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; /** * Spring MVC 5启动配置 * * @author xqlee * */ public class SpringMVC5AnnotationConfigDispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return new Class<?>[] {}; } @Override protected Class<?>[] getServletConfigClasses() { return new Class<?>[] { WebMvcConfig.class }; } @Override protected String[] getServletMappings() { return new String[] { "/" }; } } </code></pre> <p>WebMvcConfig:<br />  </p> <pre> <code class="language-java">package com.leftso.project.demo.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.view.InternalResourceViewResolver; import org.springframework.web.servlet.view.JstlView; @Configuration @EnableWebMvc @ComponentScan(basePackages = { "com.leftso.project.demo" }) public class WebMvcConfig implements WebMvcConfigurer { @Bean public InternalResourceViewResolver resolver() { InternalResourceViewResolver resolver = new InternalResourceViewResolver(); resolver.setViewClass(JstlView.class); resolver.setPrefix("/WEB-INF/views/"); resolver.setSuffix(".jsp"); return resolver; } } </code></pre> <p>这比起第一种方式少些几句代码。</p> <h2><br /> 五.编写一个测试spring mvc 5.0的controller</h2> <pre> <code class="language-java">package com.leftso.project.demo.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class TestController { @GetMapping("/sayHello.do") public Object sayHello(String name) { return "Hello," + name; } } </code></pre> 将项目添加到tomcat中,启动tomcat,并在浏览器中访问controller的地址:<br /> <img alt="spring mvc 5.0" class="img-thumbnail" src="/assist/images/blog/e2422615e7924625a55ad38461e09529.png" /><br /> 从上图可以看到我们的<a rel="" target="_blank"href="http://www.leftso.com/blog/305.html" rel="" target="_blank">spring mvc5.0</a>项目已经成功启动.后续将讲解整合其他配置<br />  
  • Spring 5 MVC 整合 Hibernate 5

    在这个Spring5教程中,学习创建Spring 5 MVC Web应用程序,处理表单提交,集成hibernate连接到后端数据库,以及添加用于输入表单字段验证的hibernate验证器。<h2>引言</h2>     在这个Spring5教程中,学习创建Spring 5 MVC Web应用程序,处理表单提交,集成hibernate连接到后端数据库,以及添加用于输入表单字段验证的hibernate验证器。<br /> <br />     我们将创建一个简单的屏幕,我们可以添加用户字段(名称和电子邮件)。 这些细节将首先验证,然后使用休眠存储在HSQL数据库中。 该页面也将列出所有存储的用户。 <h2>一.Spring MVC 5整合hibernate5开发环境准备</h2> <ul> <li>Eclipse Neon.2 +</li> <li>JDK 1.8 +</li> <li>Spring 5.0.0.RELEASE</li> <li>Hibernate 5.2.11.Final</li> <li>Hibernate validator 5.4.1.Final</li> <li>Servlets 3.1.0</li> <li>HSQLDB 1.8.0.10</li> <li>Tomcat 7 maven plugin 2.2</li> </ul> <h2>二.Spring MVC 5整合hibernate5项目结构图</h2> 该项目具有典型的Maven Web应用程序结构。<br /> <img alt="Spring5" class="img-thumbnail" src="/assist/images/blog/2cd6c348063d40caabff4dfdc8e79010.png" /> <h2>三.Spring MVC 5整合hibernate5类图关系</h2> <img alt="" class="img-thumbnail" src="/assist/images/blog/3bb67013c0b84472824f0936c8f82b6e.png" /> <h2>四.Spring MVC 5整合hibernate5 maven依赖</h2> 查找用于在pom.xml文件中运行此示例的项目依赖项。 <pre> <code class="language-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.howtodoinjava.spring5.demo</groupId> <artifactId>spring5-mvc-hibernate-example</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <properties> <failOnMissingWebXml>false</failOnMissingWebXml> <spring.version>5.0.0.RELEASE</spring.version> <hibernate.version>5.2.11.Final</hibernate.version> <hibernate.validator>5.4.1.Final</hibernate.validator> <c3p0.version>0.9.5.2</c3p0.version> <jstl.version>1.2.1</jstl.version> <tld.version>1.1.2</tld.version> <servlets.version>3.1.0</servlets.version> <jsp.version>2.3.1</jsp.version> <hsqldb.version>1.8.0.10</hsqldb.version> </properties> <dependencies> <!-- Spring MVC Dependency --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <!-- Spring ORM --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${spring.version}</version> </dependency> <!-- Hibernate Core --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>${hibernate.version}</version> </dependency> <!-- Hibernate-C3P0 Integration --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-c3p0</artifactId> <version>${hibernate.version}</version> </dependency> <!-- c3p0 --> <dependency> <groupId>com.mchange</groupId> <artifactId>c3p0</artifactId> <version>${c3p0.version}</version> </dependency> <!-- Hibernate Validator --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>${hibernate.validator}</version> </dependency> <!-- JSTL Dependency --> <dependency> <groupId>javax.servlet.jsp.jstl</groupId> <artifactId>javax.servlet.jsp.jstl-api</artifactId> <version>${jstl.version}</version> </dependency> <dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>${tld.version}</version> </dependency> <!-- Servlet Dependency --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>${servlets.version}</version> <scope>provided</scope> </dependency> <!-- JSP Dependency --> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>${jsp.version}</version> <scope>provided</scope> </dependency> <!-- HSQL Dependency --> <dependency> <groupId>hsqldb</groupId> <artifactId>hsqldb</artifactId> <version>${hsqldb.version}</version> </dependency> </dependencies> <build> <sourceDirectory>src/main/java</sourceDirectory> <resources> <resource> <directory>src/main/resources</directory> </resource> </resources> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.5.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> <configuration> <path>/</path> </configuration> </plugin> </plugins> </build> </project></code></pre> <h2>五.配置Spring MVC 5 servlet分发器DispatcherServlet</h2>     随着Servlet 3.0规范的发布,可以用几乎没有xml来配置你的Servlet容器。 为此,Servlet规范中有ServletContainerInitializer。 在这个类中,你可以注册过滤器,监听器,servlet等,就像你在web.xml中一样。<br /> <br />     Spring提供了知道如何处理WebApplicationInitializer类的SpringServletContainerInitializer。 AbstractAnnotationConfigDispatcherServletInitializer类实现了内部实现WebApplicationInitializer的WebMvcConfigurer。 它注册一个ContextLoaderlistener(可选)和DispatcherServlet,并允许您轻松添加配置类来加载这两个类,并将过滤器应用于DispatcherServlet并提供servlet映射。<br />   <pre> <code class="language-java">public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return new Class[] { HibernateConfig.class }; } @Override protected Class<?>[] getServletConfigClasses() { return new Class[] { WebMvcConfig.class }; } @Override protected String[] getServletMappings() { return new String[] { "/" }; } }</code></pre> <h2>六.Spring Web MVC 5 配置</h2> Spring Web MVC配置如下。 <pre> <code class="language-java">import org.springframework.context.MessageSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.support.ResourceBundleMessageSource; import org.springframework.validation.Validator; import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.view.InternalResourceViewResolver; import org.springframework.web.servlet.view.JstlView; @Configuration @EnableWebMvc @ComponentScan(basePackages = { "com.howtodoinjava.demo.spring"}) public class WebMvcConfig implements WebMvcConfigurer { @Bean public InternalResourceViewResolver resolver() { InternalResourceViewResolver resolver = new InternalResourceViewResolver(); resolver.setViewClass(JstlView.class); resolver.setPrefix("/WEB-INF/views/"); resolver.setSuffix(".jsp"); return resolver; } @Bean public MessageSource messageSource() { ResourceBundleMessageSource source = new ResourceBundleMessageSource(); source.setBasename("messages"); return source; } @Override public Validator getValidator() { LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean(); validator.setValidationMessageSource(messageSource()); return validator; } }</code></pre> <ol> <li><code>WebMvcConfigurer</code> 定义了通过使用@EnableWebMvc自定义或添加到默认的<code>@EnableWebMvc</code>配置的选项。</li> <li><code>@EnableWebMvc</code> 启用默认的Spring MVC配置,并注册DispatcherServlet所期望的Spring MVC基础架构组件。</li> <li><code>@Configuration</code> 指示一个类声明了一个或多个@Bean方法,并且可以被Spring容器处理,以在运行时为这些bean生成bean定义和服务请求。</li> <li><code>@ComponentScan</code> 注释用于指定要扫描的基本包。任何用@Component和@Configuration注解的类都将被扫描。</li> <li><code>InternalResourceViewResolver</code> 有助于映射逻辑视图名称,以便在特定的预配置目录下直接查看文件。</li> <li><code>ResourceBundleMessageSource</code> 使用指定的基本名称访问资源包(这里是消息)。</li> <li><code>LocalValidatorFactoryBean</code> 引导一个<code>javax.validation.ValidationFactory</code> ,并通过Spring Validator接口以及JSR-303 Validator接口和<code>ValidatorFactory</code> 接口本身公开它。</li> </ol> <h2>七.Hibernate 配置</h2> 在例子中使用Hibernate配置。 <pre> <code class="language-java">import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScans; import org.springframework.context.annotation.Configuration; import org.springframework.orm.hibernate5.HibernateTransactionManager; import org.springframework.orm.hibernate5.LocalSessionFactoryBean; import org.springframework.transaction.annotation.EnableTransactionManagement; import com.howtodoinjava.demo.spring.model.User; @Configuration @EnableTransactionManagement public class HibernateConfig { @Autowired private ApplicationContext context; @Bean public LocalSessionFactoryBean getSessionFactory() { LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean(); factoryBean.setConfigLocation(context.getResource("classpath:hibernate.cfg.xml")); factoryBean.setAnnotatedClasses(User.class); return factoryBean; } @Bean public HibernateTransactionManager getTransactionManager() { HibernateTransactionManager transactionManager = new HibernateTransactionManager(); transactionManager.setSessionFactory(getSessionFactory().getObject()); return transactionManager; } }</code></pre> <ul> <li><code>LocalSessionFactoryBean</code> 创建一个Hibernate <code>SessionFactory</code>. 这是在Spring应用程序上下文中设置共享Hibernate SessionFactory的常用方法。</li> <li><code>EnableTransactionManagement</code> 支持Spring的注解驱动事务管理功能。</li> <li><code>HibernateTransactionManager</code> 将Hibernate Session从指定的工厂绑定到线程,可能允许每个工厂有一个线程绑定的Session。 此事务管理器适用于使用单个Hibernate</li> <li><code>SessionFactory</code> 进行事务性数据访问的应用程序,但也支持事务内的直接<code>DataSource</code> 访问,即普通JDBC。</li> </ul> <strong>hibernate.cfg.xml:</strong> <pre> <code class="language-xml"><?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="hibernate.archive.autodetection">class,hbm</property> <property name="hibernate.dialect">org.hibernate.dialect.HSQLDialect</property> <property name="hibernate.show_sql">true</property> <property name="hibernate.connection.driver_class">org.hsqldb.jdbcDriver</property> <property name="hibernate.connection.username">sa</property> <property name="hibernate.connection.password"></property> <property name="hibernate.connection.url">jdbc:hsqldb:mem:howtodoinjava</property> <property name="hibernate.hbm2ddl.auto">create</property> <property name="hibernate.c3p0.min_size">5</property> <property name="hibernate.c3p0.max_size">20</property> <property name="hibernate.c3p0.acquire_increment">2</property> <property name="hibernate.c3p0.acquire_increment">1800</property> <property name="hibernate.c3p0.max_statements">150</property> </session-factory> </hibernate-configuration></code></pre> <h2>八.Spring Controller and Path Mappings</h2> 控制器类有两个简单的GET和POST操作映射。 如果输入字段未被验证,则返回相同的表单bean以显示错误消息。 否则返回刷新视图。 <pre> <code class="language-java"> import java.util.Locale; import javax.validation.alid; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PostMapping; import com.howtodoinjava.demo.spring.model.User; import com.howtodoinjava.demo.spring.service.UserService; @Controller public class UserController { @Autowired private UserService userService; @GetMapping("/") public String userForm(Locale locale, Model model) { model.addAttribute("users", userService.list()); return "editUsers"; } @ModelAttribute("user") public User formBackingObject() { return new User(); } @PostMapping("/addUser") public String saveUser(@ModelAttribute("user") @Valid User user, BindingResult result, Model model) { if (result.hasErrors()) { model.addAttribute("users", userService.list()); return "editUsers"; } userService.save(user); return "redirect:/"; } }</code></pre> <h2>九.Service and DAO 层</h2> 服务和DAO层是用@Service和@Repository注释标注的普通服务组件。 @交易注解应用于服务层以支持事务处理。<br /> <br /> <code>UserService</code> and <code>UserServiceImpl</code><br />   <pre> <code class="language-java">public interface UserService { void save(User user); List<User> list(); } @Service public class UserServiceImp implements UserService { @Autowired private UserDao userDao; @Transactional public void save(User user) { userDao.save(user); } @Transactional(readOnly = true) public List<User> list() { return userDao.list(); } }</code></pre> <code>UserDao</code> and <code>UserDaoImp</code><br />   <pre> <code class="language-java">public interface UserDao { void save(User user); List<User> list(); } @Repository public class UserDaoImp implements UserDao { @Autowired private SessionFactory sessionFactory; @Override public void save(User user) { sessionFactory.getCurrentSession().save(user); } @Override public List<User> list() { @SuppressWarnings("unchecked") TypedQuery<User> query = sessionFactory.getCurrentSession().createQuery("from User"); return query.getResultList(); } }</code></pre> User<br />   <pre> <code class="language-java">import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Table; import javax.validation.constraints.Size; import org.hibernate.validator.constraints.Email; import org.hibernate.validator.constraints.NotEmpty; @Entity @Table(name = "TBL_USERS") public class User { @Id @GeneratedValue @Column(name = "USER_ID") private Long id; @Column(name = "USER_NAME") @Size(max = 20, min = 3, message = "{user.name.invalid}") @NotEmpty(message="Please Enter your name") private String name; @Column(name = "USER_EMAIL", unique = true) @Email(message = "{user.email.invalid}") @NotEmpty(message="Please Enter your email") private String email; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } }</code></pre> <h2>十.页面和消息</h2> 最后,使用JSP文件和消息资源包<br /> <br /> editUsers.jsp<br />   <pre> <code class="language-html"><%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%> <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Spring5 MVC Hibernate Demo</title> <style type="text/css"> .error { color: red; } table { width: 50%; border-collapse: collapse; border-spacing: 0px; } table td { border: 1px solid #565454; padding: 20px; } </style> </head> <body> <h1>Input Form</h1> <form:form action="addUser" method="post" modelAttribute="user"> <table> <tr> <td>Name</td> <td> <form:input path="name" /> <br /> <form:errors path="name" cssClass="error" /> </td> </tr> <tr> <td>Email</td> <td> <form:input path="email" /> <br /> <form:errors path="email" cssClass="error" /> </td> </tr> <tr> <td colspan="2"><button type="submit">Submit</button></td> </tr> </table> </form:form> <h2>Users List</h2> <table> <tr> <td><strong>Name</strong></td> <td><strong>Email</strong></td> </tr> <c:forEach items="${users}" var="user"> <tr> <td>${user.name}</td> <td>${user.email}</td> </tr> </c:forEach> </table> </body> </html></code></pre> messages.properties<br />   <pre> <code class="language-html">user.name.invalid = Name must be between {2} and {1} characters. user.email.invalid = Please enter valid email address.</code></pre> <h2>十一.演示这个栗子</h2> 让我们使用maven tomcat7插件运行应用程序。 执行maven target:tomcat7:run。<br /> 访问URL: <code>http://localhost:8080</code><br /> Initial Screen<br /> <img alt="Initial Screen" class="img-thumbnail" src="/assist/images/blog/830164ad1b5448dab1aa39d340300c95.png" /><br /> 无效的输入验证<br /> <img alt="无效的输入验证" class="img-thumbnail" src="/assist/images/blog/8ddf9070177c4ce3a00c5dfe4b099950.png" /><br /> 有效的表格提交<br /> <img alt="有效的表格提交" class="img-thumbnail" src="/assist/images/blog/6ef29b6dbc1f4fb7954a3cb9bac38159.png" /><br /> 检查服务器日志: <pre> <code class="language-html">Hibernate: call next value for hibernate_sequence Hibernate: insert into TBL_USERS (USER_EMAIL, USER_NAME, USER_ID) values (?, ?, ?) Hibernate: select user0_.USER_ID as USER_ID1_0_, user0_.USER_EMAIL as USER_EMA2_0_, user0_.USER_NAME as USER_NAM3_0_ from TBL_USERS user0_</code></pre> <a href="https://howtodoinjava.com/wp-content/downloads/spring5-mvc-hibernate-example.zip" rel="external nofollow" target="_blank">Sourcecode Download</a>
  • junit5 新特性与使用

    在Java编程测试中junit5 新特性与使用,Java编程,junit5<h2>一、摘要说明</h2>     本JUnit 5教程讲解了如何使JUnit 5改编成java 8编码风格和其他几个特性。了解JUnit5与JUnit 3或4的不同之处。<br />     JUnit 5是Java应用程序中使用最广泛的测试框架。 很久以来,JUnit一直在做得很好。 在之间,JDK 8在java中引起了非常令人兴奋的功能,最引人注目的是lambda表达式。 JUnit 5旨在适应java 8风格的编码和几个其他功能,这就是为什么需要java 8在JUnit 5中创建和执行测试(尽管可以执行用JUnit 3或JUnit 4编写的测试用于向下兼容)。<br />     本文将讲解以下内容: <ol> <li>架构体系</li> <li>环境搭建</li> <li>注解</li> <li>编写动态测试</li> <li>测试套件</li> <li>断言</li> <li>假设</li> <li>向下兼容性</li> <li>回顾总结</li> </ol> <h2>二、JUnit 5架构体系</h2>   与JUnit 4不同,JUnit 5不再是单个库,而是模块化结构的集合,JUnit 5由三个不同的子项目组成<br /> <br /> JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage<br /> <br /> <strong>1.JUnit Platform</strong><br /> JUnit平台作为在JVM上启动测试框架的基础。 它还定义了用于开发在平台上运行的测试框架的TestEngine API。 此外,该平台提供了一个控制台启动器,从命令行启动平台,为Gradle和Maven构建插件以及基于JUnit 4的Runner,用于在平台上运行任何TestEngine。<br /> <strong>2.JUnit Jupiter</strong><br /> JUnit Jupiter是用于在JUnit 5中编写测试和扩展的新编程模型和扩展模型的组合.Jupiter子项目提供了一个用于在平台上运行基于Jupiter的测试的TestEngine。<br /> <strong>3.JUnit Vintage</strong><br /> JUnit Vintage提供了一个用于在平台上运行JUnit 3和JUnit 4的测试的TestEngine。 <h2>三、环境搭建</h2> 引入2个最基础的依赖(即Jupiter引擎依赖关系和平台运行程序依赖关系)在您的maven或gradle项目中使用JUnit 5。<br /> <br /> //pom.xml <pre> <code class="language-xml"><dependency>     <groupId>org.junit.jupiter</groupId>     <artifactId>junit-jupiter-engine</artifactId>     <version>${junit.jupiter.version}</version> </dependency> <dependency>     <groupId>org.junit.platform</groupId>     <artifactId>junit-platform-runner</artifactId>     <version>${junit.platform.version}</version>     <scope>test</scope> </dependency></code></pre> //build.gradle <pre> <code>testRuntime("org.junit.jupiter:junit-jupiter-engine:5.0.0-M4") testRuntime("org.junit.platform:junit-platform-runner:1.0.0-M4")</code></pre> 如果有疑问,请参照官方的build.gradle和pom.xml: <h2>四、JUnit 5注解</h2> JUnit 5提供了以下注释来编写测试。<br /> ANNOTATION    DESCRIPTION<br /> @BeforeEach    注释方法将在测试类中的每个测试方法之前运行。<br /> @AfterEach    注释方法将在测试类中的每个测试方法之后运行。<br /> @BeforeAll    注释方法将在测试类中的所有测试方法之前运行。 此方法必须是静态的。<br /> @AfterAll    注释方法将在测试类中的所有测试方法之后运行。 此方法必须是静态的。<br /> @Test    它用于将方法标记为junit测试<br /> @DisplayName    用于为测试类或测试方法提供任何自定义显示名称<br /> @Disable    它用于禁用或忽略来自测试套件的测试类或方法。<br /> @Nested    用于创建嵌套测试类<br /> @Tag    使用用于测试发现和过滤的标签来标记测试方法或测试类<br /> @TestFactory    标记方法是动态测试的测试工厂 <h2>五、使用JUnit 5中编写动态测试</h2> JUnit 4和JUnit 5在测试写作风格中没有太大变化。 这里是他们的生命周期方法的样本测试。 <pre> <code class="language-java">import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import com.howtodoinjava.junit5.examples.Calculator; public class AppTest { @BeforeAll static void setup(){ System.out.println("@BeforeAll executed"); } @BeforeEach void setupThis(){ System.out.println("@BeforeEach executed"); } @Tag("DEV") @Test void testCalcOne() { System.out.println("======TEST ONE EXECUTED======="); Assertions.assertEquals( 4 , Calculator.add(2, 2)); } @Tag("PROD") @Disabled @Test void testCalcTwo() { System.out.println("======TEST TWO EXECUTED======="); Assertions.assertEquals( 6 , Calculator.add(2, 4)); } @AfterEach void tearThis(){ System.out.println("@AfterEach executed"); } @AfterAll static void tear(){ System.out.println("@AfterAll executed"); } } </code></pre> <h2>六、测试套件</h2> 使用JUnit 5测试套件,您可以将测试扩展到多个测试类和不同的软件包。 JUnit 5提供了两个注解:@SelectPackages和@SelectClasses来创建测试套件。<br /> 要执行该套件,您将使用@RunWith(JUnitPlatform.class)。 <pre> <code class="language-java">​​​​​​​@RunWith(JUnitPlatform.class) @SelectPackages("com.howtodoinjava.junit5.examples") public class JUnit5TestSuiteExample  { }</code></pre> <br /> 此外,您可以使用以下注解来过滤测试包,类甚至测试方法。<br /> 1.@IncludePackages 和 @ExcludePackages 过滤测试包<br /> 2.@IncludeClassNamePatterns 和 @ExcludeClassNamePatterns 过滤测试类<br /> 3.@IncludeTags 和 @ExcludeTags 过滤测试方法 <pre> <code class="language-java">@RunWith(JUnitPlatform.class) @SelectPackages("com.howtodoinjava.junit5.examples") @IncludePackages("com.howtodoinjava.junit5.examples.packageC") @ExcludeTags("PROD") public class JUnit5TestSuiteExample  { }</code></pre> <h2>七、Junit5中的断言</h2>   断言有助于使用测试用例的实际输出验证预期输出。 为了保持简单,所有JUnit Jupiter断言是org.junit.jupiter.Assertions类中的静态方法,例如 assertEquals(),assertNotEquals()。 <pre> <code class="language-java">void testCase() { //Test will pass Assertions.assertNotEquals(3, Calculator.add(2, 2)); //Test will fail Assertions.assertNotEquals(4, Calculator.add(2, 2), "Calculator.add(2, 2) test failed"); //Test will fail Supplier<String> messageSupplier = ()-> "Calculator.add(2, 2) test failed"; Assertions.assertNotEquals(4, Calculator.add(2, 2), messageSupplier); }</code></pre> <h2>八、假设</h2>     Assumptions类提供了静态方法来支持基于假设的条件测试执行。 失败的假设导致测试被中止。 无论何时继续执行给定的测试方法没有意义,通常使用假设。 在测试报告中,这些测试将被标记为已通过。<br />     JUnit jupiter Assumptions类有两个这样的方法:putsFalse(),putsTrue()。 <pre> <code class="language-java">public class AppTest { @Test void testOnDev() { System.setProperty("ENV", "DEV"); Assumptions.assumeTrue("DEV".equals(System.getProperty("ENV")), AppTest::message); } @Test void testOnProd() { System.setProperty("ENV", "PROD"); Assumptions.assumeFalse("DEV".equals(System.getProperty("ENV"))); } private static String message () { return "TEST Execution Failed :: "; } }</code></pre> <h2>九、兼容性</h2> JUnit 3或JUnit 4的向下兼容性<br /> <br /> JUnit 4已经在这里了很长时间,并且有许多测试以junit 4写成.JUnit Jupiter还需要支持这些测试。 为此,开发了JUnit Vintage子项目。<br /> <br /> JUnit Vintage提供了一个TestEngine实现,用于在JUnit 5平台上运行基于JUnit 3和JUnit 4的测试。 <h2>十、总结</h2>     JUnit 5还在开发中。 看起来如此令人兴奋,功能丰富。 而现在它被第三方工具和API扩展开放。 作为测试作者,您可能不会觉得有什么不同,但是当您要扩展或尝试开发任何IDE插件时,您会赞美它。<br /> <br />     作为开发人员,您还可以考虑将测试模板添加到eclipse IDE中以提高开发速度。
  • java编程之java jwt token什么是JWT?(一)

    本文讲解什么是JWT,JWT的构成和JWT算法?,Java编程,JWT<h2>一、什么是JWT?了解JWT,认知JWT</h2>   首先jwt其实是三个英语单词JSON Web Token的缩写。通过全名你可能就有一个基本的认知了。token一般都是用来认证的,比如我们系统中常用的用户登录token可以用来认证该用户是否登录。jwt也是经常作为一种安全的token使用。<br /> <br /> <strong>JWT的定义:</strong><br />   JWT是一种用于双方之间传递安全信息的简洁的、URL安全的表述性声明规范。JWT作为一个开放的标准(RFC 7519),定义了一种简洁的,自包含的方法用于通信双方之间以Json对象的形式安全的传递信息。因为数字签名的存在,这些信息是可信的,JWT可以使用HMAC算法或者是RSA的公私秘钥对进行签名。<br /> <strong>JWT特点:</strong> <ul> <li> <p><strong>简洁(Compact)</strong>: 可以通过URL,POST参数或者在HTTP header发送,因为数据量小,传输速度也很快</p> </li> <li> <p><strong>自包含(Self-contained)</strong>:负载中包含了所有用户所需要的信息,避免了多次查询数据库</p> </li> </ul> <h2>二、JWT构成或者说JWT是什么样的?</h2> <strong>2.1.JWT结构</strong><br /> JWT主要包含三个部分之间用英语句号'.'隔开 <ol> <li>Header 头部</li> <li>Payload 负载</li> <li>Signature 签名</li> </ol> <strong>注意,顺序是 header.payload.signature</strong><br /> 最终的结构有点像这样: <pre> <code>leftso.com.blog </code></pre> 当然真实的jwt不可能是这么简单的明文<br /> <br /> <strong>2.2.JWT的头部(Header)</strong><br /> 在header中通常包含了两部分:token类型和采用的加密算法。如下: <pre> <code class="language-json">{ "alg": "HS256", "typ": "JWT" } </code></pre> 上面的JSON内容指定了当前采用的加密方式为HS256,token的类型为jwt<br /> <br /> 将上面的内容进行base64编码,可以得到我们JWT的头部,编码后如下:<br /> (本站提供了在线的base64编码/解码的工具,可供读者测试) <pre> <code>ewogICJhbGciOiAiSFMyNTYiLAogICJ0eXAiOiAiSldUIgp9ICA=</code></pre> <br /> <strong>2.3.JWT的负载(Payload)</strong><br /> 负载(Payload)为JWT的第二部分。JWT的标准所定义了一下几个基本字段 <ol> <li><code>iss</code>: 该JWT的签发者</li> <li><code>sub</code>: 该JWT所面向的用户</li> <li><code>aud</code>: 接收该JWT的一方</li> <li><code>exp</code>(expires): 什么时候过期,这里是一个Unix时间戳</li> <li><code>iat</code>(issued at): 在什么时候签发的</li> </ol> <br /> 除了标准定义的字段外,我们还要定义一些我们在业务处理中需要用到的字段,例如用户token一般可以包含用户登录的token或者用户的id,一个简单的例子如下: <pre> <code class="language-json">{ "iss": "Lefto.com", "iat": 1500218077, "exp": 1500218077, "aud": "www.leftso.com", "sub": "leftso@qq.com", "user_id": "dc2c4eefe2d141490b6ca612e252f92e", "user_token": "09f7f25cdb003699cee05759e7934fb2" }</code></pre> 上面的user_id、user_token都是我们自己定义的字段<br /> <br /> 现在我们需要将负载这整个部分进行base64编码,编码后结果如下: <pre> <code>ewogICAgImlzcyI6ICJMZWZ0by5jb20iLAogICAgImlhdCI6IDE1MDAyMTgwNzcsCiAgICAiZXhwIjogMTUwMDIxODA3NywKICAgICJhdWQiOiAid3d3LmxlZnRzby5jb20iLAogICAgInN1YiI6ICJsZWZ0c29AcXEuY29tIiwKICAgICJ1c2VyX2lkIjogImRjMmM0ZWVmZTJkMTQxNDkwYjZjYTYxMmUyNTJmOTJlIiwKICAgICJ1c2VyX3Rva2VuIjogIjA5ZjdmMjVjZGIwMDM2OTljZWUwNTc1OWU3OTM0ZmIyIgp9</code></pre> <br /> <strong>2.4.</strong><strong>Signature(签名)</strong><br /> 签名其实是对JWT的头部和负载整合的一个签名验证<br /> 首先需要将头部和负载通过.链接起来就像这样:header.Payload,上述的例子链接起来之后就是这样的: <pre> <code>ewogICJhbGciOiAiSFMyNTYiLAogICJ0eXAiOiAiSldUIgp9ICA=.ewogICAgImlzcyI6ICJMZWZ0by5jb20iLAogICAgImlhdCI6IDE1MDAyMTgwNzcsCiAgICAiZXhwIjogMTUwMDIxODA3NywKICAgICJhdWQiOiAid3d3LmxlZnRzby5jb20iLAogICAgInN1YiI6ICJsZWZ0c29AcXEuY29tIiwKICAgICJ1c2VyX2lkIjogImRjMmM0ZWVmZTJkMTQxNDkwYjZjYTYxMmUyNTJmOTJlIiwKICAgICJ1c2VyX3Rva2VuIjogIjA5ZjdmMjVjZGIwMDM2OTljZWUwNTc1OWU3OTM0ZmIyIgp9</code></pre> <br /> 由于HMacSHA256加密算法需要一个key,我们这里key暂时用leftso吧<br /> <br /> 加密后的内容为: <pre> <code>686855c578362e762248f22e2cc1213dc7a6aff8ebda52247780eb6b5ae91877</code></pre> <br /> 其实加密的内容也就是JWT的签名,类似我们对某个文件进行MD5加密然后接收到文件进行md5对比一样.只是这里的HMacSHA256算法需要一个key,当然这个key应该是使用者和接收者都知道的。<br /> <br /> 对上面的签名内容进行base64编码得到最终的签名 <pre> <code>Njg2ODU1YzU3ODM2MmU3NjIyNDhmMjJlMmNjMTIxM2RjN2E2YWZmOGViZGE1MjI0Nzc4MGViNmI1YWU5MTg3Nw==</code></pre> <br /> <strong>2.5最终的JWT</strong> <pre> <code>ewogICJhbGciOiAiSFMyNTYiLAogICJ0eXAiOiAiSldUIgp9ICA=.ewogICAgImlzcyI6ICJMZWZ0by5jb20iLAogICAgImlhdCI6IDE1MDAyMTgwNzcsCiAgICAiZXhwIjogMTUwMDIxODA3NywKICAgICJhdWQiOiAid3d3LmxlZnRzby5jb20iLAogICAgInN1YiI6ICJsZWZ0c29AcXEuY29tIiwKICAgICJ1c2VyX2lkIjogImRjMmM0ZWVmZTJkMTQxNDkwYjZjYTYxMmUyNTJmOTJlIiwKICAgICJ1c2VyX3Rva2VuIjogIjA5ZjdmMjVjZGIwMDM2OTljZWUwNTc1OWU3OTM0ZmIyIgp9.Njg2ODU1YzU3ODM2MmU3NjIyNDhmMjJlMmNjMTIxM2RjN2E2YWZmOGViZGE1MjI0Nzc4MGViNmI1YWU5MTg3Nw==</code></pre> <br /> 通过上面的一个简单的说明您是否对JWT有一个简单额认知了呢?接下来我将讲解JWT在Java编程中的使用<br /> <br /> 未完待续中...<br /> <br />  
  • spring框架5.0介绍说明/概述

    java编程中spring框架5.0介绍说明/概述,spring5,spring框架,java编程spring框架一直以来都是java编程中流行的框架。 <p>Spring框架5.0介绍说明</p> <h2 style="margin-left:0px; margin-right:0px; text-align:start">1.Spring入门</h2> <div style="text-align:start"> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">本参考指南提供有关Spring框架的详细信息。它为所有功能提供了全面的文档,以及Spring所接受的基本概念(如<em>“依赖注入”</em>)的背景知识。</span></span></span></span></p> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">如果您刚开始使用Spring,则可能需要通过创建基于Spring Boot的应用程序来开始使用Spring Framework 。Spring Boot提供了一种快速(和有意见的)方式来创建一个基于生产的基于Spring的应用程序。它基于Spring框架,有利于配置的约定,并且旨在尽可能快地让您运行。</span></span></span></span></p> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">您可以使用start.spring.io生成一个基本项目或遵循的一个“入门”指南类的 入门构建一个RESTful Web服务 之一。除了易于消化以外,这些指南非常<em>重视任务</em>,其中大多数都是基于Spring Boot的。他们还涵盖了Spring解决方案中您可能想要考虑的其他项目。</span></span></span></span></p> </div> </div> <h2 style="margin-left:0px; margin-right:0px; text-align:start">2. Spring框架简介</h2> <div style="text-align:start"> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">Spring Framework是一个Java平台,为开发Java应用程序提供全面的基础设施支持。Spring处理基础设施,以便您可以专注于您的应用程序。</span></span></span></span></p> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">Spring使您能够从“简单的Java对象”(POJO)构建应用程序,并将企业服务非侵入式应用于POJO。此功能适用于Java SE编程模型以及完整和部分Java EE。</span></span></span></span></p> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">作为应用程序开发人员,您可以从Spring平台中获益如何:</span></span></span></span></p> </div> <div> <ul style="margin-left:1.5em; margin-right:0px"> <li> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">使Java方法在数据库事务中执行,而不必处理事务API。</span></span></span></span></p> </li> <li> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">使本地Java方法成为HTTP端点,而无需处理Servlet API。</span></span></span></span></p> </li> <li> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">使本地Java方法成为一个消息处理程序,而无需处理JMS API。</span></span></span></span></p> </li> <li> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">使本地Java方法成为管理操作,而无需处理JMX API。</span></span></span></span></p> </li> </ul> </div> </div> <div style="text-align:start"> <h3 style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff">2.1。依赖注入和控制反转</span></span></span></h3> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">Java应用程序 - 从受限嵌入式应用程序到n层服务器端企业应用程序运行范围的宽松术语通常由协作形成应用程序的对象组成。因此,应用程序中的对象彼此具有<em>依赖关系</em>。</span></span></span></span></p> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">虽然Java平台提供了丰富的应用程序开发功能,但它缺乏将基本构建块组织成一个连贯的整体的手段,将该任务留给架构师和开发人员。虽然可以使用<em>Factory</em>,<em>Abstract Factory</em>,<em>Builder</em>,<em>Decorator</em>和<em>Service Locator</em>这样的设计模式 来构成组成应用程序的各种类和对象实例,但这些模式只是简单地说明:给出名称的最佳实践,以及什么样的模式,应用于哪里,它解决的问题等等。模式是<em>您必须</em>在应用程序中<em>实现自己的</em>正式的最佳实践。</span></span></span></span></p> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">Spring框架<em>反转控制</em>(IoC)组件通过提供将不同组件组成完整工作应用程序的正式方法来解决这一问题。Spring Framework将形式化的设计模式作为可以集成到您自己的应用程序中的第一类对象进行编译。许多组织和机构以这种方式使用Spring框架来设计强大的,可<em>维护的</em>应用程序。</span></span></span></span></p> </div> <div style="margin-left:0px; margin-right:0px"> <div> <div style="margin-left:0px; margin-right:0px; text-align:center"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="background-color:#f1f1f1"><span style="font-family:Montserrat,sans-serif"><span style="color:#0b0a0a">背景</span></span></span></span></span></span></div> <div> <p><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="background-color:#f1f1f1"><span style="font-family:inherit">“ <em>问题是,控制的哪个方面是(他们)反转?</em> ”Martin Fowler 在2004年在他的网站上提出了有关反转控制(IoC)的 问题 .Fowler建议重新命名原则,使其更加自明,并提出<em>依赖注入</em>。</span></span></span></span></span></p> </div> </div> </div> </div> <div style="text-align:start"> <h3 style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff">2.2。框架模块</span></span></span></h3> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">Spring框架由组织成约20个模块的功能组成。这些模块分为Core Container,数据访问/集成,Web,AOP(面向对象编程),Instrumentation,Messaging和Test,如下图所示。</span></span></span></span></p> </div> </div> <img alt="spring 框架图" class="img-thumbnail" src="/assist/images/blog/2937672202ba41c6862b026d169f0528.png" /> <div style="text-align:start"> <div style="margin-left:0px; margin-right:0px"> <div style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="color:#0b0a0a"><span style="font-family:"Varela Round",sans-serif"><em>图1. Spring框架概述</em></span></span></span></span></span></div> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">以下部分列出了每个功能的可用模块及其工件名称及其涵盖的主题。工件名称与依赖关系管理工具中使用的<em>工件ID </em>相关。</span></span></span></span></p> </div> <div> <h4 style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff">2.2.1。核心集装箱</span></span></span></h4> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">所述<em>核心容器</em>由以下部分组成<code>spring-core</code>, <code>spring-beans</code>,<code>spring-context</code>,<code>spring-context-support</code>,和<code>spring-expression</code>(弹簧表达式语言)模块。</span></span></span></span></p> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">的<code>spring-core</code>和<code>spring-beans</code>模块提供框架的基本零件,包括IOC和依赖注入特征。这<code>BeanFactory</code>是工厂模式的复杂实施。它消除了对编程单例的需要,并允许您将依赖关系的配置和规范与实际程序逻辑分离。</span></span></span></span></p> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">所述<em>上下文</em>(<code>spring-context</code>)模块建立由设置在固体基体上<em>的核心和豆类</em>模块:它是访问一个框架式的方式是类似于一个JNDI注册表对象的装置。上下文模块从Beans模块继承其功能,并增加了对国际化的支持(例如使用资源束),事件传播,资源加载以及例如Servlet容器透明地创建上下文。Context模块还支持Java EE功能,如EJB,JMX和基本远程处理。该<code>ApplicationContext</code>接口是语境模块的焦点。 <code>spring-context-support</code>提供了将常见第三方库集成到Spring应用程序环境中的支持,特别是用于缓存(EhCache,JCache)和调度(CommonJ,Quartz)。</span></span></span></span></p> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">该<code>spring-expression</code>模块提供了强大的<em>表达式语言,</em>用于在运行时查询和操作对象图。它是JSP 2.1规范中规定的统一表达语言(统一EL)的扩展。该语言支持设置和获取属性值,属性分配,方法调用,访问数组,集合和索引器的内容,逻辑和算术运算符,命名变量以及从Spring的IoC容器中的名称检索对象。它还支持列表投影和选择以及通用列表聚合。</span></span></span></span></p> </div> </div> <div> <h4 style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff">2.2.2。AOP和仪器仪表</span></span></span></h4> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">该<code>spring-aop</code>模块提供了一个符合<em>AOP</em>联盟标准的面向方面的编程实现,允许您定义方法拦截器和切入点,以便干净地解除实现应分隔的功能的代码。使用源级元数据功能,您还可以将行为信息与.NET属性类似。</span></span></span></span></p> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">单独的<code>spring-aspects</code>模块提供与AspectJ的集成。</span></span></span></span></p> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">该<code>spring-instrument</code>模块提供了在某些应用服务器中使用的类检测支持和类加载器实现。该<code>spring-instrument-tomcat</code> 模块包含Spring的Tomcat测试代理。</span></span></span></span></p> </div> </div> <div> <h4 style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff">2.2.3。消息</span></span></span></h4> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">Spring框架4包括<code>spring-messaging</code>从关键抽象模块 <em>Spring集成</em>项目,例如<code>Message</code>,<code>MessageChannel</code>,<code>MessageHandler</code>,和其他人作为基于消息的应用奠定了基础。该模块还包括一组用于将消息映射到方法的注释,类似于基于Spring MVC注释的编程模型。</span></span></span></span></p> </div> </div> <div> <h4 style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff">2.2.4。数据访问/集成</span></span></span></h4> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">所述<em>数据访问/集成</em>层由JDBC,ORM,OXM,JMS和交易模块。</span></span></span></span></p> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">该<code>spring-jdbc</code>模块提供了一个JDBC抽象层,无需执行繁琐的JDBC编码和解析数据库供应商特定的错误代码。</span></span></span></span></p> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">该<code>spring-tx</code>模块支持 针对实现特殊接口和<em>所有POJO(普通Java对象)的</em>类的编程和声明式事务管理。</span></span></span></span></p> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">该<code>spring-orm</code>模块为流行的对象关系映射 API(包括JPA和Hibernate)提供集成层 。使用该<code>spring-orm</code>模块,您可以将这些O / R映射框架与Spring提供的所有其他功能结合使用,例如前面提到的简单的声明性事务管理功能。</span></span></span></span></p> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">该<code>spring-oxm</code>模块提供了一个支持Object / XML映射实现的抽象层, 如JAXB,Castor,JiBX和XStream。</span></span></span></span></p> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">该<code>spring-jms</code>模块(Java消息服务)包含用于生成和消费消息的功能。从Spring Framework 4.1开始,它提供了与<code>spring-messaging</code>模块的集成 。</span></span></span></span></p> </div> </div> <div> <h4 style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff">2.2.5。卷筒纸</span></span></span></h4> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">所述<em>网络</em>层由的<code>spring-web</code>,<code>spring-webmvc</code>和<code>spring-websocket</code> 模块。</span></span></span></span></p> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">该<code>spring-web</code>模块提供基本的面向Web的集成功能,例如多部分文件上传功能,以及使用Servlet侦听器和面向Web的应用程序上下文初始化IoC容器。它还包含一个HTTP客户端和Spring的远程支持的Web相关部分。</span></span></span></span></p> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">该<code>spring-webmvc</code>模块(也称为<em>Web-Servlet</em>模块)包含用于Web应用程序的Spring的模型视图控制器(<em>MVC</em>)和REST Web Services实现。Spring的MVC框架提供了领域模型代码和Web表单之间的清晰分离,并与Spring Framework的所有其他功能集成。</span></span></span></span></p> </div> </div> <div> <h4 style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff">2.2.6。测试</span></span></span></h4> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">该<code>spring-test</code>模块支持使用JUnit或TestNG对Spring组件进行单元测试和 集成测试。它提供了Spring 的一致加载<code>ApplicationContext</code>和这些上下文的缓存。它还提供可用于孤立测试代码的模拟对象。</span></span></span></span></p> </div> </div> </div> <div style="text-align:start"> <h3 style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff">2.3。使用场景</span></span></span></h3> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">之前描述的构建模块使Spring成为许多场景中的逻辑选择,从在资源受限设备上运行的嵌入式应用程序到使用Spring的事务管理功能和Web框架集成的全面的企业应用程序。<br /> <img alt="流程" class="img-thumbnail" src="/assist/images/blog/4ef2d77e2fa6406791ea64ad87b24c68.png" /></span></span></span></span><br />  </p> <div style="margin-left:0px; margin-right:0px; text-align:start"> <div style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="color:#0b0a0a"><span style="font-family:"Varela Round",sans-serif"><em>图2.典型的成熟的Spring Web应用程序</em></span></span></span></span></span></div> </div> <div style="text-align:start"> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">Spring的声明式事务管理功能 使Web应用程序完全事务性,就像使用EJB容器管理的事务一样。所有您的定制业务逻辑都可以使用简单的POJO实现,并由Spring的IoC容器进行管理。其他服务包括支持发送电子邮件和独立于Web层的验证,可让您选择执行验证规则的位置。Spring的ORM支持与JPA和Hibernate集成; 例如,当使用Hibernate时,可以继续使用现有的映射文件和标准的Hibernate <code>SessionFactory</code>配置。表单控制器将Web层与域模型无缝集成,消除了<code>ActionForms</code>将HTTP参数转换为域模型值的需求 或其他类。<br /> <img alt="3" class="img-thumbnail" src="/assist/images/blog/218014be82624d42ab35c430c91b7b98.png" /></span></span></span></span><br />  </p> <div style="margin-left:0px; margin-right:0px; text-align:start"> <div style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="color:#0b0a0a"><span style="font-family:"Varela Round",sans-serif"><em>图3.使用第三方Web框架的Spring中间层</em></span></span></span></span></span></div> </div> <div style="text-align:start"> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">有时情况不允许您完全切换到不同的框架。Spring框架并<em>没有</em>强迫你在它使用的一切; 这不是一个 <em>全无或缺的</em>解决方案。使用Struts,Tapestry,JSF或其他UI框架构建的现有前端可以与基于Spring的中间层集成,从而允许您使用Spring事务功能。您只需要使用一个连接您的业务逻辑,<code>ApplicationContext</code>并使用它<code>WebApplicationContext</code>来集成您的Web层。<br /> <img alt="4" class="img-thumbnail" src="/assist/images/blog/48658620eeaf4d7d9defac9736e058f7.png" /></span></span></span></span><br />  </p> <div style="margin-left:0px; margin-right:0px; text-align:start"> <div style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="color:#0b0a0a"><span style="font-family:"Varela Round",sans-serif"><em>图4.远程使用场景</em></span></span></span></span></span></div> </div> <div style="text-align:start"> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">当你需要通过Web服务来访问现有的代码,你可以使用Spring的 <code>Hessian-</code>,<code>Rmi-</code>或<code>HttpInvokerProxyFactoryBean</code>类。启用对现有应用程序的远程访问并不困难。<br /> <img alt="5" class="img-thumbnail" src="/assist/images/blog/88119b88334c40f7b0178ccc9fa384e3.png" /></span></span></span></span><br />  </p> <div style="margin-left:0px; margin-right:0px; text-align:start"> <div style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="color:#0b0a0a"><span style="font-family:"Varela Round",sans-serif"><em>图5. EJB - 包装现有的POJO</em></span></span></span></span></span></div> </div> <div style="text-align:start"> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">Spring Framework还为Enterprise JavaBeans 提供了一个访问和抽象层,使您能够重用现有的POJO,并将其包装在无状态会话bean中,以用于可能需要声明式安全性的可伸缩的,故障安全的Web应用程序。</span></span></span></span></p> </div> <div style="text-align:start"> <h4 style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff">2.3.1。依赖管理和命名约定</span></span></span></h4> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">依赖关系管理和依赖注入是不同的。要将Spring的这些不错的功能带入应用程序(如依赖注入),您需要组装所有需要的库(jar文件),并在运行时,并且可能在编译时将它们存入您的类路径。这些依赖关系不是注入的虚拟组件,而是文件系统中的物理资源(通常为)。依赖关系管理的过程包括定位这些资源,存储它们并将其添加到类路径中。依赖关系可以是直接的(例如,我的应用程序依赖于Spring在运行时)或间接(例如我的应用程序取决于<code>commons-dbcp</code>哪个依赖于 <code>commons-pool</code>)。间接依赖关系也被称为“传递性”,它们是最难识别和管理的依赖关系。</span></span></span></span></p> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">如果要使用Spring,您需要获取构成您所需要的Spring部分的jar库的副本。为了使这更容易,Spring被打包为一组尽可能分离依赖关系的模块,例如,如果您不想编写Web应用程序,则不需要spring-web模块。要参照本指南中,我们使用速记命名约定到Spring库模块<code>spring-*</code>或 <code>spring-*.jar,</code>其中<code>*</code>代表该模块的短名称(例如<code>spring-core</code>,<code>spring-webmvc</code>,<code>spring-jms</code>等)。您使用的实际jar文件名通常是与版本号连接的模块名称(例如<em>spring-core-5.0.0.RC2.jar</em>)。</span></span></span></span></p> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">Spring Framework的每个版本都会将工件发布到以下位置:</span></span></span></span></p> </div> <div> <ul style="margin-left:1.5em; margin-right:0px"> <li> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">Maven Central,它是Maven查询的默认存储库,不需要任何特殊配置。Spring的许多常见的库也可以从Maven Central获得,Spring社区的大部分使用Maven进行依赖关系管理,所以这对他们来说很方便。这里的jar的名字是形式<code>spring-*-<version>.jar</code>,Maven groupId是<code>org.springframework</code>。</span></span></span></span></p> </li> <li> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">在专门用于Spring的公共Maven存储库中。除了最终的GA版本,该存储库还承载开发快照和里程碑。jar文件名与Maven Central格式相同,因此这是一个有用的地方,可以让Spring的开发版本与在Maven Central中部署的其他库一起使用。该存储库还包含捆绑包分发zip文件,其中包含所有Spring jar,捆绑在一起以便于下载。</span></span></span></span></p> </li> </ul> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">所以您需要决定的第一件事是如何管理您的依赖关系:我们通常建议使用自动化系统,如Maven,Gradle或Ivy,但您也可以手动下载所有的jar。</span></span></span></span></p> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">下面你将会找到Spring工件的列表。有关每个模块的更完整的描述,请参阅框架模块。</span></span></span></span></p> </div> <table class="table table-bordered table-hover"> <caption style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff">表1. Spring Framework人工制品</span></span></span></caption> <thead> <tr> <th style="border-color:#dedede; text-align:left; vertical-align:top"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff">GroupId的</span></span></span></th> <th style="border-color:#dedede; text-align:left; vertical-align:top"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff">的artifactId</span></span></span></th> <th style="border-color:#dedede; text-align:left; vertical-align:top"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff">描述</span></span></span></th> </tr> </thead> <tbody> <tr> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit"><span style="color:#34302d">org.springframework</span></span></span></span></span></p> </td> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left">spring-aop</p> </td> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit"><span style="color:#34302d">基于代理的AOP支持</span></span></span></span></span></p> </td> </tr> <tr> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit"><span style="color:#34302d">org.springframework</span></span></span></span></span></p> </td> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left">spring-aspects</p> </td> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit"><span style="color:#34302d">基于AspectJ的方面</span></span></span></span></span></p> </td> </tr> <tr> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit"><span style="color:#34302d">org.springframework</span></span></span></span></span></p> </td> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left">spring-beans</p> </td> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit"><span style="color:#34302d">豆支持,包括Groovy</span></span></span></span></span></p> </td> </tr> <tr> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit"><span style="color:#34302d">org.springframework</span></span></span></span></span></p> </td> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left">spring-context</p> </td> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit"><span style="color:#34302d">应用程序上下文运行时,包括调度和远程抽象</span></span></span></span></span></p> </td> </tr> <tr> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit"><span style="color:#34302d">org.springframework</span></span></span></span></span></p> </td> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left">spring-context-support</p> </td> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit"><span style="color:#34302d">支持类将常见的第三方库集成到Spring应用程序上下文中</span></span></span></span></span></p> </td> </tr> <tr> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit"><span style="color:#34302d">org.springframework</span></span></span></span></span></p> </td> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left">spring-core</p> </td> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit"><span style="color:#34302d">许多其他Spring模块使用的核心实用程序</span></span></span></span></span></p> </td> </tr> <tr> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit"><span style="color:#34302d">org.springframework</span></span></span></span></span></p> </td> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left">spring-expression</p> </td> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit"><span style="color:#34302d">Spring表达语言(Spel)</span></span></span></span></span></p> </td> </tr> <tr> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit"><span style="color:#34302d">org.springframework</span></span></span></span></span></p> </td> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left">spring-instrument</p> </td> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit"><span style="color:#34302d">用于JVM自举的仪表代理</span></span></span></span></span></p> </td> </tr> <tr> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit"><span style="color:#34302d">org.springframework</span></span></span></span></span></p> </td> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left">spring-instrument-tomcat</p> </td> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit"><span style="color:#34302d">Tomcat的仪表代理</span></span></span></span></span></p> </td> </tr> <tr> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit"><span style="color:#34302d">org.springframework</span></span></span></span></span></p> </td> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left">spring-jdbc</p> </td> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit"><span style="color:#34302d">JDBC支持包,包括DataSource设置和JDBC访问支持</span></span></span></span></span></p> </td> </tr> <tr> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit"><span style="color:#34302d">org.springframework</span></span></span></span></span></p> </td> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left">spring-jms</p> </td> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit"><span style="color:#34302d">JMS支持包,包括发送/接收JMS消息的帮助类</span></span></span></span></span></p> </td> </tr> <tr> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit"><span style="color:#34302d">org.springframework</span></span></span></span></span></p> </td> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left">spring-messaging</p> </td> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit"><span style="color:#34302d">支持消息架构和协议</span></span></span></span></span></p> </td> </tr> <tr> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit"><span style="color:#34302d">org.springframework</span></span></span></span></span></p> </td> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left">spring-orm</p> </td> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit"><span style="color:#34302d">对象/关系映射,包括JPA和Hibernate支持</span></span></span></span></span></p> </td> </tr> <tr> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit"><span style="color:#34302d">org.springframework</span></span></span></span></span></p> </td> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left">spring-oxm</p> </td> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit"><span style="color:#34302d">对象/ XML映射</span></span></span></span></span></p> </td> </tr> <tr> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit"><span style="color:#34302d">org.springframework</span></span></span></span></span></p> </td> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left">spring-test</p> </td> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit"><span style="color:#34302d">支持单元测试和集成测试Spring组件</span></span></span></span></span></p> </td> </tr> <tr> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit"><span style="color:#34302d">org.springframework</span></span></span></span></span></p> </td> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left">spring-tx</p> </td> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit"><span style="color:#34302d">交易基础设施,包括DAO支持和JCA整合</span></span></span></span></span></p> </td> </tr> <tr> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit"><span style="color:#34302d">org.springframework</span></span></span></span></span></p> </td> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left">spring-web</p> </td> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit"><span style="color:#34302d">基础网络支持,包括Web客户端和基于Web的远程处理</span></span></span></span></span></p> </td> </tr> <tr> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit"><span style="color:#34302d">org.springframework</span></span></span></span></span></p> </td> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left">spring-webmvc</p> </td> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit"><span style="color:#34302d">基于HTTP的Model-View-Controller和REST端点,用于Servlet堆栈</span></span></span></span></span></p> </td> </tr> <tr> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit"><span style="color:#34302d">org.springframework</span></span></span></span></span></p> </td> <td style="background-color:#ffffff; border-color:#dedede"> <p style="text-align:left">spring-websocket</p> </td> <td style="background-color:#ffffff"> <p style="text-align:left"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit"><span style="color:#34302d">WebSocket和SockJS基础架构,包括STOMP消息传递支持</span></span></span></span></span></p> </td> </tr> </tbody> </table> <div> <h5 style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff">Spring依赖和依靠Spring</span></span></span></h5> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">虽然Spring为大量的企业和其他外部工具提供集成和支持,但它有意将其强制性依赖性保持在绝对最小值:您不必定位和下载(甚至自动)大量的jar库,以便使用Spring用于简单的用例。对于基本的依赖注入,只有一个强制性的外部依赖关系,即日志记录(有关日志记录选项的更详细描述,请参见下文)。</span></span></span></span></p> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">接下来,我们概述了配置依赖于Spring的应用程序所需的基本步骤,首先是使用Maven,然后使用Gradle,最后使用Ivy。在任何情况下,如果有什么不清楚,请参阅依赖关系管理系统的文档,或查看一些示例代码 - Spring本身在构建时使用Gradle来管理依赖关系,而我们的示例主要使用Gradle或Maven。</span></span></span></span></p> </div> </div> <div> <h5 style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff">Maven依赖管理</span></span></span></h5> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">如果您使用Maven进行依赖关系管理,则甚至不需要显式提供记录依赖关系。例如,要创建应用程序上下文并使用依赖注入来配置应用程序,您的Maven依赖项将如下所示:</span></span></span></span><br />  </p> <pre> <code class="language-xml"><dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.0.RC2</version> <scope>runtime</scope> </dependency> </dependencies></code></pre> </div> </div> </div> </div> </div> </div> </div> </div> <div style="text-align:start"> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">而已。注意,如果您不需要针对Spring API进行编译,那么范围可以被声明为运行时,通常情况下这是基本依赖注入用例的情况。</span></span></span></span></p> </div> <div style="text-align:start"> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">以上示例适用于Maven Central存储库。要使用Spring Maven存储库(例如,用于里程碑或开发人员快照),您需要在Maven配置中指定存储库位置。完整版本:</span></span></span></span><br />  </p> <pre> <code class="language-xml"><repositories> <repository> <id>io.spring.repo.maven.release</id> <url>http://repo.spring.io/release/</url> <snapshots><enabled>false</enabled></snapshots> </repository> </repositories></code></pre> <div style="text-align:start"> <div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">对于里程碑:</span></span></span></span></p> </div> <div style="margin-left:0px; margin-right:0px"> <div> <pre> <code class="language-xml"><repositories> <repository> <id>io.spring.repo.maven.milestone</id> <url>http://repo.spring.io/milestone/</url> <snapshots><enabled>false</enabled></snapshots> </repository> </repositories></code></pre> </div> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">对于快照:</span></span></span></span></p> </div> <div style="margin-left:0px; margin-right:0px"> <div> <pre> <code class="language-xml"><repositories> <repository> <id>io.spring.repo.maven.snapshot</id> <url>http://repo.spring.io/snapshot/</url> <snapshots><enabled>true</enabled></snapshots> </repository> </repositories></code></pre> </div> </div> </div> <div> <h5 style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff">Maven“物料清单”依赖</span></span></span></h5> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">当使用Maven时,可能会意外混合不同版本的Spring JAR。例如,您可能会发现第三方库或另一个Spring项目会将旧的版本的依赖关系传递给旧版本。如果您忘记自己明确声明直接依赖,可能会出现各种意外问题。</span></span></span></span></p> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">为了克服这些问题,Maven支持“物料清单”(BOM)依赖的概念。您可以导入<code>spring-framework-bom</code>您的<code>dependencyManagement</code> 部分,以确保所有弹簧依赖(直接和传递)都是相同的版本。</span></span></span></span></p> </div> <div style="margin-left:0px; margin-right:0px"> <div> <pre> <code class="language-xml"><dependencyManagement> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-framework-bom</artifactId> <version>5.0.0.RC2</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement></code></pre> </div> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">使用BOM的另一个好处是,您不再需要<code><version></code> 根据Spring Framework工件指定属性:</span></span></span></span></p> </div> <div style="margin-left:0px; margin-right:0px"> <div> <pre> <code class="language-xml"><dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> </dependency> <dependencies></code></pre> </div> </div> </div> <div> <h5 style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff">渐进依赖管理</span></span></span></h5> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">要使用具有<a href="http://www.gradle.org/" rel="nofollow" style="box-sizing:border-box; background:transparent; color:#548e2e; text-decoration:underline; line-height:inherit" target="_blank">Gradle</a>构建系统的Spring存储库,请在该<code>repositories</code>部分中包含相应的URL :</span></span></span></span></p> </div> <div style="margin-left:0px; margin-right:0px"> <div> <pre> <span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="background-color:#f5f5f5"><span style="font-family:Monaco,Menlo,Consolas,"Courier New",monospace"><span style="color:rgba(0, 0, 0, 0.9)"><code>repositories { mavenCentral() <span style="color:#999988"><em>// and optionally...</em></span> maven { url <span style="color:#dd2200"><span style="color:#dd1144">"</span><span style="color:#dd1144">http://repo.spring.io/release</span><span style="color:#dd1144">"</span></span> } }</code></span></span></span></span></span></span></pre> </div> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">您可以更改<code>repositories</code>从URL <code>/release</code>到<code>/milestone</code>或<code>/snapshot</code>适当。一旦存储库被配置,你可以按照通常的Gradle方式声明依赖:</span></span></span></span></p> </div> <div style="margin-left:0px; margin-right:0px"> <div> <pre> <span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="background-color:#f5f5f5"><span style="font-family:Monaco,Menlo,Consolas,"Courier New",monospace"><span style="color:rgba(0, 0, 0, 0.9)"><code>dependencies { compile(<span style="color:#dd2200"><span style="color:#dd1144">"</span><span style="color:#dd1144">org.springframework:spring-context:5.0.0.RC2</span><span style="color:#dd1144">"</span></span>) testCompile(<span style="color:#dd2200"><span style="color:#dd1144">"</span><span style="color:#dd1144">org.springframework:spring-test:5.0.0.RC2</span><span style="color:#dd1144">"</span></span>) }</code></span></span></span></span></span></span></pre> </div> </div> </div> <div> <h5 style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff">常春藤依赖管理</span></span></span></h5> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">如果您喜欢使用<a href="https://ant.apache.org/ivy" rel="nofollow" style="box-sizing:border-box; background:transparent; color:#548e2e; text-decoration:underline; line-height:inherit" target="_blank">Ivy</a>来管理依赖项,那么还有类似的配置选项。</span></span></span></span></p> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">要配置Ivy以指向Spring存储库,请将以下解析器添加到 <code>ivysettings.xml</code>:</span></span></span></span></p> </div> <div style="margin-left:0px; margin-right:0px"> <div> <pre> <code class="language-xml"><resolvers> <ibiblio name="io.spring.repo.maven.release" m2compatible="true" root="http://repo.spring.io/release/"/> </resolvers></code></pre> </div> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">您可以更改<code>root</code>从URL <code>/release/</code>到<code>/milestone/</code>或<code>/snapshot/</code>适当。</span></span></span></span></p> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">配置完成后,您可以按通常的方式添加依赖项。例如(in <code>ivy.xml</code>):</span></span></span></span></p> </div> <div style="margin-left:0px; margin-right:0px"> <div> <pre> <code><dependency org="org.springframework" name="spring-core" rev="5.0.0.RC2" conf="compile->runtime"/>xx</code></pre> </div> </div> </div> <div> <h5 style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff">分发Zip文件</span></span></span></h5> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">虽然使用支持依赖关系管理的构建系统是推荐的获取Spring框架的方法,但仍然可以下载分发zip文件。</span></span></span></span></p> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">分发的拉链发布到Spring Maven Repository(这只是为了方便起见,您不需要Maven或任何其他构建系统才能下载它们)。</span></span></span></span></p> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">要下载一个分发zip打开一个Web浏览器到 http://repo.spring.io/release/org/springframework/spring,并为所需的版本选择相应的子文件夹。分发文件结束<code>-dist.zip</code>,例如spring-framework- {spring-version} -RELEASE-dist.zip。发行的分发也是针对里程碑和 快照发布的。</span></span></span></span></p> </div> </div> </div> <div style="text-align:start"> <h4 style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff">2.3.2。记录</span></span></span></h4> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">Spring的日志记录设置已经修改为Spring 5:它仍然基于Apache Commons Logging API,也称为Jakarta Commons Logging(JCL)。但是,现在<code>spring-core</code> 指的是<code>spring-jcl</code>模块中定制的Commons Logging桥,具有Spring特定的<code>LogFactory</code>实现,它自动地连接到 Log4j 2,SLF4J或JDK自己的<code>java.util.logging</code>(JUL)。该实现类似于JCL-over-SLF4J桥,但具有一系列动态检测的提供程序,类似于JBoss Logging的常见目标(如Hibernate和Undertow所支持的)。</span></span></span></span></p> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">作为一个好处,不再需要像JCL-over-SLF4J这样的外部桥接器,相应地不需要从<code>spring-core</code>依赖关系手动排除标准Commons Logging jar 。相反,它只是在运行时在Spring的自动检测样式中工作:只需将Log4j 2.x或SLF4J放在您的类路径上,而不需要任何额外的桥接jar,或者依靠通过JUL(具有可自定义的JUL设置)的默认日志记录。并且很好地对齐,默认的Hibernate设置将选择相同的通用日志目标。</span></span></span></span></p> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">如果Log4j和SLF4J都存在,则Log4j API将被优选使用(因为它直接匹配JCL的签名,并且本机支持“致命”日志级别以及延迟解析的消息对象),类似于JBoss Logging的提供程序首选项。可以将Log4j配置为委派给SLF4J,否则SLF4J可能被配置为委托给Log4j:请检查其网站上的说明,了解如何在这种混合场景中达成一致的结果。</span></span></span></span></p> </div> <div style="margin-left:0px; margin-right:0px"> <table class="table table-bordered table-hover"> <tbody> <tr> <td style="background-color:none; text-align:center; width:80px"> </td> <td style="background-color:none"> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="background-color:#ebf1e7"><span style="color:rgba(0, 0, 0, 0.6)"><span style="font-family:inherit">从Spring 5起,删除对外部Commons Logging网桥的任何引用,还可以从现有的<code>spring-core</code> 依赖关系设置中任意手动排除标准Commons Logging jar 。您的Log4j或SLF4J或JUL设置将继续工作,无需更改。请注意,您可能仍然需要<code>commons-logging</code>其他库(例如Apache HttpClient,Castor,HtmlUnit)的排除,以便代替Spring的JCL桥接器。</span></span></span></span></span></span></p> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="background-color:#ebf1e7"><span style="color:rgba(0, 0, 0, 0.6)"><span style="font-family:inherit"><code>LogFactory</code>Commons Logging级别的自定义实现将不会被拾取,因为Spring的Bridge不支持定制的commons-logging.properties设置。对于任何其他日志提供程序,请设置相应的SLF4J或JUL桥(您很可能需要其他库,如Hibernate)。请注意,Log4j 1.x已经达到其使用寿命; 请迁移到Log4j 2.x.</span></span></span></span></span></span></p> </div> <div> <p><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="background-color:#ebf1e7"><span style="color:rgba(0, 0, 0, 0.6)"><span style="font-family:inherit">如果您遇到Spring Commons Logging实现的任何其他问题,请考虑排除<code>spring-jcl</code>和切换到标准<code>commons-logging</code>工件(支持<code>commons-logging.properties' setup) or to `jcl-over-slf4j</code>。</span></span></span></span></span></span></p> </div> </td> </tr> </tbody> </table> </div> <div> <h5 style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff">使用Log4j 2.x</span></span></span></h5> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">Log4j 2本身就是将原来的Log4j项目(1.x现在是EOL)重新进行重写。从Spring 5开始,嵌入式日志桥将在类路径上可用时自动委托给Log4j 2.x。</span></span></span></span></p> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">因此,要使用Log4j与Spring,所有你需要做的就是把Log4j的在类路径,并为其提供一个配置文件(<code>log4j2.xml</code>,<code>log4j2.properties</code>或其他 支持的配置格式)。对于Maven用户,所需的最小依赖是:</span></span></span></span></p> </div> <div style="margin-left:0px; margin-right:0px"> <div> <pre> <code class="language-xml"><dependencies> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.8.2</version> </dependency> </dependencies></code></pre> </div> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">如果您还希望启用SLF4J委托Log4j,例如默认使用SLF4J的其他库,则还需要以下依赖关系:</span></span></span></span></p> </div> <div style="margin-left:0px; margin-right:0px"> <div> <pre> <code class="language-xml"><dependencies> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j-impl</artifactId> <version>2.8.2</version> </dependency> </dependencies></code></pre> </div> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">以下是<code>log4j2.xml</code>登录控制台的示例:</span></span></span></span></p> </div> <div style="margin-left:0px; margin-right:0px"> <div> <pre> <code class="language-xml"><?xml version="1.0" encoding="UTF-8"?> <Configuration status="WARN"> <Appenders> <Console name="Console" target="SYSTEM_OUT"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> </Console> </Appenders> <Loggers> <Logger name="org.springframework.beans.factory" level="DEBUG"/> <Root level="error"> <AppenderRef ref="Console"/> </Root> </Loggers> </Configuration></code></pre> </div> </div> </div> <div> <h5 style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff">使用SLF4J与Logback</span></span></span></h5> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">Java的简单日志门面(SLF4J)是Spring通常使用的其他库使用的流行API。它通常与Logback一起使用, 它是SLF4J API的本机实现,因此在添加到应用程序类路径时由Spring自动检测:</span></span></span></span></p> </div> <div style="margin-left:0px; margin-right:0px"> <div> <pre> <code class="language-xml"><dependencies> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.2</version> </dependency> </dependencies></code></pre> </div> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">或者,您还可以将SLF4J配置为委托给Log4j(见上文)或JUL,特别是对于默认使用SLF4J的其他库。请注意,所有图书馆通过同一个日志门面并不重要; 这只是重要的,他们最终委托给同一个日志提供商。所以当Spring可以直接去Log4j时,其他库可能会通过Log4j的SLF4J绑定,或类似于JUL。</span></span></span></span></p> </div> </div> <div> <h5 style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff">使用JUL(java.util.logging)</span></span></span></h5> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit"><code>java.util.logging</code>如果类路径中没有检测到Log4j或SLF4J API,Spring将默认委派。所以没有特殊的依赖关系:只要<code>java.util.logging</code>在独立的应用程序(在JDK级别使用自定义或默认的JUL设置)或应用程序服务器的日志系统(和它的系统范围的JUL设置)。</span></span></span></span></p> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">请注意,该<code>java.logging</code>模块在JDK 9中默认不存在,因为它不包括在内<code>java.base</code>。当使用Spring与Log4j或SLF4J时,这可以正常工作,因为在这种情况下不引用JUL API。但是,当选择使用JUL作为默认日志提供程序时,请记住激活该<code>java.logging</code>模块。</span></span></span></span></p> </div> </div> <div> <h5 style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff">Commons登录WebSphere</span></span></span></h5> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">Spring应用程序可以在本身提供JCL实现的容器上运行,例如IBM的WebSphere Application Server(WAS)。这不会引起问题本身,而是导致需要了解的两种不同的场景:</span></span></span></span></p> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">在“父第一”ClassLoader委托模型(WAS中的默认值)中,应用程序将始终选择Commons Logging提供的服务器版本,委托给WAS记录子系统(实际上基于JUL)。JCL的应用程序提供的变体,无论是Spring 5还是JCL-over-SLF4J桥,将随着任何本地包含的日志提供程序而被有效地忽略。</span></span></span></span></p> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">使用“父进程”委托模式(常规Servlet容器中的默认值,但WAS上的显式配置选项),将提取应用程序提供的Commons Logging变体,使您能够设置本地包含的日志提供程序,例如Log4j或Logback,在您的应用程序。在没有本地日志提供程序的情况下,Spring(如常规Commons Logging)将默认委托给JUL,有效地记录到WebSphere的日志记录子系统,如“父第一”方案。</span></span></span></span></p> </div> <div> <p style="margin-left:0px; margin-right:0px"><span style="color:#34302d"><span style="font-family:"Varela Round",sans-serif"><span style="background-color:#ffffff"><span style="font-family:inherit">总而言之,我们建议您将“Spring”应用程序部署在“最后一个”模式中,因为它自然允许本地提供程序以及服务器的日志子系统。</span></span></span></span></p> </div> </div> </div> </div>