“Java”的版本间的差异

来自tomtalk
跳转至: 导航搜索
compareto, equals, == 在java中相对于值和引用
Tom讨论 | 贡献
hello world
 
(未显示同一用户的70个中间版本)
第3行: 第3行:
  
  
==AES加密==
+
==基础入门==
  
java代码
+
===hello world===
  
 
<source lang="java">
 
<source lang="java">
    // 密钥
+
public class HelloWorld{
     private final static String secretKey = "key123";
+
     public static void main(String[] args) { 
     private final static String salt = "0123456789abcdef" ;//KeyGenerators.string().generateKey();
+
        System.out.println("Hello World!");  
 +
     }
 +
}
 +
</source>
  
    /**
+
<source lang="bash">
    * 加密
+
#运行java程序
    *
+
$ javac HelloWorld.java
    * @param plainString 明文
+
$ java HelloWorld  #文件名后面不要带.class后缀,否则会报错“错误:找不到或无法加载主类”。
    * @return
+
Hello World!
    */
+
    private static String encrypt(String plainString) {
+
        // 明文
+
        byte[] byteArray = plainString.getBytes();
+
  
        // 加密,设置密钥和随机数
+
#打包可运行的jar文件
        byte[] cipherArrayTemp = Encryptors.standard(secretKey, salt).encrypt(byteArray);
+
$ jar -cvfe HelloWorld.jar HelloWorld HelloWorld.class
        byte[] cipherArray = Base64.encode(cipherArrayTemp);
+
$ java -jar HelloWorld.jar
        return new String(cipherArray);
+
Hello World!
    }
+
</source>
  
    /**
+
===java打印数组===
    * 解密
+
    *
+
    * @param cipherString 密文
+
    * @return
+
    */
+
    private static String decrypt(String cipherString) {
+
        // 密文
+
        byte[] byteArray = cipherString.getBytes();
+
        byte[] plainArrayTemp = Base64.decode(byteArray);
+
  
        // 解密
+
将数组转化为有序的List打印出来
        byte[] plainArray = Encryptors.standard(secretKey, salt).decrypt(plainArrayTemp);
+
 
         return new String(plainArray);
+
<source lang="java">
 +
import java.util.Arrays;
 +
 
 +
public class Hello {
 +
    public static void main(String[] args)
 +
         String pool[] = {"dog", "cat", "pig", "main", "fish"};
 +
        System.out.println(Arrays.asList(pool));
 
     }
 
     }
 +
}
 
</source>
 
</source>
  
javascript代码
+
===JAVA中int转String类型有三种方法===
  
https://cdn.bootcss.com/crypto-js/3.1.9-1/crypto-js.js
+
<source lang="java">
 +
int i = 123;
  
<source lang="javascript">
+
String s = String.valueOf(i);
  // 可在第三方网站解密
+
 
  let word = 'hello world!';
+
String s = Integer.toString(i);
  let key = 'key123';
+
 
  var iv = '0123456789abcdef';
+
String s = i + "";
  var attr = {
+
 
    iv: iv,
+
//字符转数字
    mode: CryptoJS.mode.CBC,
+
String str = "123456";
    padding: CryptoJS.pad.Pkcs7
+
 
  };
+
i = Integer.parseInt(str);  
  console.log(CryptoJS.AES.encrypt(word, key, attr).toString());
+
  console.log(CryptoJS.AES.decrypt(CryptoJS.AES.encrypt(word, key), key).toString(CryptoJS.enc.Utf8));
+
 
</source>
 
</source>
  
==Base64,Base32,Base16进制的区别==
+
===compareto, equals, == 在java中相对于值和引用===
  
刚刚接触Base时,没有太注重区分Base64,Base32,Base16的区别,后面每一次遇到就要去一个一个试,这次花了点时间记下了一下Base的区别,顺便写一下。
+
1.compareto是判断一个对象的值是否包含包含另一个对象的值;
  
在看了大佬们的分析后http://blog.51cto.com/xiaoqin00/1718416,我截取了几个关键的记住这些就能区分Base之间的区别了:
+
例如"abcds".compareto("ab")就是判断abcds中是否含有ab
 +
 
 +
2.equals 是比较两个对象的值 
  
Base64:
+
3.==是比较两个对象内存地址 
  
包含大写字母(A-Z),小写字母(a-z),数字(0-9)以及+/;
+
<source lang="java">
 +
String A = "abcd";
 +
String B = "abcd";  
  
Base32:
+
A == B;      //ture 
 +
A.equals(B);  //true
  
而Base32中只有大写字母(A-Z)和数字234567;
+
String A = new String("abcd");
 +
String B = new String("abcd");
 +
A == B;        //false 
 +
A.equals(B);  //true
 +
</source>
  
Base16:
+
===java中List的初始化问题===
  
而Base16就是16进制,他的范围是数字(0-9),字母(ABCDEF);
+
我声明了一个
  
顺便说一句,当ASCll用Base加密达不到所对应的位数的时候用=号补齐;
+
<source lang="java">
 +
List<String[]> users = null;
 +
</source>
  
在这里附带由三种Base加密的:I love you!
+
然后 使用 add()方法想这个List中加入元素的时候为啥会出现空指针啊。
  
Base64:SSBsb3ZlIHlvde+8gQ==
+
List当然不能初始化为null,
  
Base32:JEQGY33WMUQHS33V566IC===
+
<source lang="java">
 +
List<String[]> users = new LinkedList<String[]>();
 +
</source>
  
Base16:49206c6f766520796f75efbc81
+
就可以了,然后添加元素就不会出现空指针了。
 +
 
 +
===一个很诡异的bug,原来是由int精度引起的===
 +
 
 +
<source lang="java">
 +
import java.util.*;
 +
import java.text.SimpleDateFormat;
 +
 
 +
public class hello {
 +
   
 +
 
 +
    public static void main(String[] args) { 
 +
 
 +
        int[] ebbing = {1, 2, 4, 7, 15, 30, 50, 70, 100, 150, 200, 150, 200, 300, 400};
 +
 
 +
        getToday((long)ebbing[0] * 3600 * 24 * 1000);
 +
        getToday((long)ebbing[1] * 3600 * 24 * 1000);
 +
        getToday((long)ebbing[2] * 3600 * 24 * 1000);
 +
        getToday((long)ebbing[3] * 3600 * 24 * 1000);
 +
        getToday((long)ebbing[4] * 3600 * 24 * 1000);
 +
        getToday((long)ebbing[5] * 3600 * 24 * 1000);
 +
        getToday((long)ebbing[6] * 3600 * 24 * 1000);
 +
        getToday((long)ebbing[7] * 3600 * 24 * 1000);
 +
        getToday((long)ebbing[8] * 3600 * 24 * 1000);
 +
    }
 +
 
 +
    // int为整数类型,在存储的时候,用4个字节存储,范围为-2,147,483,648到2,147,483,647。
 +
    // 原用的是getToday(int offset_ms),这样在第6个日期,就超出范围了。
 +
    public static String getToday(long offset_ms) {
 +
 
 +
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
 +
Date date = new Date(System.currentTimeMillis() + offset_ms);
 +
String today = dateFormat.format(date);
 +
 
 +
        System.out.println(offset_ms + " " + today);
 +
 +
return today;
 +
    }
 +
}
 +
</source>
 +
 
 +
<source lang="bash">
 +
# java hello
 +
86400000 2014-05-14
 +
172800000 2014-05-15
 +
345600000 2014-05-17
 +
604800000 2014-05-20
 +
1296000000 2014-05-28
 +
2592000000 2014-06-12
 +
4320000000 2014-07-02
 +
6048000000 2014-07-22
 +
8640000000 2014-08-21
 +
</source>
 +
 
 +
===<T>(尖括号)是什么意思?===
 +
 
 +
它与java中的泛型有关。如果我提到ArrayList<String>这意味着我只能将String类型对象添加到该ArrayList。
 +
 
 +
Java中泛型的两个主要好处是:
 +
 
 +
* 减少程序中的强制转换数量,从而减少程序中潜在错误的数量。
 +
* 提高代码清晰度。
 +
 
 +
===Java map 详解 - 用法、遍历、排序、常用API等===
 +
 
 +
https://baike.xsoftlab.net/view/250.html
 +
 
 +
* HashMap:最常用的Map,它根据键的HashCode 值存储数据,根据键可以直接获取它的值,具有很快的访问速度。HashMap最多只允许一条记录的键为Null(多条会覆盖);允许多条记录的值为 Null。非同步的。
 +
* TreeMap:能够把它保存的记录根据键(key)排序,默认是按升序排序,也可以指定排序的比较器,当用Iterator 遍历TreeMap时,得到的记录是排过序的。TreeMap不允许key的值为null。非同步的。
 +
* Hashtable:与 HashMap类似,不同的是:key和value的值均不允许为null;它支持线程的同步,即任一时刻只有一个线程能写Hashtable,因此也导致了Hashtale在写入时会比较慢。
 +
* LinkedHashMap:保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的.在遍历的时候会比HashMap慢。key和value均允许为空,非同步的。
 +
 
 +
===@validated和@valid不同点===
 +
 
 +
https://www.jianshu.com/p/89a800eda155
 +
https://segmentfault.com/a/1190000011712893
 +
 
 +
* @Valid可以注解在成员属性(字段)上,但是@Validated不行。
 +
* @valid只能用在controller。@Validated可以用在其他被spring管理的类上。
 +
 
 +
===Java bean 是个什么概念?===
 +
 
 +
Java语言欠缺属性、事件、多重继承功能。所以,如果要在Java程序中实现一些面向对象编程的常见需求,只能手写大量胶水代码。Java Bean正是编写这套胶水代码的惯用模式或约定。这些约定包括getXxx、setXxx、isXxx、addXxxListener、XxxEvent等。遵守上述约定的类可以用于若干工具或库。
 +
 
 +
==Tomcat==
 +
===java开发环境===
 +
 
 +
* 安装JDK
 +
* 设置环境变量
 +
    JAVA_HOME = C:\Program Files\Java\jdk1.8.0_66
 +
    PATH = C:\ProgramData\Oracle\Java\javapath;%JAVA_HOME%\bin;
 +
    CLASSPATH = %JAVA_HOME%\lib; %JAVA_HOME%\lib\dt.jar; %JAVA_HOME%\lib\tools.jar;
 +
* 安装tomcat
 +
* 安装IntellJ idea
 +
* 新建项目,关联tomcat
 +
* 部署项目:把IntelliJ项目的web目录上传到外网虚拟站点根目录就可以了。
 +
 
 +
<source lang="bash">
 +
jar xf tomcat.war
 +
chown -R www.www ./*
 +
service tomcat restart
 +
</source>
 +
 
 +
数据库连接不上,把mysql-connector-java-5.1.18-bin.jar放到tomcat/lib目录下,重启。
  
 
==Spring==
 
==Spring==
第195行: 第307行:
 
这里还需要说明的是:这种方法不能访问WEB-INF目录下的静态资源,也就是js目录必须是web根(可能是webapp,webContent等)目录下,否则是不能引用的。
 
这里还需要说明的是:这种方法不能访问WEB-INF目录下的静态资源,也就是js目录必须是web根(可能是webapp,webContent等)目录下,否则是不能引用的。
  
==如何在mac上安装gradle==
+
===使用spring ResponseEntity处理http响应===
  
首先,先download最新版本的gradle,网址如下:
+
https://blog.csdn.net/neweastsun/article/details/81142870
  
http://www.gradle.org/get-started
+
使用spring时,达到同一目的通常有很多方法,对处理http响应也是一样。本文我们学习如何通过ResponseEntity设置http相应内容、状态以及头信息。
  
然后将下载下来的zip包放在你要安装的路径上,我安装在
+
ResponseEntity标识整个http相应:状态码、头部信息以及相应体内容。因此我们可以使用其对http响应实现完整配置。
  
<source lang="html5">
+
如果需要使用ResponseEntity,必须在请求点返回,通常在spring rest中实现。ResponseEntity是通用类型,因此可以使用任意类型作为响应体。
/usr/local/bin;
+
</source>
+
  
然后打开电脑上的.bash_profile文件,输入以下命令:
+
<source lang="java">
 +
@GetMapping("/customHeader")
 +
ResponseEntity<String> customHeader() {
 +
    HttpHeaders headers = new HttpHeaders();
 +
    headers.add("Custom-Header", "foo");
  
<source lang="bash">
+
    return new ResponseEntity<>("Custom header set", headers, HttpStatus.OK);
GRADLE_HOME=/usr/local/bin/gradle-1.8;
+
}
export GRADLE_HOME
+
export PATH=$PATH:$GRADLE_HOME/bin
+
 
</source>
 
</source>
  
然后再在console上输入以下命令:
+
===Controller中返回数据总结(ResponseEntity,@ResponseBody,@ResponseStatus)===
  
<source lang="bash">
+
https://www.cnblogs.com/Jason-Xiang/p/10244075.html
source ~/.bash_profile
+
 
 +
在传统的开发过程中,我们的控制CONTROLLER层通常需要转向一个JSP视图;但随着WEB2.0相关技术的崛起,我们很多时候只需要返回数据即可,而不是一个JSP页面。
 +
 
 +
* ResponseEntity:表示整个HTTP响应:状态代码,标题和正文。因此,我们可以使用它来完全配置HTTP响应,它是一个对象。
 +
* @ResponseBody:返回json格式的结果
 +
* @ResponseStatus:返回状态
 +
 
 +
<source lang="java">
 +
@GetMapping("/hello")
 +
public ResponseEntity<String> hello() {
 +
    return new ResponseEntity<>(new User(‘jdon’), HttpStatus.OK);
 +
}
 +
//返回的是JSON字符串:[ { ‘name’: 'jdon'}]
 
</source>
 
</source>
  
这样就安装成功啦,可以通过以下命令来查看是否安装成功。
+
在类级别使用@Controller标注情况下, @ResponseBody注解告诉返回的对象将自动序列化为JSON,并通过回控制器的HttpResponse对象。
  
<source lang="bash">
+
<source lang="java">
gradle -version
+
@Controller
 +
public class XXXController{
 +
    @ResponseBody
 +
    public User postResponseController(@RequestBody LoginForm loginForm) {
 +
        return new User("Thanks For Posting!!!");
 +
    }
 +
}
 +
//将返回客户端JSON字符串:[ { ‘name’: Thanks For Posting!!!"}]
 
</source>
 
</source>
  
==java.lang.ClassNotFoundException: com.mysql.jdbc.Driver==
+
在@RestController注解了类的情况下,我们就不需要再使用@ResponseBody了。
  
Add mysql.connector-java-x.x.x-bin.jar to your libraries folder. No need to import anything. Have a good one.
+
@ResponseStatus
  
'''别忘了重户tomcat'''。
+
ResponseStatus虽然只是规定了返回的状态,但是只需要标注在方法上,简单,而且状态码与返回类型分离,比较清晰。我们将上面返回对象列表的代码使用ResponseStatus改写如下,注意类级别@RestController:
  
==在IntellIj IDEA中JSP页面 cannot resolve method getParameter("")的解决方案==
+
<source lang="java">
 +
@RestController
 +
public class XXXController{
 +
    @ResponseStatus(HttpStatus.FOUND)
 +
    public User postResponseController() {
 +
        return new User("Thanks For Posting!!!");
 +
    }
 +
}
 +
//这也会返回客户端JSON字符串:[ { ‘name’: Thanks For Posting!!!"}]
 +
</source>
  
原来,是我在导入jar包的时候应该选择Platform setting下的global libraries,然后只要导入servlet.jar即可!
+
这样的代码更加专注于业务。
  
==一个很诡异的bug,原来是由int精度引起的==
+
Spring还允许我们直接访问javax.servlet.http.HttpServletResponse对象; 我们只需要将它声明为方法参数:
  
 
<source lang="java">
 
<source lang="java">
import java.util.*;  
+
@GetMapping("/manual")
import java.text.SimpleDateFormat;
+
public void manual(HttpServletResponse response) throws IOException {
 +
    response.setHeader("Custom-Header", "foo");
 +
    response.setStatus(200);
 +
    response.getWriter().println("Hello World!");
 +
}
 +
</source>
 +
由于Spring在底层实现之上提供了抽象和附加功能,因此如果以这种方式直接操纵响应,会失去很多Spring提供方便功能。
  
public class hello {
+
===注解@RequestParam与@RequestBody的使用场景===
   
+
  
    public static void main(String[] args) { 
+
https://cloud.tencent.com/developer/article/1414464
  
        int[] ebbing = {1, 2, 4, 7, 15, 30, 50, 70, 100, 150, 200, 150, 200, 300, 400};
+
注解@RequestParam接收的参数是来自requestHeader中,即请求头。通常用于GET请求,比如常见的url:
  
        getToday((long)ebbing[0] * 3600 * 24 * 1000);
+
http://localhost:8081/spring-boot-study/novel/findByAuthorAndType?author=唐家三少&type=已完结
        getToday((long)ebbing[1] * 3600 * 24 * 1000);
+
        getToday((long)ebbing[2] * 3600 * 24 * 1000);
+
        getToday((long)ebbing[3] * 3600 * 24 * 1000);
+
        getToday((long)ebbing[4] * 3600 * 24 * 1000);
+
        getToday((long)ebbing[5] * 3600 * 24 * 1000);
+
        getToday((long)ebbing[6] * 3600 * 24 * 1000);
+
        getToday((long)ebbing[7] * 3600 * 24 * 1000);
+
        getToday((long)ebbing[8] * 3600 * 24 * 1000);
+
    }
+
  
    // int为整数类型,在存储的时候,用4个字节存储,范围为-2,147,483,648到2,147,483,647。
+
注解@RequestBody接收的参数是来自requestBody中,即请求体。一般用于处理非 Content-Type: application/x-www-form-urlencoded编码格式的数据,比如:application/json、application/xml等类型的数据。
    // 原用的是getToday(int offset_ms),这样在第6个日期,就超出范围了。
+
    public static String getToday(long offset_ms) {
+
  
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
+
===RestTemplate===
Date date = new Date(System.currentTimeMillis() + offset_ms);
+
String today = dateFormat.format(date);
+
  
        System.out.println(offset_ms + " " + today);
+
https://blog.csdn.net/itguangit/article/details/78825505
+
return today;
+
    }
+
}
+
</source>
+
  
<source lang="bash">
+
REST与RPC几乎没有任何关系。RPC是面向服务的,并关注于行为和动作;而REST是面向资源的,强调描述应用程序的事物和名词。
# java hello
+
86400000 2014-05-14
+
172800000 2014-05-15
+
345600000 2014-05-17
+
604800000 2014-05-20
+
1296000000 2014-05-28
+
2592000000 2014-06-12
+
4320000000 2014-07-02
+
6048000000 2014-07-22
+
8640000000 2014-08-21
+
</source>
+
  
==poi导出excel文件、下载==
+
RestTemplate定义了36个与REST资源交互的方法,其中的大多数都对应于HTTP的方法。
 +
其实,这里面只有11个独立的方法,其中有十个有三种重载形式,而第十一个则重载了六次,这样一共形成了36个方法。
  
<source lang="java">
+
# put() PUT 资源到特定的URL
@RequestMapping(value = "batchCardNoExport", method = RequestMethod.GET)
+
# getForEntity() 发送一个HTTP GET请求,返回的ResponseEntity包含了响应体所映射成的对象
public void batchCardNoExport(HttpServletRequest request, HttpServletResponse response) throws Exception {
+
# getForObject() 发送一个HTTP GET请求,返回的请求体将映射为一个对象
    // 创建Excel的工作书册 Workbook,对应到一个excel文档
+
# postForEntity()POST 数据到一个URL,返回包含一个对象的ResponseEntity,这个对象是从响应体中映射得到的
    HSSFWorkbook wb = new HSSFWorkbook();
+
# postForObject() POST 数据到一个URL,返回根据响应体匹配形成的对象
 +
# postForLocation() POST 数据到一个URL,返回新创建资源的URL
 +
# delete() 在特定的URL上对资源执行HTTP DELETE操作
 +
# headForHeaders() 发送HTTP HEAD请求,返回包含特定资源URL的HTTP头
 +
# optionsForAllow() 发送HTTP OPTIONS请求,返回对特定URL的Allow头信息
 +
# exchange()在URL上执行特定的HTTP方法,返回包含对象的ResponseEntity,这个对象是从响应体中映射得到的
 +
# execute() 在URL上执行特定的HTTP方法,返回一个从响应体映射得到的对象
  
    // 创建Excel的工作sheet,对应到一个excel文档的tab
+
==Spring Boot==
    HSSFSheet sheet = wb.createSheet("sheet1");
+
  
    HSSFRow row;
+
===入门--Hello World===
    HSSFCell cell;
+
  
    for (int i = 0; i < 60; i++) {
+
https://blog.csdn.net/duchao123duchao/article/details/73011717
        row = sheet.createRow(i); // 创建Excel的sheet的一行
+
        for (int j = 0; j < 30; j++) {
+
            cell = row.createCell(j); // 创建一个Excel的单元格
+
            cell.setCellValue("hello world " + i + " " + j);
+
        }
+
    }
+
  
    response.setContentType("application/vnd.ms-excel");
+
Spring Boot是一种简化原有Spring应用繁杂配置的微框架。使开发者从繁杂的各种配置文件中解脱出来,通过Spring Boot能够很简单、很快速构建一个优秀的、产品级的Spring基础应用。运行Spring Boot和运行普通的Java类一样简单,仅仅run一下Spring Boot的入口main()方法即可开启应用;你也可以把Spring Boot应用打成jar,在命令行执行java -jar xxx.jar命令来运行;或者打成war包部署到服务器下运行服务器来开启应用。Spring Boot微框架考虑到了Spring平台和第三方库的情况,所以你需要做的则是最少的操作或配置。
    response.setHeader("Content-Disposition", "attachment; filename=filename.xls");
+
    wb.write(response.getOutputStream()); // Write workbook to response.
+
    wb.close();
+
}
+
</source>
+
  
==基础入门==
+
Spring Boot特点:
  
===hello world===
+
# 创建优秀的Spring Web应用;
 +
# 直接嵌入了Tomcat、Jetty和Undertow等三个Web服务器,很方便的部署应用;
 +
# 提供一系列不同类型的starter POMs简化原有Spring应用繁杂的Maven配置;
 +
# 充分利用JavaConfig的配置模式以及“约定优于配置”的理念,自动化配置、装配Spring,简化了人为的配置;
 +
# 提供生产就绪型功能,如指标,健康检查和外部配置(?不理解这点,求指教);
 +
# 没有代码产生、没有XML文件要求配置。
  
 
<source lang="java">
 
<source lang="java">
public class HelloWorld{  
+
@RestController //里面的方法都以 json 格式输出,表示这个入口类也是控制类,=@Controller+@ResponseBody
     public static void main(String[] args) {
+
@SpringBootApplication
         System.out.println("Hello World!");  
+
public class DemoApplication {
 +
    @RequestMapping("/")  //请求的映射路由
 +
    public String home(){
 +
        return "hello world";
 +
    }
 +
     public static void main(String[] args) {
 +
         SpringApplication.run(DemoApplication.class, args);
 
     }
 
     }
 
}
 
}
 
</source>
 
</source>
  
===java打印数组===
+
===spring boot 指定启动端口===
  
将数组转化为有序的List打印出来
+
<source lang="text">
 +
src/main/resources/application.properties
 +
server.port=8081
 +
</source>
  
<source lang="java">
+
===如何禁用 Spring Boot DEBUG 和 Spring Boot INFO 日志?===
import java.util.Arrays;
+
<source lang="text">
 
+
logging.level.org.springframework=OFF
public class Hello {
+
logging.level.root=OFF
    public static void main(String[] args) { 
+
spring.main.banner-mode=off
        String pool[] = {"dog", "cat", "pig", "main", "fish"};
+
        System.out.println(Arrays.asList(pool));
+
    }
+
}
+
 
</source>
 
</source>
 +
===SpringApplication启动原理===
  
===JAVA中int转String类型有三种方法===
+
http://www.majunwei.com/view/201708231840127244.html
  
<source lang="java">
+
# SpringApplication.run(args)
int i = 123;
+
# 初始化监听器
 +
# 发布ApplicationStarterEvent事件
 +
# 装配环境
 +
# 发布ApplicatinEnvironmentPreparedEvent事件
 +
# 打印Banner
 +
# 创建ApplicationContext
 +
# 装配Context
 +
# 发布ApplicationPreparedEvent事件(注意源码中是空的,没有真正发布)
 +
# 注册、加载等等…
 +
# 发布ApplicationPreparedEvent事件(注意这里才是真正发布了Prepared事件)
 +
# refreshContent
 +
# afterContent
 +
# 发布ApplicationReadyEvent事件
  
String s = String.valueOf(i);
+
===springboot中 @Autowired @Resource @Bean===
  
String s = Integer.toString(i);
+
https://www.jianshu.com/p/70e7e7bc652e
  
String s = i + "";
+
===Spring Data JPA 与 MyBatis简单对比===
  
//字符转数字
+
https://www.jianshu.com/p/3927c2b6acc0
String str = "123456";
+
  
i = Integer.parseInt(str);
+
JPA是Java Persistence API的简称,是一套Sun官方提出的Java持久化规范。
</source>
+
  
===compareto, equals, == 在java中相对于值和引用===
+
Spring Data JPA是Spring Data的子模块。使用Spring Data,使得基于“repositories”概念的JPA实现更简单和容易。Spring Data JPA的目标是大大简化数据访问层代码的编码。作为使用者,我们只需要编写自己的repository接口,接口中包含一些个性化的查询方法,Spring Data JPA将自动实现查询方法。
  
1.compareto是判断一个对象的值是否包含包含另一个对象的值;
+
JPA默认使用hibernate作为ORM实现,所以,一般使用Spring Data JPA即会使用hibernate。我们再看看hibernate的官方概念,Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架,hibernate可以自动生成SQL语句,自动执行,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。
  
例如"abcds".compareto("ab")就是判断abcds中是否含有ab
+
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
 
+
2.equals 是比较两个对象的值 
+
  
3.==是比较两个对象内存地址 
+
这样看,Spring Data JPA与MyBatis对比,起始也就是hibernate与MyBatis对比。所以,我们直接来比较后两者。
  
<source lang="java">
+
hibernate是一个自动化更强、更高级的框架,毕竟在java代码层面上,省去了绝大部分sql编写,取而代之的是用面向对象的方式操作关系型数据库的数据。而MyBatis则是一个能够灵活编写sql语句,并将sql的入参和查询结果映射成POJOs的一个持久层框架。
String A = "abcd";
+
String B = "abcd";
+
  
A == B;      //ture 
+
这样看来MyBatis更适合于面向关系(或面向数据、或面向过程)的系统设计方法,这样的系统一般称为“事务脚步”系统(事务脚步(Transaction Script) 出自Martin Fowler 2004年所著的企业应用架构模式(Patterns of Enterprise Application Architecture))。而hibernate(也可以说Spring Data JPA)更适合于构建领域模型类的系统。当然,我们也不能说MyBatis无法构建领域模型驱动的系统,而hibernate无法构建事务脚步系统。只是用MyBatis构建领域模型要做更多、更脏、更累的工作;而用hibernate构建一个事务脚本系统有些大材小用,数据的查询反而没那么灵活。
A.equals(B);  //true
+
  
String A = new String("abcd");
+
===Spring Data Jpa的使用===
String B = new String("abcd");
+
A == B;        //false 
+
A.equals(B);  //true
+
</source>
+
  
===java中List的初始化问题===
+
https://www.jianshu.com/p/c23c82a8fcfc
  
我声明了一个
+
====相关配置====
 
+
<source lang="text">
<source lang="java">
+
server:
List<String[]> users = null;
+
  port: 8080
 +
  servlet:
 +
  context-path: /
 +
spring:
 +
  datasource:
 +
    url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false
 +
    username: root
 +
    password: mysql123
 +
  jpa:
 +
    database: MySQL
 +
    database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
 +
    show-sql: true
 +
    hibernate:
 +
    ddl-auto: update
 
</source>
 
</source>
  
然后 使用 add()方法想这个List中加入元素的时候为啥会出现空指针啊。
+
ddl-auto
  
List当然不能初始化为null,
+
* create:每次运行程序时,都会重新创建表,故而数据会丢失
 +
* create-drop:每次运行程序时会先创建表结构,然后待程序结束时清空表
 +
* upadte:每次运行程序,没有表时会创建表,如果对象发生改变会更新表结构,原有数据不会清空,只会更新(推荐使用)
 +
* validate:运行程序会校验数据与数据库的字段类型是否相同,字段不同会报错
 +
* none: 禁用DDL处理
  
<source lang="java">
+
====简单的REST CRUD示例====
List<String[]> users = new LinkedList<String[]>();
+
</source>
+
  
就可以了,然后添加元素就不会出现空指针了。
+
写一个类继承JpaRepository<T, ID>,需要写两个泛型,第一个代表要存储的实体类型,第二个代表主键类型,例如写一个User类的仓储如下:
  
==jdk Path设置==
+
<source lang="java">
 
+
public interface UserRepository extends JpaRepository<User, Long> {
只要在Path变量的头部添加如下路径:
+
}
 
+
C:\Program Files\Java\jdk1.5.0\bin;
+
 
+
就可以了。
+
 
+
==java开发环境==
+
 
+
* 安装JDK
+
* 设置环境变量
+
    JAVA_HOME = C:\Program Files\Java\jdk1.8.0_66
+
    PATH = C:\ProgramData\Oracle\Java\javapath;%JAVA_HOME%\bin;
+
    CLASSPATH = %JAVA_HOME%\lib; %JAVA_HOME%\lib\dt.jar; %JAVA_HOME%\lib\tools.jar;
+
* 安装tomcat
+
* 安装IntellJ idea
+
* 新建项目,关联tomcat
+
* 部署项目:把IntelliJ项目的web目录上传到外网虚拟站点根目录就可以了。
+
 
+
<source lang="bash">
+
jar xf tomcat.war
+
chown -R www.www ./*
+
service tomcat restart
+
 
</source>
 
</source>
 
数据库连接不上,把mysql-connector-java-5.1.18-bin.jar放到tomcat/lib目录下,重启。
 
  
 
==常用代码==
 
==常用代码==
第510行: 第624行:
 
</source>
 
</source>
  
==bookmarks==
+
==应用==
* [http://www.blogjava.net/bibi/archive/2006/07/18/58701.html 收藏的JAVA面试题大全 - 鱼上游 - BlogJava]
+
===AES加密===
* [http://www.233.com/Java/zhenti/20100817/094328887.html java程序员面试题及解答-Java认证考试-考试大]
+
* [http://www.douban.com/note/62156073/ 【java 专业】最全 JAVA面试题]
+
* [http://www.wangzhanjianghu.com/ 面试题-java面试题|面试题及答案|php 面试题|c 面试题|面试问题|java程序员面试题|android面试题|c#面试题|php面试题]
+
* [http://www.mianwww.com/html/category/it-interview/java/ Java面试题笔试题专栏 专业精心收集!绝对史上最全! - IT公司面试手册]
+
* [http://www.portnov.com/FreeResumeSample/JavaDeveloperResume.htm Free Java Developer Resume Samples | Portnov Computer School]
+
* [http://www.java.net/ Welcome | Java.net]
+
* [http://hk.design-demo.com/wp/archives/391 CentOS 5 使用 yum 安裝 Tomcat | WordPress]
+
* [http://java.chinaitlab.com/dynamic/792394.html Google选择Jetty放弃Tomcat-Java频道-中国IT实验室]
+
* [http://baike.baidu.com/view/25374.htm tiles_百度百科]
+
* [http://www.linuxso.com/architecture/13124.html jetty的基本安装配置 - Linux安全网 - Linux操作系统_Linux 命令_Linux教程_Linux黑客]
+
* [http://www.cnblogs.com/eafy/archive/2007/10/24/906792.html 什么是Jetty - eafy.ye - 博客园]
+
* [http://baike.baidu.com/view/171821.htm Jmeter_百度百科]
+
  
==Java在Web开发语言上败给了PHP==
+
java代码
  
PHP的主要语言开发者之一、Zend公司的创始人之一Andi Gutmans最近在blog中直言不讳地批评了Java语言。他指出,目前Java厂商试图在JVM上提供动态语言实现的路子根本不对,Java已经输掉了Web开发语言的战争,网络营销培训PHP是事实上的标准和胜利者。
+
<source lang="java">
 +
    // 密钥
 +
    private final static String secretKey = "key123";
 +
    private final static String salt = "0123456789abcdef" ;//KeyGenerators.string().generateKey();
  
Gutmans的这篇文章在技术界引发了强烈争议,很对人对此有不同的意见,我在这里就阐述一下我对PHP和Java两种语言的看法。
+
    /**
 +
    * 加密
 +
    *
 +
    * @param plainString 明文
 +
    * @return
 +
    */
 +
    private static String encrypt(String plainString) {
 +
        // 明文
 +
        byte[] byteArray = plainString.getBytes();
  
我早先曾经在《Perl、PHP、ASP、JSP技术比较》一文中对比过PHP和Java的异同,简而言之,PHP是一种解释执行的脚本语言,语法和C语言类似,易学易用,不懂电脑的非专业人员稍经学习也能使用PHP.而Java要先编译成Class文件,然后在Java虚拟机上执行,Java开发需要熟悉Java语法以及一些核心的架构,从而实现一种可复用的、跨平台的软件,Java比PHP要难学的多。
+
        // 加密,设置密钥和随机数
 +
        byte[] cipherArrayTemp = Encryptors.standard(secretKey, salt).encrypt(byteArray);
 +
        byte[] cipherArray = Base64.encode(cipherArrayTemp);
 +
        return new String(cipherArray);
 +
    }
  
实际上,从技术架构来说,Java语言相比PHP有明显的优势,Java使用的是面向对象的系统设计方法,而PHP还是采用面向过程的开发方法。PHP只能实现简单的分布式两层或三层的架构,而JAVA可以实现多层架构。数据库层(持久化层)、应用(业务)逻辑层、表示逻辑层彼此分开,而且现在不同的层都已经有一些成熟的开发框架的支持。例如Struts就是利用Java的web开发技术实现了MVC的设计模式,而在业务逻辑层也有Spring框架,数据库持久化层有Hibernate等框架。这些框架可以方便开发者高效、合理、科学得架构多层的商业应用。从数学运算和数据库访问速度来讲,Java的性能也优于PHP.实际上,对于跨平台的大型的企业应用系统来讲,Java几乎已经成为唯一的选择(微软.NET不支持跨平台),但是在于Web网站应用开发来讲,Java却面临着被PHP边缘化的危险,几乎所有的虚拟主机都支持PHP+MySQL,而支持Java的却少之又少,在资源上,网上有不计其数的PHP资源,很多著名的大型网站(例如Facebook、Mediawiki等)都是基于PHP的,而成功的Java网站却寥寥无几,这又是什么原因呢?
+
    /**
 +
    * 解密
 +
    *
 +
    * @param cipherString 密文
 +
    * @return
 +
    */
 +
    private static String decrypt(String cipherString) {
 +
        // 密文
 +
        byte[] byteArray = cipherString.getBytes();
 +
        byte[] plainArrayTemp = Base64.decode(byteArray);
  
Java的理念是“一次编写,到处运行”,Java在应用框架底下的架构是无与伦比的,远胜过其他任何语言,Java的框架利于大型的协同编程开发,系统易维护、可复用性较好。而PHP很容易自学,让热备能快速简洁地编写代码,适合于快速开发,中小型应用系统,开发成本低。在调试、发布上,PHP也较Java简单。
+
        // 解密
 +
        byte[] plainArray = Encryptors.standard(secretKey, salt).decrypt(plainArrayTemp);
 +
        return new String(plainArray);
 +
    }
 +
</source>
  
理念上的不同导致了Java和PHP在Web应用开发上显示了不同的结果,尽管Java的数学计算和数据库访问都有优势,架构也相当完美,但是PHP却可以简单轻松地支持高强度Web访问,能够快速开发应用,支持PHP的虚拟主机多如牛毛,使得用PHP开发一个网站比用Java开发一个网站要快得多,容易的多。Java所拥有的优点只适合传统的以软件项目为核心的开发模式,而PHP更适合于以客户为核心的SaaS的开发模式,因此,PHP目前在Web网站开发的优势完全是因为Web网站开发的特殊性而导致的,并非编程语言特性所决定。
+
javascript代码
  
因此,PHP在Web网站开发语言的战争中已经慢慢将Java抛在了后面,Java要想在Web网站开发上奋起直追,的确应该多听听Andi Gutmans的意见,彻底改变一下思路才行,否则两者的差距只能是越来越远。
+
https://cdn.bootcss.com/crypto-js/3.1.9-1/crypto-js.js
  
另外,虽然网络营销培训在国际上LAMP(Linux+Apache+Mysql+Php)架构已经占领了统治地位,但是在中国国内还有一个怪胎,就是基于微软的Windows Server+IIS+SqlServer+ASP/ASP.NET的架构,从理论上说,微软的这一套架构也能实现不错的性能,只可惜Windows和SqlServer价格不菲,整个架构在性能上比起LAMP不仅没有什么优势,反而还有不少劣势,因此微软的这一套家伙在国际市场上吃不开。而国内使用微软盗版则可以忽略成本,而ASP的易学易用性不逊于PHP,甚至连IT外行都能够使用,因此在国内也有不小的市场。但是随着中国在保护知识产权方面的日趋完善,免费的LAMP依旧是未来的趋势。(fblww-0120)
+
<source lang="javascript">
 +
  // 可在第三方网站解密
 +
  let word = 'hello world!';
 +
  let key = 'key123';
 +
  var iv = '0123456789abcdef';
 +
  var attr = {
 +
    iv: iv,
 +
    mode: CryptoJS.mode.CBC,
 +
    padding: CryptoJS.pad.Pkcs7
 +
  };
 +
  console.log(CryptoJS.AES.encrypt(word, key, attr).toString());
 +
  console.log(CryptoJS.AES.decrypt(CryptoJS.AES.encrypt(word, key), key).toString(CryptoJS.enc.Utf8)); 
 +
</source>
  
==61条Java面向对象设计的经验原则==
+
===Base64,Base32,Base16进制的区别===
  
(1)所有数据都应该隐藏在所在的类的内部。
+
刚刚接触Base时,没有太注重区分Base64,Base32,Base16的区别,后面每一次遇到就要去一个一个试,这次花了点时间记下了一下Base的区别,顺便写一下。
  
(2)类的使用者必须依赖类的共有接口,但类不能依赖它的使用者。
+
在看了大佬们的分析后http://blog.51cto.com/xiaoqin00/1718416,我截取了几个关键的记住这些就能区分Base之间的区别了:
  
(3)尽量减少类的协议中的消息。
+
Base64:
  
(4)实现所有类都理解的最基本公有接口[例如,拷贝操作(深拷贝和浅拷贝)、相等性判断、正确输出内容、从ASCII描述解析等等].
+
包含大写字母(A-Z),小写字母(a-z),数字(0-9)以及+/;
  
(5)不要把实现细节(例如放置共用代码的私有函数)放到类的公有接口中。
+
Base32:
  
如果类的两个方法有一段公共代码,那么就可以创建一个防止这些公共代码的私有函数。
+
而Base32中只有大写字母(A-Z)和数字234567;
  
(6)不要以用户无法使用或不感兴趣的东西扰乱类的公有接口。
+
Base16:
  
(7)类之间应该零耦合,或者只有导出耦合关系。也即,一个类要么同另一个类毫无关系,要么只使用另一个类的公有接口中的操作。
+
而Base16就是16进制,他的范围是数字(0-9),字母(ABCDEF);
  
(8)类应该只表示一个关键抽象。
+
顺便说一句,当ASCll用Base加密达不到所对应的位数的时候用=号补齐;
  
包中的所有类对于同一类性质的变化应该是共同封闭的。一个变化若对一个包影响,则将对包中的所有类产生影响,而对其他的包不造成任何影响 .(9)把相关的数据和行为集中放置。
+
在这里附带由三种Base加密的:I love you!
  
设计者应当留意那些通过get之类操作从别的对象中获取数据的对象。这种类型的行为暗示着这条经验原则被违反了。
+
Base64:SSBsb3ZlIHlvde+8gQ==
  
(10)把不相关的信息放在另一个类中(也即:互不沟通的行为)。
+
Base32:JEQGY33WMUQHS33V566IC===
  
朝着稳定的方向进行依赖。
+
Base16:49206c6f766520796f75efbc81
  
(11)确保你为之建模的抽象概念是类,而不只是对象扮演的角色。类应当统一地共享工作。
+
===poi导出excel文件、下载===
  
(13)在你的系统中不要创建全能类/对象。对名字包含Driver、Manager、System、Susystem的类要特别多加小心。
+
<source lang="java">
 +
@RequestMapping(value = "batchCardNoExport", method = RequestMethod.GET)
 +
public void batchCardNoExport(HttpServletRequest request, HttpServletResponse response) throws Exception {
 +
    // 创建Excel的工作书册 Workbook,对应到一个excel文档
 +
    HSSFWorkbook wb = new HSSFWorkbook();
  
规划一个接口而不是实现一个接口。
+
    // 创建Excel的工作sheet,对应到一个excel文档的tab
 +
    HSSFSheet sheet = wb.createSheet("sheet1");
  
(14)对公共接口中定义了大量访问方法的类多加小心。大量访问方法意味着相关数据和行为没有集中存放。
+
    HSSFRow row;
 +
    HSSFCell cell;
  
(15)对包含太多互不沟通的行为的类多加小心。
+
    for (int i = 0; i < 60; i++) {
 +
        row = sheet.createRow(i); // 创建Excel的sheet的一行
 +
        for (int j = 0; j < 30; j++) {
 +
            cell = row.createCell(j); // 创建一个Excel的单元格
 +
            cell.setCellValue("hello world " + i + " " + j);
 +
        }
 +
    }
  
这个问题的另一表现是在你的应用程序中的类的公有接口中创建了很多的get和set函数。
+
    response.setContentType("application/vnd.ms-excel");
 +
    response.setHeader("Content-Disposition", "attachment; filename=filename.xls");
 +
    wb.write(response.getOutputStream()); // Write workbook to response.
 +
    wb.close();
 +
}
 +
</source>
  
(16)在由同用户界面交互的Java面向对象模型构成的应用程序中,模型不应该依赖于界面,界面则应当依赖于模型。
+
==如何在mac上安装gradle==
  
(17)尽可能地按照现实世界建模(我们常常为了遵守系统功能分布原则、避免全能类原则以及集中放置相关数据和行为的原则而违背这条原则) .(18)从你的设计中去除不需要的类。
+
首先,先download最新版本的gradle,网址如下:
  
一般来说,我们会把这个类降级成一个属性。
+
http://www.gradle.org/get-started
  
(19)去除系统外的类。
+
然后将下载下来的zip包放在你要安装的路径上,我安装在
  
系统外的类的特点是,抽象地看它们只往系统领域发送消息但并不接受系统领域内其他类发出的消息。
+
<source lang="html5">
 +
/usr/local/bin;
 +
</source>
  
(20)不要把操作变成类。质疑任何名字是动词或者派生自动词的类,特别是只有一个有意义行为的类。考虑一下那个有意义的行为是否应当迁移到已经存在或者尚未发现的某个类中。
+
然后打开电脑上的.bash_profile文件,输入以下命令:
  
(21)我们在创建应用程序的分析模型时常常引入代理类。在设计阶段,我们常会发现很多代理没有用的,应当去除。
+
<source lang="bash">
 +
GRADLE_HOME=/usr/local/bin/gradle-1.8;
 +
export GRADLE_HOME
 +
export PATH=$PATH:$GRADLE_HOME/bin
 +
</source>
  
(22)尽量减少类的协作者的数量。
+
然后再在console上输入以下命令:
  
一个类用到的其他类的数目应当尽量少。
+
<source lang="bash">
 +
source ~/.bash_profile
 +
</source>
  
(23)尽量减少类和协作者之间传递的消息的数量。
+
这样就安装成功啦,可以通过以下命令来查看是否安装成功。
  
(24)尽量减少类和协作者之间的协作量,也即:减少类和协作者之间传递的不同消息的数量。
+
<source lang="bash">
 +
gradle -version
 +
</source>
  
(25)尽量减少类的扇出,也即:减少类定义的消息数和发送的消息数的乘积。
+
==IntelliJ IDEA 配置==
  
(26)如果类包含另一个类的对象,那么包含类应当给被包含的对象发送消息。也即:包含关系总是意味着使用关系。
+
https://www.cnblogs.com/knowledgesea/p/11158412.html
  
(27)类中定义的大多数方法都应当在大多数时间里使用大多数数据成员。
+
IDEA 清除类中无用的import包:Ctrl + Alt + O
  
(28)类包含的对象数目不应当超过开发者短期记忆的容量。这个数目常常是6.当类包含多于6个数据成员时,可以把逻辑相关的数据成员划分为一组,然后用一个新的包含类去包含这一组成员。
+
自动导入缺失的包:Alt + Enter
  
(29)让系统功能在窄而深的继承体系中垂直分布。
+
格式化代码:Ctrl + Alt + L
  
(30)在实现语义约束时,最好根据类定义来实现。这常常会导致类泛滥成灾,在这种情况下,约束应当在类的行为中实现,通常是在构造函数中实现,但不是必须如此。
+
==swagger常用注解说明==
  
(31)在类的构造函数中实现语义约束时,把约束测试放在构造函数领域所允许的尽量深的包含层次中。
+
https://www.jianshu.com/p/12f4394462d5
  
(32)Java面向对象中,约束所依赖的语义信息如果经常改变,那么最好放在一个集中式的第3方对象中。
+
<source lang="java">
 
+
@Api:用在类上,说明该类的作用。
(33)约束所依赖的语义信息如果很少改变,那么最好分布在约束所涉及的各个类中。
+
@ApiOperation:用在方法上,说明方法的作用。
 +
@ApiParam:请求属性。
 +
@ApiResponse:响应配置。
 +
@ApiResponses:响应集配置。
 +
@ResponseHeader:响应头设置。
  
(34)类必须知道它包含什么,但是不能知道谁包含它。
+
@ApiModel:描述一个Model的信息,(这种一般用在post创建的时候,使用@RequestBody这样的场景,请求参数无法使用@ApiImplicitParam注解进行描述的时候)。
 
+
@ApiModelProperty:描述一个model的属性。
(35)共享字面范围(也就是被同一个类所包含)的对象相互之间不应当有使用关系。
+
</source>
 
+
(36)继承只应被用来为特化层次结构建模。
+
 
+
(37)派生类必须知道基类,基类不应该知道关于它们的派生类的任何信息。
+
 
+
(38)基类中的所有数据都应当是私有的,不要使用保护数据。
+
 
+
类的设计者永远都不应该把类的使用者不需要的东西放在公有接口中。
+
 
+
(39)在理论上,继承层次体系应当深一点,越深越好。
+
 
+
(40)在实践中,继承层次体系的深度不应当超出一个普通人的短期记忆能力。一个广为接受的深度值是6.(41)所有的抽象类都应当是基类。
+
 
+
(42)所有的基类都应当是抽象类。
+
 
+
(43)把数据、行为和/或接口的共性尽可能地放到继承层次体系的高端。
+
 
+
(44)如果两个或更多个类共享公共数据(但没有公共行为),那么应当把公共数据放在一个类中,每个共享这个数据的类都包含这个类。
+
 
+
(45)如果两个或更多个类有共同的数据和行为(就是方法),那么这些类的每一个都应当从一个表示了这些数据和方法的公共基类继承。
+
 
+
(46)如果两个或更多个类共享公共接口(指的是消息,而不是方法),那么只有他们需要被多态地使用时,他们才应当从一个公共基类继承。
+
 
+
(47)对对象类型的显示的分情况分析一般是错误的。在大多数这样的情况下,设计者应当使用多态。
+
 
+
(48)对属性值的显示的分情况分析常常是错误的。类应当解耦合成一个继承层次结构,每个属性值都被变换成一个派生类。
+
 
+
(49)不要通过继承关系来为类的动态语义建模。试图用静态语义关系来为动态语义建模会导致在运行时切换类型。
+
 
+
(50)不要把类的对象变成派生类。对任何只有一个实例的派生类都要多加小心。
+
 
+
(51)如果你觉得需要在运行时刻创建新的类,那么退后一步以认清你要创建的是对象。现在,把这些对象概括成一个类。
+
 
+
(52)在派生类中用空方法(也就是什么也不做的方法)来覆写基类中的方法应当是非法的。
+
 
+
(53)不要把可选包含同对继承的需要相混淆。把可选包含建模成继承会带来泛滥成灾的类。
+
 
+
(54)在创建继承层次时,试着创建可复用的框架,而不是可复用的组件。
+
 
+
(55)如果你在设计中使用了多重继承,先假设你犯了错误。如果没犯错误,你需要设法证明。
+
 
+
(56)只要在Java面向对象设计中用到了继承,问自己两个问题:(1)派生类是否是它继承的那个东西的一个特殊类型?(2)基类是不是派生类的一部分?
+
 
+
(57)如果你在一个面向对象设计中发现了多重继承关系,确保没有哪个基类实际上是另一个基类的派生类。
+
 
+
(58)在面向对象设计中如果你需要在包含关系和关联关系间作出选择,请选择包含关系。
+
 
+
(59)不要把全局数据或全局函数用于类的对象的薄记工作。应当使用类变量或类方法。
+
 
+
(60)Java面向对象设计者不应当让物理设计准则来破坏他们的逻辑设计。但是,在对逻辑设计作出决策的过程中我们经常用到物理设计准则。
+
 
+
(61)不要绕开公共接口去修改对象的状态。
+
 
+
==Java的辉煌,还能延续多久?==
+
 
+
Oracle对Sun的收购引发了人们对Java未来的一丝担心,Oracle能否继续保持Java的开放性,面对Ruby、Python或PHP等一批轻量型语言的崛起,Java能否继续保持其在开发领域的领导地位?
+
 
+
14年前,Sun公司的一位营销天才把一门试验性的跨平台语言由象征踏实的Oak(橡树),改名为香气四溢的Java(咖啡)时,可能他没有想到这门语言能有后来的辉煌。事实上,如果现在Sun想为这门语言改名,以准确体现其在计算机行业的地位,似乎Oak更形象。今天,虽然Java语言并非真正意义上的遍地开花,但它已经出现在众多场合和设备中,而且它享有运行稳定、设计精良的美名;Java代码也许无法主导所有计算机或所有平台,但它离成为通用语言已近在咫尺。
+
Java之父詹姆斯戈斯林(JamesGosling)在Oracle主办的OpenWorld大会上登台发言时阐述了这一点。他调出JavaFX幻灯片,上面是一连串统计数字:超过8.5亿个具有Java功能的桌面机和大约100亿个具有Java功能的设备。实际上,Java虚拟机在电子设备中司空见惯:电子书阅读器Kindle、蓝光磁盘播放机和智能电话(包括不太智能的手机)等。iPhone(手机上网)应用程序可以在成千上万部iPhone上运行,但Java嵌入在26亿部手机上,从不太智能、20美元就能买到的手机,到最新一代的黑莓和Android手机无一不包。
+
请戈斯林到OpenWorld大会上演讲,只是Oracle掌门人拉里埃利森(LarryEllison)希望向工程师们一再保证这门语言前途光明的手段之一。Oracle想要并购Sun,但它仍得等待欧洲监管部门批准这一决策。美国政府已开了绿灯,但欧洲政府官员由于担心MySQL的发展还没有同意这一起交易。戈斯林和Sun董事长麦克尼利(McNealy)都表示,一旦并购工作完成,Java会从Oracle得到比以往更多的关注和资源。
+
从近期来看,埃利森传达的信号也许不是很重要,因为如今Java已成气候,要改变发展方向也并不容易。当然,也有一些人认为,Oracle的商业模式太不一样了,所以它必然会对Java生态系统的每个部分进行重大变化。总体来说,每拿出一个Java可能变化的理由,就有同样充足的理由表明Oracle可能还是希望保持现状。
+
 
+
企业级应用是主战场
+
 
+
Java最先在服务器端找到了自己的位置,未来这个领域仍是有望看到Java虚拟机的主要地方。对Oracle的所有产品来说,大型服务器也是主要的安身之处,所以出现这对组合自在情理当中。虽然PHP编程员青睐MySQL,但对数据密集型的企业应用来说,许多最要紧的项目还是使用基于Oracle的架构封装而成的Java,这种情况应该不会很快发生变化。
+
Sun称,GlassFish应用服务器每个月的下载量超过100万人次,Tomcat等比较旧的平台仍然很常见。由于Java这项技术备受推崇、运行速度快、真正跨平台,大型企业(如银行和保险公司)对Java开发人员求之若渴。
+
不过,Java不再被认为是最新最酷的语法。一些编程员对静态类型语言的结构满腹牢骚,纷纷改用更新颖或更简单的语言,比如Ruby、Python或PHP。现在许多较简单的Web应用程序就是用这些语言开发而成的,因为它们编写的代码容易修改,能快速建立原型。然而,这些使用便捷的新语言常常离不开Java:Ruby开发人员常常使用JRuby(基于Java实现的Ruby语言),因为Java虚拟机能够更出色地处理繁重任务、释放多个线程。Jython(基于Java实现的Python语言)也相似。
+
Java现在正在加入一些最新的编程技术,以此遏制这些新语言大举入侵。Grails明显模仿了Ruby onRails的许多简单的说明性模式;Grails这种框架利用名为Hibernate的数据库中间件,把Groovy等脚本插件结合起来。Groovy本身添加了众多的动态选项便于代码解释,同时可以直接链接至Java应用编程接口(API)的任何部分。甚至不需要考虑Python或Ruby,因为Groovy凭借一种精巧、现代的语法,让Java编程员可以使用似乎变化无穷的庞大库和底层稳若磐石的虚拟机。
+
 
+
走上移动之路
+
 
+
Java手机的数量(估计约26亿部)委实惊人,因为市面上许多最简单的手机里面都运行Java平台微型版(Java ME)。这让Wattpad.com等公司得以构建在整个第三世界都能顺畅运行的文档阅读平台。
+
不过,运行Java的智能电话数量相对少一点。iPhone的巨大成功激励许多人重新学习ObjectiveC,这门语言让编程员对于内存使用等一些系统问题提高了控制能力。Java为编程员隐藏了大部分底层问题,这是个优点,但前提是不需要管理内存等资源,因为要是垃圾收集出现一个小失误,有些游戏就运行不了。可遗憾的是,因为电池续航时间是极其重要的一个因素,智能电话需要比几乎其他任何平台更严格的资源管理。
+
不过,Java编程员仍然很吃香,因为黑莓手机在其新平台上继续采用JavaME:它为手机的情景模式(profile)添加了支持触摸屏和方向感应器的功能。而Android存在不可预知的因素。由于谷歌开放了Android的使用,许多手机厂商搭上Android这辆彩车。
+
谷歌的Android建立在开源Apache Harmony及其类上,而不是建立在Sun开发的Java开发工具包(JDK)和JavaME上。对使用Eclipse编写代码的人来说,它们看上去几乎一模一样。在其他许多情况下也无关紧要,因为Android开发使用了很多XML表单,但如果这两套开发框架离对方渐行渐远,这种分裂可能会变成大问题。
+
 
+
收复桌面阵地
+
 
+
大多数人仍然认为Java在桌面端从来没有取得成功,这是过去。如今,Java正在缓慢而稳步地渗入到现代操作系统的各个角落。虽然用Swing编写的标准应用程序因试图定位在每个平台的最基本部分而继续遭殃,但是有了像JavaFX和WebStart这些比较新的开发平台和框架,就有可能通过Web有效地部署软件。本地平台可处理Java归档(JAR)的所有缓存工作。只要点击链接,有时偶尔随后点击几下授予权限的对话框,软件就可以安装及更新,还可以随时运行。
+
JavaFX仍然是一个名副其实的未知因素。图形功能现在可与Adobe的Flash相竞争;计算引擎可支持大部分的JavaAPI,但这门语言是一门奇怪的混合语言,融合了正宗Java、JavaScript及其他的一些标记语言。其代码比正规的Java简单,所以Java编程员又要学习新的东西。不过,对极具互动性的桌面工具而言,新的动画类也许值得花时间学习。WebStart正在继续慢慢改进通过浏览器直接把软件部署到桌面的功能。
+
 
+
抢占嵌入式领域
+
 
+
Java还在人们最预料不到的地方茁壮成长。虽然C编程人员可能从来不会承认Java虚拟机巧妙处理存储区、快速运行的功能,但Java在非智能手机、机顶盒、嵌入式芯片、Kindle及其他低功耗设备取得的成功表明:Java虚拟机完全有能力在嵌入式应用方面一展身手。Java的普及性还帮助编程人员从大平台迁移到小平台。虽然为大型机开发企业级应用软件改成开发小型嵌入式代码并不简单,但Java标准大大简化了这种转变,这让其他许多工具自叹弗如。
+
Java程序包也在变得越来越小巧。戈斯林用尘埃来形容一台硬币大小、能够识别Java的计算机。JavaCard是面向这类小型程序包的一种虚拟机和API,它即将迎来3.0版,这个里程碑式版本将增添网络连接功能。尽管这些小不点还没有小得足以放入到人的眼睛中,但直接与互联网通话的功能却让它们显得极具诱惑力。
+
 
+
合作伙伴会分道扬镳?
+
 
+
所有开发人员的最大担心是:要是Oracle收购Sun的交易尘埃落定,会出现什么样的利益冲突变化?Oracle是靠收取大笔的软件许可费成长壮大,其软件可运行在客户想要购买的任何硬件上。而另一方面,Sun通常是免费赠送软件,然后通过销售服务器赚到一些钱。这些经销策略也许不会立即发生变化,因为惯性实在太太了,但谁也不知道将来Oracle会做出怎样的决策。
+
一些人认为,Oracle过去在收取大笔许可费方面屡试不爽,只会鼓励埃利森对Sun采取类似的手法。也许Oracle的销售团队眼下就在垂涎这个机会:针对Java以前免费的地方开始逐步提高许可费。为了避免重新编写Java平台企业版(JavaEE)应用软件,许多企业很可能宁可支付每个CPU 100美元、200美元甚至100万美元的费用。
+
批评人士指出,Oracle很容易开发出新版Java虚拟机,针对不同的市场推出不同的性能级别。桌面虚拟机可能保持免费,Oracle甚至可能会掏钱请电脑厂商来推销Java和JavaFX,而处理极限多线程方面的性能改进可能会收取非常高的费用。从用户身上捞钱有好多法子,许可费相比之下往往便宜得多:要是让拒不服从的编程员先学习一门新语言,然后重新编写代码库,那成本高多了。
+
但也有人认为,Oracle也许不会采用这一招。一名接近Sleepycat(这家开源数据库公司在2006年被Oracle收购)的消息人士表示,Oracle已把技术队伍的规模扩大了约一倍,而所有双许可模式原封不动。软件仍然采用开源或商业许可证这两种形式。如果Oracle像Sleepycat那样对待Java,社区许可及其他方案仍然会跟以前一样免费、随处可得,同时有更多的工程师来改进代码。
+
与其他各大Java合作伙伴的长期关系方面仍存在更深层的问题。谷歌继续支持ApacheHarmony,这个代码超过125万行的项目似乎一心要破坏Sun作为世界中心的地位。IBM输掉了争夺Sun的竞标战,现在发现竞争对手Oracle的实力更强劲了。IBM设计了Eclipse开发工具,可能也会开始把Java平台带往另一个方向。
+
其他合作伙伴的态度比较激烈。SAP公司首席技术官VishalSikka一再要求Sun发布Java社区进程(JCP),着重提到了Oracle在2007年提出的方案:将控制权交由一家开放、独立、与厂商中立的标准组织,标准组织的所有成员在机会均等的前提下参与。虽然Oracle对相关细节基本保持缄默,但可以认为,这家公司会因为从Sun承袭过来的一些观点而重新赢得尊重。
+
但是,尽管其他合作伙伴可能会参与恫吓的举动,但他们可能会考虑度的问题,因为大家其实是相互牵制的,任何过激的行为都极可能会被阻止,因为大家都认识到一次编写、到处运行理念具有的优势。如果为Android手机编写的代码无法很容易地迁移至索尼蓝光播放机或Glassfish服务器,另一门语言就有机会应运而生。实际上已经有多家公司在编写工具包,让用户可以在iPhone上轻松运行Ruby on Rails或Python软件。
+
另外,许多这些比较新的语言可能会成为不可小觑的竞争对手,而暗斗过多只会帮助它们攻城掠地。现在有几十种非常好、知名度小一点的开源程序包,只要忠实的爱好者稍加转换,通常就能把它们移植到每个平台上。比如,Python已经是一些科学领域的主要语言,谷歌选择Python、而不是Java作为其应用引擎(AppEngine)支持的第一种语言。虽然IBM、Oracle和谷歌在争夺主导权的竞争中可能会相互排挤,但它们必须认识到:所有人都受益于标准化,而不是垄断。要是谁敢过于排挤别人、企图一手控制Java,其他厂商可能会奔向其竞争对手。
+
 
+
Java也开应用程序商店?
+
 
+
Java代码库仍相当有凝聚力、相对标准化,这个事实惹得众人猜测:Sun(如果合并案完成,还有Oracle)到底会怎样利用Java的普及性来大发其财,又不提高许可费、挤压每个人?如果有人开发出一种面向整个Java生态系统的应用程序商店(AppStore),从而像销售面向iPhone的应用程序那样销售用Java编写的小组件(widget)它们可以在桌面、手机、蓝光播放机或可以使用Java的其他任何平台上运行,将会怎么样?
+
最近已经有了面向Android手机的一批数量可观的应用程序,Sun也在谋划一家Java商店,好让人们只需把应用程序拖到桌面上,或者只要再编一点代码,就可以把各应用程序结合起来,从而让它们可以在Java世界的几乎每个角落里运行。不过,处理截然不同的屏幕和用户界面还是个挑战。
+
设想一下这种场景有多吸引人:开发人员编写的某个应用程序在Android手机上运行着,他在办公桌面上处理任务,回到家后在客厅的蓝光播放机上顺畅运行。
+
 
+
把Java应用程序带到坐沙发的人面前甚至有点出人意料,因为Java这门语言在被叫做Oak的早期阶段,本意就是运行在机顶盒上。这种远景将依赖于Java平台的最大优点:普及性和跨平台的稳定性,也许这些优点会帮助Java给其发明者带来滚滚收入。
+
 
+
==收藏==
+
 
+
http://www.javacoder.cn
+

2021年6月6日 (日) 10:15的最后版本



目录

基础入门

hello world

public class HelloWorld{ 
    public static void main(String[] args) {  
        System.out.println("Hello World!"); 
    }
}
#运行java程序
$ javac HelloWorld.java
$ java HelloWorld  #文件名后面不要带.class后缀,否则会报错“错误:找不到或无法加载主类”。
Hello World!
 
#打包可运行的jar文件
$ jar -cvfe HelloWorld.jar HelloWorld HelloWorld.class
$ java -jar HelloWorld.jar
Hello World!

java打印数组

将数组转化为有序的List打印出来

import java.util.Arrays; 
 
public class Hello { 
    public static void main(String[] args) {  
        String pool[] = {"dog", "cat", "pig", "main", "fish"};
        System.out.println(Arrays.asList(pool));
    }
}

JAVA中int转String类型有三种方法

int i = 123;
 
String s = String.valueOf(i);
 
String s = Integer.toString(i);
 
String s = i + "";
 
//字符转数字
String str = "123456";
 
i = Integer.parseInt(str);

compareto, equals, == 在java中相对于值和引用

1.compareto是判断一个对象的值是否包含包含另一个对象的值;

例如"abcds".compareto("ab")就是判断abcds中是否含有ab

2.equals 是比较两个对象的值

3.==是比较两个对象内存地址

String A = "abcd";
String B = "abcd"; 
 
A == B;       //ture   
A.equals(B);  //true
 
String A = new String("abcd");
String B = new String("abcd");
A == B;        //false  
A.equals(B);   //true

java中List的初始化问题

我声明了一个

List<String[]> users = null;

然后 使用 add()方法想这个List中加入元素的时候为啥会出现空指针啊。

List当然不能初始化为null,

List<String[]> users = new LinkedList<String[]>();

就可以了,然后添加元素就不会出现空指针了。

一个很诡异的bug,原来是由int精度引起的

import java.util.*; 
import java.text.SimpleDateFormat;
 
public class hello { 
 
 
    public static void main(String[] args) {  
 
        int[] ebbing = {1, 2, 4, 7, 15, 30, 50, 70, 100, 150, 200, 150, 200, 300, 400};
 
        getToday((long)ebbing[0] * 3600 * 24 * 1000); 
        getToday((long)ebbing[1] * 3600 * 24 * 1000); 
        getToday((long)ebbing[2] * 3600 * 24 * 1000); 
        getToday((long)ebbing[3] * 3600 * 24 * 1000); 
        getToday((long)ebbing[4] * 3600 * 24 * 1000); 
        getToday((long)ebbing[5] * 3600 * 24 * 1000); 
        getToday((long)ebbing[6] * 3600 * 24 * 1000); 
        getToday((long)ebbing[7] * 3600 * 24 * 1000); 
        getToday((long)ebbing[8] * 3600 * 24 * 1000); 
    } 
 
    // int为整数类型,在存储的时候,用4个字节存储,范围为-2,147,483,648到2,147,483,647。
    // 原用的是getToday(int offset_ms),这样在第6个日期,就超出范围了。
    public static String getToday(long offset_ms) {
 
    	SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); 
		Date date = new Date(System.currentTimeMillis() + offset_ms);
		String today = dateFormat.format(date);
 
        System.out.println(offset_ms + " " + today); 
 
		return today;
    } 
}
# java hello
86400000 2014-05-14
172800000 2014-05-15
345600000 2014-05-17
604800000 2014-05-20
1296000000 2014-05-28
2592000000 2014-06-12
4320000000 2014-07-02
6048000000 2014-07-22
8640000000 2014-08-21

<T>(尖括号)是什么意思?

它与java中的泛型有关。如果我提到ArrayList<String>这意味着我只能将String类型对象添加到该ArrayList。

Java中泛型的两个主要好处是:

  • 减少程序中的强制转换数量,从而减少程序中潜在错误的数量。
  • 提高代码清晰度。

Java map 详解 - 用法、遍历、排序、常用API等

https://baike.xsoftlab.net/view/250.html

  • HashMap:最常用的Map,它根据键的HashCode 值存储数据,根据键可以直接获取它的值,具有很快的访问速度。HashMap最多只允许一条记录的键为Null(多条会覆盖);允许多条记录的值为 Null。非同步的。
  • TreeMap:能够把它保存的记录根据键(key)排序,默认是按升序排序,也可以指定排序的比较器,当用Iterator 遍历TreeMap时,得到的记录是排过序的。TreeMap不允许key的值为null。非同步的。
  • Hashtable:与 HashMap类似,不同的是:key和value的值均不允许为null;它支持线程的同步,即任一时刻只有一个线程能写Hashtable,因此也导致了Hashtale在写入时会比较慢。
  • LinkedHashMap:保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的.在遍历的时候会比HashMap慢。key和value均允许为空,非同步的。

@validated和@valid不同点

https://www.jianshu.com/p/89a800eda155 https://segmentfault.com/a/1190000011712893

  • @Valid可以注解在成员属性(字段)上,但是@Validated不行。
  • @valid只能用在controller。@Validated可以用在其他被spring管理的类上。

Java bean 是个什么概念?

Java语言欠缺属性、事件、多重继承功能。所以,如果要在Java程序中实现一些面向对象编程的常见需求,只能手写大量胶水代码。Java Bean正是编写这套胶水代码的惯用模式或约定。这些约定包括getXxx、setXxx、isXxx、addXxxListener、XxxEvent等。遵守上述约定的类可以用于若干工具或库。

Tomcat

java开发环境

  • 安装JDK
  • 设置环境变量
   JAVA_HOME = C:\Program Files\Java\jdk1.8.0_66
   PATH = C:\ProgramData\Oracle\Java\javapath;%JAVA_HOME%\bin;
   CLASSPATH = %JAVA_HOME%\lib; %JAVA_HOME%\lib\dt.jar; %JAVA_HOME%\lib\tools.jar;
  • 安装tomcat
  • 安装IntellJ idea
  • 新建项目,关联tomcat
  • 部署项目:把IntelliJ项目的web目录上传到外网虚拟站点根目录就可以了。
jar xf tomcat.war
chown -R www.www ./*
service tomcat restart

数据库连接不上,把mysql-connector-java-5.1.18-bin.jar放到tomcat/lib目录下,重启。

Spring

谈谈对ssh三大框架的理解?

SSH框架一般指的是Struts、Spring、Hibernate,后来Struts2代替了Struts。最近5年,Struts2已经被Spring MVC代替,而Hibernate基本也被iBatis/MyBatis代替。

所以你真正需要了解的是Spring,Spring你需要了解两个概念AOP和IOC,更进一步就是Spring的核心技术“动态代理”。

持久层框架看看Hibernate/iBatis/MyBatis,研究一下Spring的数据库事务管理,各个持久层框架式如何实现ORM的,了解至少一种缓存框架,知道什么是数据库连接池。和数据库的交互最核心的不是ORM,而是掌握和数据库相关的能力,比如数据库编程、SQL优化、对范式的理解。

MVC框架Struts2和Spring MVC,你需要知道他们在web.xml文件里配置了一些什么,Struts2/Spring MVC接到前台请求之后经过哪些步骤之后转到Action/Controller,return之后Struts2/Spring MVC又作了些什么。还有就是Filter、Listener和Struts2/Spring MVC的拦截器各有什么特点,适合处理什么样的问题。

Spring Security取username

前台

<%@ taglib prefix='security' uri='http://www.springframework.org/security/tags' %>
<security:authentication property="principal.username"></security:authentication>

后台

Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String username = "";
 
if (principal instanceof UserDetails) {
    username = ((UserDetails) principal).getUsername();
} else {
    username = principal.toString();
}
 
System.out.println(username);

favicon.ico引起的spring security登录后跳转错误

在使用spring security登录的时候,用户在某些情况下登录成功的时候莫名被重定向到favicon.ico。

之前一直没发现这个问题是因为在项目中存在favicon.ico文件,这个请求被nginx处理了而未转发给tomcat。

这次因为偷懒还没来得及配置nginx,结果就出现了上面的问题。

出现上述问题的原因是:基本大多数浏览器都会请求favicon.ico这个图标文件用来展示在浏览器的URL地址前面,而这个文件被spring security保护了,所以…有下面的流程:

the user requests URL "/". This URL is cached.

the browser makes a requests to "/favicon.ico". This URL becomes the new URL where to redirect to upon authentication.

the user posts the login form and is redirected to "/favicon.ico"

而解决办法是将favicon.ico加入允许匿名访问.

<http pattern="/favicon.ico" security="none"/>

SPRING MVC 的请求参数获取的几种方法

<form method="post" action="hao.do">
    a: <input id="a" type="text" name="a"/>
    b: <input id="b" type="text" name="b"/>
    <input type="submit" value="Submit" />
</form>

方法1:

public class Pojo{
    private String a;
    private int b;
}
 
@RequestMapping(method = RequestMethod.POST)
public String processSubmit(@ModelAttribute("pojo") Pojo pojo) {
    return "helloWorld";
}

方法2:

@RequestMapping(method = RequestMethod.GET)
public String get(HttpServletRequest request, HttpServletResponse response) {
    System.out.println(request.getParameter("a"));
    return "helloWorld";
}

spring mvc 静态资源 404问题

修改web.xml文件,增加对静态资源的url映射。

<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.js</url-pattern>
</servlet-mapping>
 
<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.css</url-pattern>
</servlet-mapping>

在web.xml中添加好配置后,在jsp页面就可以引用这些静态资源了。

这里还需要说明的是:这种方法不能访问WEB-INF目录下的静态资源,也就是js目录必须是web根(可能是webapp,webContent等)目录下,否则是不能引用的。

使用spring ResponseEntity处理http响应

https://blog.csdn.net/neweastsun/article/details/81142870

使用spring时,达到同一目的通常有很多方法,对处理http响应也是一样。本文我们学习如何通过ResponseEntity设置http相应内容、状态以及头信息。

ResponseEntity标识整个http相应:状态码、头部信息以及相应体内容。因此我们可以使用其对http响应实现完整配置。

如果需要使用ResponseEntity,必须在请求点返回,通常在spring rest中实现。ResponseEntity是通用类型,因此可以使用任意类型作为响应体。

@GetMapping("/customHeader")
ResponseEntity<String> customHeader() {
    HttpHeaders headers = new HttpHeaders();
    headers.add("Custom-Header", "foo");
 
    return new ResponseEntity<>("Custom header set", headers, HttpStatus.OK);
}

Controller中返回数据总结(ResponseEntity,@ResponseBody,@ResponseStatus)

https://www.cnblogs.com/Jason-Xiang/p/10244075.html

在传统的开发过程中,我们的控制CONTROLLER层通常需要转向一个JSP视图;但随着WEB2.0相关技术的崛起,我们很多时候只需要返回数据即可,而不是一个JSP页面。

  • ResponseEntity:表示整个HTTP响应:状态代码,标题和正文。因此,我们可以使用它来完全配置HTTP响应,它是一个对象。
  • @ResponseBody:返回json格式的结果
  • @ResponseStatus:返回状态
@GetMapping("/hello")
public ResponseEntity<String> hello() {
    return new ResponseEntity<>(new User(‘jdon’), HttpStatus.OK);
}
//返回的是JSON字符串:[ { ‘name’: 'jdon'}]

在类级别使用@Controller标注情况下, @ResponseBody注解告诉返回的对象将自动序列化为JSON,并通过回控制器的HttpResponse对象。

@Controller
public class XXXController{
    @ResponseBody
    public User postResponseController(@RequestBody LoginForm loginForm) {
        return new User("Thanks For Posting!!!");
    }
}
//将返回客户端JSON字符串:[ { ‘name’: Thanks For Posting!!!"}]

在@RestController注解了类的情况下,我们就不需要再使用@ResponseBody了。

@ResponseStatus

ResponseStatus虽然只是规定了返回的状态,但是只需要标注在方法上,简单,而且状态码与返回类型分离,比较清晰。我们将上面返回对象列表的代码使用ResponseStatus改写如下,注意类级别@RestController:

@RestController
public class XXXController{
    @ResponseStatus(HttpStatus.FOUND)
    public User postResponseController() {
        return new User("Thanks For Posting!!!");
    }
}
//这也会返回客户端JSON字符串:[ { ‘name’: Thanks For Posting!!!"}]

这样的代码更加专注于业务。

Spring还允许我们直接访问javax.servlet.http.HttpServletResponse对象; 我们只需要将它声明为方法参数:

@GetMapping("/manual")
public void manual(HttpServletResponse response) throws IOException {
    response.setHeader("Custom-Header", "foo");
    response.setStatus(200);
    response.getWriter().println("Hello World!");
}

由于Spring在底层实现之上提供了抽象和附加功能,因此如果以这种方式直接操纵响应,会失去很多Spring提供方便功能。

注解@RequestParam与@RequestBody的使用场景

https://cloud.tencent.com/developer/article/1414464

注解@RequestParam接收的参数是来自requestHeader中,即请求头。通常用于GET请求,比如常见的url:

http://localhost:8081/spring-boot-study/novel/findByAuthorAndType?author=唐家三少&type=已完结

注解@RequestBody接收的参数是来自requestBody中,即请求体。一般用于处理非 Content-Type: application/x-www-form-urlencoded编码格式的数据,比如:application/json、application/xml等类型的数据。

RestTemplate

https://blog.csdn.net/itguangit/article/details/78825505

REST与RPC几乎没有任何关系。RPC是面向服务的,并关注于行为和动作;而REST是面向资源的,强调描述应用程序的事物和名词。

RestTemplate定义了36个与REST资源交互的方法,其中的大多数都对应于HTTP的方法。 其实,这里面只有11个独立的方法,其中有十个有三种重载形式,而第十一个则重载了六次,这样一共形成了36个方法。

  1. put() PUT 资源到特定的URL
  2. getForEntity() 发送一个HTTP GET请求,返回的ResponseEntity包含了响应体所映射成的对象
  3. getForObject() 发送一个HTTP GET请求,返回的请求体将映射为一个对象
  4. postForEntity()POST 数据到一个URL,返回包含一个对象的ResponseEntity,这个对象是从响应体中映射得到的
  5. postForObject() POST 数据到一个URL,返回根据响应体匹配形成的对象
  6. postForLocation() POST 数据到一个URL,返回新创建资源的URL
  7. delete() 在特定的URL上对资源执行HTTP DELETE操作
  8. headForHeaders() 发送HTTP HEAD请求,返回包含特定资源URL的HTTP头
  9. optionsForAllow() 发送HTTP OPTIONS请求,返回对特定URL的Allow头信息
  10. exchange()在URL上执行特定的HTTP方法,返回包含对象的ResponseEntity,这个对象是从响应体中映射得到的
  11. execute() 在URL上执行特定的HTTP方法,返回一个从响应体映射得到的对象

Spring Boot

入门--Hello World

https://blog.csdn.net/duchao123duchao/article/details/73011717

Spring Boot是一种简化原有Spring应用繁杂配置的微框架。使开发者从繁杂的各种配置文件中解脱出来,通过Spring Boot能够很简单、很快速构建一个优秀的、产品级的Spring基础应用。运行Spring Boot和运行普通的Java类一样简单,仅仅run一下Spring Boot的入口main()方法即可开启应用;你也可以把Spring Boot应用打成jar,在命令行执行java -jar xxx.jar命令来运行;或者打成war包部署到服务器下运行服务器来开启应用。Spring Boot微框架考虑到了Spring平台和第三方库的情况,所以你需要做的则是最少的操作或配置。

Spring Boot特点:

  1. 创建优秀的Spring Web应用;
  2. 直接嵌入了Tomcat、Jetty和Undertow等三个Web服务器,很方便的部署应用;
  3. 提供一系列不同类型的starter POMs简化原有Spring应用繁杂的Maven配置;
  4. 充分利用JavaConfig的配置模式以及“约定优于配置”的理念,自动化配置、装配Spring,简化了人为的配置;
  5. 提供生产就绪型功能,如指标,健康检查和外部配置(?不理解这点,求指教);
  6. 没有代码产生、没有XML文件要求配置。
@RestController //里面的方法都以 json 格式输出,表示这个入口类也是控制类,=@Controller+@ResponseBody 
@SpringBootApplication
public class DemoApplication {
    @RequestMapping("/")   //请求的映射路由
    public String home(){
        return "hello world";
    }
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

spring boot 指定启动端口

src/main/resources/application.properties
server.port=8081

如何禁用 Spring Boot DEBUG 和 Spring Boot INFO 日志?

logging.level.org.springframework=OFF
logging.level.root=OFF
spring.main.banner-mode=off

SpringApplication启动原理

http://www.majunwei.com/view/201708231840127244.html

  1. SpringApplication.run(args)
  2. 初始化监听器
  3. 发布ApplicationStarterEvent事件
  4. 装配环境
  5. 发布ApplicatinEnvironmentPreparedEvent事件
  6. 打印Banner
  7. 创建ApplicationContext
  8. 装配Context
  9. 发布ApplicationPreparedEvent事件(注意源码中是空的,没有真正发布)
  10. 注册、加载等等…
  11. 发布ApplicationPreparedEvent事件(注意这里才是真正发布了Prepared事件)
  12. refreshContent
  13. afterContent
  14. 发布ApplicationReadyEvent事件

springboot中 @Autowired @Resource @Bean

https://www.jianshu.com/p/70e7e7bc652e

Spring Data JPA 与 MyBatis简单对比

https://www.jianshu.com/p/3927c2b6acc0

JPA是Java Persistence API的简称,是一套Sun官方提出的Java持久化规范。

Spring Data JPA是Spring Data的子模块。使用Spring Data,使得基于“repositories”概念的JPA实现更简单和容易。Spring Data JPA的目标是大大简化数据访问层代码的编码。作为使用者,我们只需要编写自己的repository接口,接口中包含一些个性化的查询方法,Spring Data JPA将自动实现查询方法。

JPA默认使用hibernate作为ORM实现,所以,一般使用Spring Data JPA即会使用hibernate。我们再看看hibernate的官方概念,Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架,hibernate可以自动生成SQL语句,自动执行,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。

MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。

这样看,Spring Data JPA与MyBatis对比,起始也就是hibernate与MyBatis对比。所以,我们直接来比较后两者。

hibernate是一个自动化更强、更高级的框架,毕竟在java代码层面上,省去了绝大部分sql编写,取而代之的是用面向对象的方式操作关系型数据库的数据。而MyBatis则是一个能够灵活编写sql语句,并将sql的入参和查询结果映射成POJOs的一个持久层框架。

这样看来MyBatis更适合于面向关系(或面向数据、或面向过程)的系统设计方法,这样的系统一般称为“事务脚步”系统(事务脚步(Transaction Script) 出自Martin Fowler 2004年所著的企业应用架构模式(Patterns of Enterprise Application Architecture))。而hibernate(也可以说Spring Data JPA)更适合于构建领域模型类的系统。当然,我们也不能说MyBatis无法构建领域模型驱动的系统,而hibernate无法构建事务脚步系统。只是用MyBatis构建领域模型要做更多、更脏、更累的工作;而用hibernate构建一个事务脚本系统有些大材小用,数据的查询反而没那么灵活。

Spring Data Jpa的使用

https://www.jianshu.com/p/c23c82a8fcfc

相关配置

server:
  port: 8080
  servlet:
  context-path: /
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false
    username: root
    password: mysql123
  jpa:
    database: MySQL
    database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
    show-sql: true
    hibernate:
    ddl-auto: update

ddl-auto

  • create:每次运行程序时,都会重新创建表,故而数据会丢失
  • create-drop:每次运行程序时会先创建表结构,然后待程序结束时清空表
  • upadte:每次运行程序,没有表时会创建表,如果对象发生改变会更新表结构,原有数据不会清空,只会更新(推荐使用)
  • validate:运行程序会校验数据与数据库的字段类型是否相同,字段不同会报错
  • none: 禁用DDL处理

简单的REST CRUD示例

写一个类继承JpaRepository<T, ID>,需要写两个泛型,第一个代表要存储的实体类型,第二个代表主键类型,例如写一个User类的仓储如下:

public interface UserRepository extends JpaRepository<User, Long> {
}

常用代码

随机取读取数据库的一道题

Random random    = new Random(System.currentTimeMillis());
int index_random = random.nextInt(listItem.size());

guid()

private String guid() {
    UUID uuid = UUID.randomUUID();
    String str = uuid.toString();
 
    // 去掉"-"符号
    String temp = str.substring(0, 8) + str.substring(9, 13) + str.substring(14, 18) + str.substring(19, 23) + str.substring(24);
    return temp;
}

Java数字格式化

double pi = 3.1415927;//pi   
 
// 取一位整数   
System.out.println(new DecimalFormat("0").format(pi));// 3   
 
// 取一位整数和两位小数   
System.out.println(new DecimalFormat("0.00").format(pi));// 3.14   
 
// 取两位整数和三位小数,整数不足部分以0填补。   
System.out.println(new DecimalFormat("00.000").format(pi));// 03.142   
 
// 取所有整数部分   
System.out.println(new DecimalFormat("#").format(pi));// 3   
 
// 以百分比方式计数,并取两位小数   
System.out.println(new DecimalFormat("#.##%").format(pi));// 314.16%   
 
long c = 299792458;
 
// 显示为科学计数法,并取五位小数   
System.out.println(new DecimalFormat("#.#####E0").format(c));// 2.99792E8   
 
// 显示为两位整数的科学计数法,并取四位小数   
System.out.println(new DecimalFormat("00.####E0").format(c));// 29.9792E7   
 
// 每三位以逗号进行分隔。   
System.out.println(new DecimalFormat(",###").format(c));// 299,792,458   
 
// 将格式嵌入文本   
System.out.println(new DecimalFormat("光速大小为每秒,###米。").format(c));

生成随机字符

private String RandomString(int length, String type) {
    String number = "0123456789";
    String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    Random random = new Random();
    StringBuffer sb = new StringBuffer();
 
    for (int i = 0; i < length; i++) {
        if (type.equals("number")) {
            int num = random.nextInt(number.length());
            sb.append(number.charAt(num));
        } else {
            int num = random.nextInt(str.length());
            sb.append(str.charAt(num));
        }
    }
 
    return sb.toString();
}

应用

AES加密

java代码

    // 密钥
    private final static String secretKey = "key123";
    private final static String salt = "0123456789abcdef" ;//KeyGenerators.string().generateKey();
 
    /**
     * 加密
     *
     * @param plainString 明文
     * @return
     */
    private static String encrypt(String plainString) {
        // 明文
        byte[] byteArray = plainString.getBytes();
 
        // 加密,设置密钥和随机数
        byte[] cipherArrayTemp = Encryptors.standard(secretKey, salt).encrypt(byteArray);
        byte[] cipherArray = Base64.encode(cipherArrayTemp);
        return new String(cipherArray);
    }
 
    /**
     * 解密
     *
     * @param cipherString 密文
     * @return
     */
    private static String decrypt(String cipherString) {
        // 密文
        byte[] byteArray = cipherString.getBytes();
        byte[] plainArrayTemp = Base64.decode(byteArray);
 
        // 解密
        byte[] plainArray = Encryptors.standard(secretKey, salt).decrypt(plainArrayTemp);
        return new String(plainArray);
    }

javascript代码

https://cdn.bootcss.com/crypto-js/3.1.9-1/crypto-js.js

  // 可在第三方网站解密
  let word = 'hello world!';
  let key = 'key123';
  var iv = '0123456789abcdef';
  var attr = {
    iv: iv,
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7
  };
  console.log(CryptoJS.AES.encrypt(word, key, attr).toString());
  console.log(CryptoJS.AES.decrypt(CryptoJS.AES.encrypt(word, key), key).toString(CryptoJS.enc.Utf8));

Base64,Base32,Base16进制的区别

刚刚接触Base时,没有太注重区分Base64,Base32,Base16的区别,后面每一次遇到就要去一个一个试,这次花了点时间记下了一下Base的区别,顺便写一下。

在看了大佬们的分析后http://blog.51cto.com/xiaoqin00/1718416,我截取了几个关键的记住这些就能区分Base之间的区别了:

Base64:

包含大写字母(A-Z),小写字母(a-z),数字(0-9)以及+/;

Base32:

而Base32中只有大写字母(A-Z)和数字234567;

Base16:

而Base16就是16进制,他的范围是数字(0-9),字母(ABCDEF);

顺便说一句,当ASCll用Base加密达不到所对应的位数的时候用=号补齐;

在这里附带由三种Base加密的:I love you!

Base64:SSBsb3ZlIHlvde+8gQ==

Base32:JEQGY33WMUQHS33V566IC===

Base16:49206c6f766520796f75efbc81

poi导出excel文件、下载

@RequestMapping(value = "batchCardNoExport", method = RequestMethod.GET)
public void batchCardNoExport(HttpServletRequest request, HttpServletResponse response) throws Exception {
    // 创建Excel的工作书册 Workbook,对应到一个excel文档
    HSSFWorkbook wb = new HSSFWorkbook();
 
    // 创建Excel的工作sheet,对应到一个excel文档的tab
    HSSFSheet sheet = wb.createSheet("sheet1");
 
    HSSFRow row;
    HSSFCell cell;
 
    for (int i = 0; i < 60; i++) {
        row = sheet.createRow(i); // 创建Excel的sheet的一行
        for (int j = 0; j < 30; j++) {
            cell = row.createCell(j); // 创建一个Excel的单元格
            cell.setCellValue("hello world " + i + " " + j);
        }
    }
 
    response.setContentType("application/vnd.ms-excel");
    response.setHeader("Content-Disposition", "attachment; filename=filename.xls");
    wb.write(response.getOutputStream()); // Write workbook to response.
    wb.close();
}

如何在mac上安装gradle

首先,先download最新版本的gradle,网址如下:

http://www.gradle.org/get-started

然后将下载下来的zip包放在你要安装的路径上,我安装在

/usr/local/bin;

然后打开电脑上的.bash_profile文件,输入以下命令:

GRADLE_HOME=/usr/local/bin/gradle-1.8;
export GRADLE_HOME
export PATH=$PATH:$GRADLE_HOME/bin

然后再在console上输入以下命令:

source ~/.bash_profile

这样就安装成功啦,可以通过以下命令来查看是否安装成功。

gradle -version

IntelliJ IDEA 配置

https://www.cnblogs.com/knowledgesea/p/11158412.html

IDEA 清除类中无用的import包:Ctrl + Alt + O

自动导入缺失的包:Alt + Enter

格式化代码:Ctrl + Alt + L

swagger常用注解说明

https://www.jianshu.com/p/12f4394462d5

@Api:用在类上,说明该类的作用。
@ApiOperation:用在方法上,说明方法的作用。
@ApiParam:请求属性。
@ApiResponse:响应配置。
@ApiResponses:响应集配置。
@ResponseHeader:响应头设置。
 
@ApiModel:描述一个Model的信息,(这种一般用在post创建的时候,使用@RequestBody这样的场景,请求参数无法使用@ApiImplicitParam注解进行描述的时候)。
@ApiModelProperty:描述一个model的属性。