知識點
類
靜態方法,即可以在類上被調用,也可以在實例對象上被調用。
Java類 先執行靜態構造函數,再執行靜態方法或靜態字段,所以如果在類的靜態構造函數中,執行了該類的靜態方法,則會報錯。因為類還沒有初始化,不能調用類方法,這一點和C#不同。以下代碼報錯:
public class obj{
static{
Init();
}
public static void Init(){}
}
使用 import static 包.類.*; 可以直接使用該類下的方法。
類上可以定義代碼段,在執行完構造函數之后執行。如:
public class test{
{system.out.println("OK");}
{system.out.println("22");}
}
一些考點: http://www.cnblogs.com/lanxuezaipiao/p/3371224.html
getClass().getClassLoader() 根在哪?
在 target/@/Web-inf/classes
可能通過:this.getClass().getClassLoader().getResource("").getPath() 取得。
Jdbc
executeQuery 是執行并返回結果
getResultSet 可以多次調用,僅一次執行。
ResultSet.getInt(index) 中的 index 是從 1 開始的。
JdbcTemplate
用法: http://www.cnblogs.com/Fskjb/archive/2009/11/18/1605622.html
org/springframework/dao/DataAccessException: http://blog.sina.com.cn/s/blog_55fc875c0100hfdm.html
需要的Jar包:
spring-tx-4.3.0.RELEASE.jar
MySQL-connector-java-5.1.39-bin.jar
MySQL-connector-java-5.1.30.jar
sqljdbc.jar
Kotlin代碼:
Class.forName("com.mysql.jdbc.Driver");
var s = DriverManagerDataSource("jdbc:mysql://127.0.0.1:3306/ptr", "root", "1234");
//s.setDriverClassName("com.mysql.jdbc.Driver")
//var s = org.springframework.jdbc.datasource.DriverManagerDataSource("jdbc:microsoft:sqlserver://localhost:1433;databasename=MyMvcApp", "sa", "sa@")
//s.setDriverClassName("com.microsoft.sqlserver.jdbc.SQLServerDriver")
var d:JdbcTemplate = JdbcTemplate(s)
var list = d.queryForList("select * from P_User where LoginName=?","SysAdmin");
不支持
1. 不支持分部類。
2. 不支持參數默認值
3. 不支持 擴展方法
4. String.Join 還是自己寫吧。
5.
6. 不支持索引器, 把它改為一個方法, get(int index) 吧。List也是這么干的。
7. 沒有var
9. 沒有擴展方法
10. 沒有屬性,所以不能這樣寫: new Node(){ Name = "abc"}
11. 不支持運算符重載,Java作者說是不喜歡,其實是他不會。
12. 關于泛型,Java并不支持真正的泛型,作者喜歡泛型,但是水平太低,不會實現,所以僅僅做了個樣子: http://blog.sina.com.cn/s/blog_44c1e6da0100cus3.html
ava中泛型實現使用的擦除機制,為類型參數傳入類型并不導致新類型出現,即傳入了類型參數后在運行時仍然完全不知道類型參數的具體類型!
13. 定義方法可以拋出異常,調用方法必須使用 try catch ,或也拋出同樣的異常。 好煩!
14. Java 的枚舉,不能和 int 相互轉換, 比如它不能從 任意一個數字轉為枚舉,它是一個有限集合。而C#的枚舉之間可以相互運算,如 | & 等。
14.
惡心事
先記錄一下我問的問題和經常聽到的回答:
問:我想實現C#的 MyObject.As<Int>("22"); Java如何實現? MyObject.<Integer>("22",Integer.class) 是多一個參數的。
答:你為什么那樣做? 你不應該那樣實現,應該針對每個類型定義函數。
析:
先弄明白一件事,是Java不能實現!
好像這是很多人的邏輯,不能實現的東西,從另一方面去說實現方案不對。 一個軟件實現不了的功能,就可以說,這個功能是不合理的。
要讓豬上樹,先把樹砍到豬能上去的高度。要讓Java去實現功能,先把功能砍到Java能實現的程度。
1. ==
Java 判斷字符串相等不能使用 == , 而必須使用 equals
http://www.cnblogs.com/yjmyzz/archive/2012/12/10/2812079.html
2. 配置文件
配置文件不能編譯,所以大量依賴就很惡心了,配置階段誰也不敢保證它是正確的。萬一解析程序更新了呢。萬一 Spring9.0有了新的配置文件架構呢。
配置文件做為一個中間數據載體(可以看做是數庫),應該提供一個配置工具(微軟有一個web.config配置工具)!或者最起碼,提供一個全部配置的,且最優化的例子。
3. HttpServletResponseWrapper
如果靜態資源進入Filter,有的時候,會是莫名其妙的 isCommited() 為 true ,為 true 之后, 就不能再進行輸出了。
解決辦法:通過utl-pattern 阻止靜態資源進入Filter
4. 各種包的不穩定,返回Json 406錯誤
http://blog.csdn.NET/a4307515/article/details/42394869
5. 相同的Controller報錯
兩個包名下,同名的類名, spring運行時出錯: Servlet.init() for servlet mvc-dispatcher threw exception
解決方法:
1. 把類名改為: Admin_Home , Open_Home,保證不重名。
2. 把 @Controller 屬性的構造函數里設置 Controller名稱。保證里面的名稱不重名。
6. (String[]) toArray()報錯
toArray()時,返回的是 Object[],強轉會出錯。Java推薦使用帶參數的 toArray(),但參數時,必須傳入一個有空間大小的數組,toArray方法進行填充并返回(我想罵)
7. 依賴異常
Java有很多方法,并不會返回 null ,而是拋出異常!
Class.getField ,如果沒有該列,則報: NoSuchFieldException ,而不是返回null
如果函數拋出異常,需要要函數上顯式進行定義。 我去年買了個表,Java設計者。
我想:在定義函數時不定義拋出異常,但出現異常的時候還要拋出異常!!!
只好對異常規范進行修改。
想拋出異常的時候,運行一個函數 Throw("異常消息"); Throw方法產生一個運行時異常。
private static class MyException extends RuntimeException {
public MyException(String msg) {
super(msg);
}
}
public static void Throw(String msg){
System.out.println("自定義運行時異常:"+ msg);
}
public static void Throw(Exception e){
System.out.println(e.getMessage());
MyException exp = new MyException(e.getMessage());
exp.setStackTrace(e.getStackTrace());
throw exp;
}
在catch 完異常之后, 調用 MyObject.Throw(e); 如下:
public static void Do()
{
try {
delete = (ActionClipBase) this.getClass().newInstance();
} catch (Exception e) {
MyObject.Throw(e);
}
}
這樣,拋出運行時異常來達到停止代碼執行的目的。
8. static函數中不能使用 return
9. 所有類,必須在某個包下。
源碼根文件夾,下面不能有類。
如: java做為Sources Root,下面只能是文件夾。不能是類。
10. int[] Integer[]
雖然 int 和 Integer 可以相互轉換,但是 數組不能相互轉換。
ArrayUtils.toPrimitive
11. jackson
readValue(jsonString, clazz)
如果 classz 是 繼承自 HashMap 的,可以使用字典,但是,如果classz有public 字段, 則不能被認為是字典。Fuck!
與C#的區別
1. List是一個接口,使用: LinkedList<T>
2. 導入常用包:
import java.util.*;
3. Java8的 lambda表達式,需要使用 final 修飾表達式內的變量。
final Object[] ret = {null};
.lambda(o ->{
ret[0] = true;
});
//使用 ret[0]
list.removeIf(x-> x.startsWith( Prefix));
教程:
http://www.importnew.com/14841.html
http://my.oschina.Net/benhaile/blog/177148
Lambda基本招式:
Collection<>
.stream()
.map()
.filter()
.collection()
4. substring, 第二個參數:C#表示Length, Java表示EndIndex。 轉換: EndIndex = StartIndex + Length
5. 把 String.Empty 換成 “”
6. Array和List區別很大,函數最好返回List
7. foreach => for( int i : list)
8. 數組 Length =》 .length() ,盡量避免使用數組, 多使用 List,List有更多方法。
9. List [] => .get(index)
10. 代碼自動提示 : Ctrl+ Shift + 空格
11. 值類型與引用類型有很大使用上的區別,值類型都有一個引有類型和它對應。 int => Integer , boolean=>Boolean ,這個設計,我也是醉了。
12. HttpContext.Current.Item[] => request.setAttribute(key,val) , request.getAttribute(key)
13. Action => Consumer 一個參數 , BiConsumer 二個參數 。
14. Function => Supplier 沒有參數, Function 一個參數 , BiFunction 兩個參數
參考:http://www.java3z.com/cwbwebhome/article/article20/200101.html?id=4970
15. Server.MapPath => ServletContext.getRealPath
16. Java 的靜態構造函數寫法非法簡潔。只需要一個 static 即可。
17. C# 之于 ThreadStatic, Java 之于 ThreadLocal : http://my.oschina.NET/doctor2014/blog/396162
18. Switch 枚舉中 case 不必寫枚舉名, 這一點比 C# 好。
19. C# Attribute 使用 []修飾, Java使用 @
20. C#可以定義兩個類: List<T> : List ,而Java里,只需定義 List<T> , 使用時,可以使用 : List<T> ,List ,List<?>三種方式
21. C# 的 lock => Java 的 synchronized , ReentrantLock 。 : http://www.cnblogs.com/dolphin0520/p/3923167.html
優先使用 ReentrantLock
22. Java的一切異常是出錯的,比如強制類型轉換,而 .Net 不會出錯,從這一點上來說, .Net 性能會更高。
if( Obj instanceof String){
String strVal = (String) Obj;
...
}
23. C# Web.config 自定義 AppSettings => Bean 屬性注入。 字段怎么注入?!
24. C# : Application_Start 需要一個 Global.asax 文件。 而Java則需要 實現 WebApplicationInitializer 的類,不需要配置。可以有多個:
http://docs.spring.io/spring/docs/4.0.0.RELEASE/javadoc-api/
25:
C#是語法更新快,類庫穩定。可以向上升級。
Java是語法穩定,類庫不穩定。類庫的作者不必對之前的版本負責,所以不必兼容之前的版本。就導致兩個小版本的Jar包不能替換使用。可能會出現編譯不報錯,但是運行報錯的情況,也可能實現機制改變,而導致編譯不通過。
26. Java里到處是接口。你得到的永遠不是實現。
比如你得到 Xml的 Node 對象,但是Node對象沒有 getAttribute(name) 方法, 實現DeferredElementImpl 里有,但是你不能用。因為這個方法不是接口的方法,需要你轉換為 DeferredElementImpl 才能使用, 但是真保不齊下個版本的實現還是他。
就像: 通過一個方法,你提到一個楊過的老婆,老婆是個接口,具體實現叫 小龍女, 但是下個版本,你得到的還是楊過的老婆,但是叫 李莫愁。
27. Function 做為函數參數時,即使返回值不同,也不能重載。如:
public SelectClip<T> Select(Function<T,ColumnClip > colsFunc){
ColumnClip cols = null;
if( colsFunc == null){
cols = colsFunc.apply(this.LambdaHelperModel);
}
return Select(cols);
}
public SelectClip<T> Select(Function<T,ColumnClip[]> colsFunc){
ColumnClip[] cols = null;
if( colsFunc == null){
cols = colsFunc.apply(this.LambdaHelperModel);
}
return Select(cols);
}
會報錯。
組件
Spring用法:
1. 實現C# 的 using ,使用 import 包名.*;
2. 使用 Response,在action參數中添加: HttpServletResponse ,同理還有: HttpServletRequest 。
獲取HttpContext.Current 上下文: http://blog.csdn.Net/yanjiaye520/article/details/26602679
需要在
<!-- WEB.XML中配置相關的監聽機制 -->
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
使用:
//在任意的class下通過以下方法獲取到HttpServletRequest
HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
3. 修改編碼為 UTF8 , 修改 Tomcat 的編碼為 UTF8 http://www.it165.net/admin/html/201503/5139.html
4. Project Structure 里,修改Modules里的Spring項目的 Language Level為 8 : Lambda 時,編譯報錯。
5. URL大小寫: http://blog.csdn.net/k_scott/article/details/8254932
6. 返回的 Action: http://www.360doc.com/content/14/0309/19/834950_359081989.shtml
7. 輸出Filter,參考:
http://blog.csdn.net/wubai250/article/details/8552960
http://www.cnblogs.com/lhj588/archive/2012/07/06/2579188.html
url-pattern 設置:
*.jsp 時不起作用
/ 僅Mvc頁面程序處理!!!
*包含:.jsp , *.js , *.css 等,太煩了。
對指定路由使用Filter
<!-- HTML特殊字符過濾器-->
<filter>
<filter-name>HTMLFiter</filter-name>
<filter-class>com.cv.mvc.common.helper.HttpContext</filter-class>
</filter>
<filter-mapping>
<filter-name>HTMLFiter</filter-name>
<url-pattern>/Hr/*</url-pattern>
<url-pattern>/Person/*</url-pattern>
<url-pattern>/Open/*</url-pattern>
<url-pattern>/Sys/*</url-pattern>
<url-pattern>/Test/*</url-pattern>
</filter-mapping>
在Filter中,也可以設置當前的 Request 和 Response

public class HttpContext implements Filter {
private ServletContext servletContext = null;
private HttpServletRequest myRequest = null;
private MyHttpResponseWrapper myResponse = null;
public static ThreadLocal<HttpServletRequest> Request = new ThreadLocal<HttpServletRequest>();
public static ThreadLocal<HttpServletResponse> Response = new ThreadLocal<HttpServletResponse>();
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
myRequest = (HttpServletRequest) request;
myResponse = new MyHttpResponseWrapper((HttpServletResponse) response);
Request.set(myRequest);
Response.set(myResponse);
}
public static HttpServletRequest getRequest(){
if( Request == null || Request.get() == null){
System.out.printf("Web.xml沒有配置該路由,導致Request為空,將從RequestContextHolder返回Request對象!");
return ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
}
return Request.get();
}
public static HttpServletResponse getResponse(){
return Response.get();
}
public static HttpSession getSession(){
return getRequest().getSession();
}
}

7.1使用:HandlerInterceptorAdapter http://blog.csdn.net/liuwenbo0920/article/details/7283757
8. 訪問靜態資源,Web的根在哪?
根:Project Structure—》Modules -》 Web -》 Web Resource Directories -> 有 《Path Relative To Deployment Root》 一項,該值應該是 “/" , 左邊的 Web Resource Directory 就是根:默認指向 main\webapp
由于在 web.xml中,指定了所有的頁面程序程序,所以需要單獨設置靜態資源的處理程序。: http://www.cnblogs.com/rollenholt/archive/2012/12/26/2834209.html
如下設置:
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.jpg</url-pattern>
</servlet-mapping>
<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>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
如果設置了 Filter,則靜態資源也會進入到Mvc-Dispatcher。防止靜態資源進入Filter
<filter>
<filter-name>HTMLFiter</filter-name>
<filter-class>BaseMvc.MyResponseFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HTMLFiter</filter-name>
<url-pattern>/Admin/*</url-pattern>
<url-pattern>/Open/*</url-pattern>
<url-pattern>/Sys/*</url-pattern>
</filter-mapping>
9. HttpServletResponse 有 setStatus 方法,但是沒有 getStatus 方法,有文章說: http://blog.01000.name/http-servlet-response-status/
解決方案:http://yingzhuo.iteye.com/blog/1844714 + http://www.iteye.com/problems/41733
在自己的包裝器里,重寫 setStatus :
public class MyHttpResponseWrapper extends httpServletResponseWrapper {
int httpStatus;
@Override
public void setStatus(int sc) {
httpStatus = sc;
super.setStatus(sc);
}
public int getStatus() {
return httpStatus;
}
}
https://github.com/sitemesh/sitemesh3
10. @ResponseBody 表示返回內容不包含視圖,所有內容都在函數中處理了,相當于.Net 里的 Content() ,或 Json()。
11. getContextPath、getServletPath、getRequestURI的區別
http://my.oschina.net/xsh1208/blog/177522
12. 如何實現XA式、非XA式Spring分布式事務: http://www.importnew.com/15812.html
Json
公認: SmartJson 最快: https://github.com/netplex/json-smart-v2
學習資料
1. Spring Controller: http://my.oschina.net/hcliu/blog/396887
2. Spring源碼: http://www.cnblogs.com/xing901022/p/4178963.html
3. HttpServletResponseWrapper: http://www.mzone.cc/article/260.html
4. 進階: http://blog.csdn.net/it_man/article/details/7556903
5. Sitemesh3 : http://www.cnblogs.com/luotaoyeah/p/3776879.html
6. 反射 : http://www.cnblogs.com/penghongwei/p/3300084.html
判斷聲明類型: getModifiers : http://blog.csdn.net/zhou8622/article/details/44038699
7. BasicDataSource: http://my.oschina.net/DeanCTO/blog/323567
8. Jdbc:
http://www.cnblogs.com/wing011203/archive/2013/05/12/3073838.html
http://www.cnblogs.com/xinsheng/p/3898107.html
http://www.codingdiary.com/developers/developers/diary/javaapi/java/sql/SampleCode/ResultSetfindColumnExampleCode.html
9. Web中獲取路徑: http://blog.csdn.net/poplong/article/details/9734701
自制母版頁
目錄結構webapp(Tomcat根)
webapp(Tomcat根)
web-inf
pages(Spring根)
web.xml
Admin...(Mvc_Area)
Home (Mvc_Controller)
Index.jsp
Layout(母版頁位置)
Admin.jsp(對應Mvc_Area的母版頁)
Open.jsp (另一個Mvc_Area的母版頁)
Res(資源源文件)
R(生成的資源文件)
子頁面:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<layout>
<jsp:include page="../../layout/Open.jsp" />
</layout>
<def id="title" >我是首頁</def> <def id="body" /> 內容隨便寫。 都在 body 里。
母頁:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title><def id=title /></title>
<script src="/R/MyJs_Open.js"></script>
<link href="~/R/MyCss_Open.css" rel="stylesheet">
</head>
<body>
<def id=body />
</body>
</html>
關聯點:
子頁面使用
<layout>
<jsp:include page="../../layout/Open.jsp" />
</layout>
聲明母版頁位置,并把母版頁的內容渲染到當前頁的 layout內。
母版頁和子頁使用 def 標簽的 進行關聯, 子頁的def 內容填充到母頁的 def 元素內,并去除 def 標簽。
寬泛的擴展:
子頁的 def 定義有兩種方式:
推薦方式:
<def id="body">
Body內容區
</def>
或者,自閉合方式
<def id="body" />
下面全部是Body的內容。直到遇到下一個 def 標簽。
母版頁定義的 def 元素標簽:
1. 允許有內容,內容將在加載子頁面后,被移除。
2. 標簽如果是自閉合。推薦。
母子頁面自動關聯 def中沒有定義 id的def元素。僅關聯第一個匹配的。
給母版傳遞Model
母頁面使用 @變量名 來接收子頁面 request.setAttribute 的 Key值。
public static HttpServletRequest getRequest(){
if( Request == null || Request.get() == null){
System.out.printf("Web.xml沒有配置該路由,導致Request為空,將從RequestContextHolder返回Request對象!");
return ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
}
return Request.get();
}
技巧片斷
1. 找包下類名:

/**
* 從一個包中找出所有的類,不包括jar包
* @param packageName
* @return
* @throws IOException
* @throws ClassNotFoundException
*/
@SuppressWarnings("rawtypes")
public static List<Class> getClasses(String packageName)
throws IOException, ClassNotFoundException {
ClassLoader classLoader = Thread.currentThread()
.getContextClassLoader();
String path = packageName.replace(".", "/");
System.out.println("Path:"+path);
Enumeration<URL> resources = classLoader.getResources(path);
List<File> dirs = new ArrayList<File>();
while (resources.hasMoreElements()) {
URL urlResource = resources.nextElement();
dirs.add(new File(urlResource.getFile()));
}
List<Class> classes = new ArrayList<Class>();
for (File directory : dirs) {
classes.addAll(findClasses(directory, packageName));
}
return classes;
}
@SuppressWarnings("rawtypes")
private static List<Class> findClasses(File directory, String packageName) throws ClassNotFoundException {
List<Class> classes=new ArrayList<Class>();
if(!directory.isDirectory()){
return classes;
}
File[] files=directory.listFiles();
for(File file:files){
if(file.isDirectory()){
assert !file.getName().contains(".");
System.out.println(packageName+"."+file.getName());
classes.addAll(findClasses(file,packageName+"."+file.getName()));
}else if(file.getName().endsWith(".class")){
classes.add(Class.forName(packageName+"."+file.getName().substring(0, file.getName().length()-6)));
}
}
return classes;
}

源自: http://bbs.csdn.net/topics/390716276
2. 代碼生成器 rapid generator 調試
rapid-generator.jar:cn.org.rapid_framework.generator.Generator.class
scanTemplatesAndProcess
日志的地方:
GLogger.println("-------------------load template from templateRootDir = \'" + templateRootDir.getAbsolutePath() + "\' outRootDir:" + (new File(this.outRootDir)).getAbsolutePath());
即是開始的地方。
到:executeGenerate 方法的時候,可以看 filePathModel 參數,即是可以使用的變量。
一些列的屬性方法在: cn.org.rapid_framework.generator.provider.db.table.model.Column 中。
問題
1. java.lang.ClassNotFoundException: org.bson.conversions.Bson
把mongo-java-driver-3.2.0 Copy 到 \target\MyMvc\WEB-INF\lib 下。
學習Java的同學注意了!!!
學習過程中遇到什么問題或者想獲取學習資源的話,歡迎加入Java學習交流群,群號碼:533586908 我們一起學Java!