Eclipse version:
Eclipse Java EE IDE for Web Developers.
Version: Kepler Service Release 1
Build id: 20130919-0819
反射获取目标class的目标属性泛型实际类型
(参考资料:Java反射与动态代理):
package com.tch.test.testextend; import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.List; import java.util.Map; public class GetGenericActualTypeTest { public static void main(String[] args) { getGenericActualType(User.class, "username"); getGenericActualType(User.class, "friends"); getGenericActualType(User.class, "friendUsername"); getGenericActualType(User.class, "friendNameMap"); } public static void getGenericActualType(Class<?> clazz, String fieldName){ System.out.println("begin to getGenericActualType for field: " + fieldName); Field field = null; try { field = clazz.getDeclaredField(fieldName); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } if(field != null){ /** * 如果field是一个普通的属性,不带有泛型,则getGenericType() 和 getType()的结果一样,都是该field的类型 * 如果field是一个带有泛型的属性,则getGenericType()得到的是泛型类型,需要类型转换为ParameterizedType, 和getType()的结果就不一样了 */ // 拿到属性的泛型类型(比如List<String> list, 得到的就是String) Type genericType = field.getGenericType(); // getType() 得到的是属性的类型 Type type = field.getType(); System.out.println("fieldName: " + fieldName + ", genericType equals type? " + genericType.toString().equals(type.toString())); if(genericType instanceof ParameterizedType){ // 获取泛型的实际类型 Type[] actualTypes = ((ParameterizedType) genericType).getActualTypeArguments(); if(actualTypes.length > 0){ for(Type actualType : actualTypes){ // 类型转为Class Class<?> actualClass = (Class<?>) actualType; System.out.println(actualClass); } } } } System.out.println(); System.out.println(); } class User{ private int age; private String username; private List<User> friends; private List<String> friendUsername; private Map<String, User> friendNameMap; public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public List<User> getFriends() { return friends; } public void setFriends(List<User> friends) { this.friends = friends; } public List<String> getFriendUsername() { return friendUsername; } public void setFriendUsername(List<String> friendUsername) { this.friendUsername = friendUsername; } public Map<String, User> getFriendNameMap() { return friendNameMap; } public void setFriendNameMap(Map<String, User> friendNameMap) { this.friendNameMap = friendNameMap; } } }
import java.util.List; public class Class1 { private List<String> list; private String name1; private void add(){ System.out.println("add---"); } }
package com.tch.test.concurrent; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Collection; import java.util.List; public class ReturnTest { private int i; public static void main(String[] args) throws Exception{ m1("name1", Class1.class); } /** * Created on: 2013-11-27 * <p>Discription: 反射获取目标class的目标属性泛型实际类型</p> * @param fieldName 属性名 * @param clazz 目标Class对象 * @return void */ public static <T> void m1(String fieldName,Class<T> clazz){ try { Field field = clazz.getDeclaredField(fieldName); Type type = field.getGenericType(); if (type instanceof ParameterizedType) { ParameterizedType paramType = (ParameterizedType) type; Type[] actualTypes = paramType.getActualTypeArguments(); for (Type aType : actualTypes) { if (aType instanceof Class<?>) { Class<?> clz = (Class<?>) aType; System.out.println(clz.getName()); } } } }catch (Exception e) { e.printStackTrace(); } } }
访问私有方法:
public static void callHiddenMethod(Object a, String methodName) throws Exception { Method g = a.getClass().getDeclaredMethod(methodName); g.setAccessible(true); g.invoke(a); }
获取目标Class对象的实际父类泛型类型:
public class Father<T> { }
public class Child extends Father<String>{ }
import java.lang.reflect.ParameterizedType; public class GenericUtils { /** * Created on: 2013-11-27 * <p>Discription: 获取目标Class对象的实际父类泛型类型</p> * @param clazz 目标Class对象 * @return Class<T> */ @SuppressWarnings("unchecked") public static <T> Class<T> getGenericType(Class<T> clazz){ return (Class<T>)((ParameterizedType)clazz.getGenericSuperclass()).getActualTypeArguments()[0]; } }
测试方法:
public static void main(String[] args) throws Exception { System.out.println(GenericUtils.getGenericType(Child.class)); }
快速排序 / 冒泡排序:
package com.tch.test; public class QuickSort { public void quickSort(int[] arr, int from, int to) { if(from >= to){ return; } int left = from; int right = to; int tmp = arr[from]; while(left < right){ while(right > left){ if(arr[right] < tmp){ arr[left] = arr[right]; break; } right --; } while(left < right){ if(arr[left] > tmp){ arr[right] = arr[left]; break; } left++; } } arr[left] = tmp; quickSort(arr, from, left-1); quickSort(arr, right+1, to); } public void maopao(int[] arr){ int length = arr.length; int tmp = 0; for(int i=0;i<length;i++){ for(int j=(i+1);j<length;j++){ if(arr[i] > arr[j]){ tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; } } } } public static void main(String[] args) { int[] arr = new int[] { 1,4,8,2,5,9,7,6,3,10 ,3,5,8,0,1,6 }; QuickSort sort = new QuickSort(); //sort.quickSort(strVoid, 0, arr.length - 1); sort.maopao(arr); for (int i = 0; i < arr.length; i++) { System.out.print(arr[i] + " "); } } }
读取一行:
/** * Created on 2013-5-22 * <p>Discription:读取一行内容</p> * @param in 输入流 * @return String 读取到的一行内容 */ public static String readLine(InputStream in){ String result = null; try { byte[] b = new byte[1]; int n = -1; while((n = in.read()) != -1){ if(n == '\r' || n == '\n'){ break; }else{ b[b.length-1] = (byte)n; b = Arrays.copyOf(b, b.length+1); } } if(b.length <= 1){ return null; } b = Arrays.copyOf(b, b.length-1); return new String(b,"utf-8"); } catch (IOException e) { e.printStackTrace(); } return result; }
servlet下载pdf:
package com.tch.excel; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ExportExcel extends HttpServlet { /** * The doGet method of the servlet. <br> * * This method is called when a form has its tag value method equals to get. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } /** * The doPost method of the servlet. <br> * * This method is called when a form has its tag value method equals to post. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("application/pdf"); File file = new File("E:\\中文.pdf"); response.addHeader("Content-Disposition", "attachment;"+new String(("filename=我的Excel.pdf").getBytes("GBK"), "ISO-8859-1")); response.setContentLength((int) file.length()); PrintWriter out = response.getWriter(); FileReader in = new FileReader(file); char[] b = new char[10240]; int n = -1; while((n=in.read(b)) != -1){ out.write(b, 0, n); } out.flush(); out.close(); } }
下载excel::(只需要改contentType和文件后缀即可)
package com.tch.excel; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @SuppressWarnings("serial") public class ExportExcel extends HttpServlet { /** * The doGet method of the servlet. <br> * * This method is called when a form has its tag value method equals to get. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } /** * The doPost method of the servlet. <br> * * This method is called when a form has its tag value method equals to post. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("application/x-xls;charset=utf-8"); response.addHeader("Content-Disposition", "attachment;"+new String(("filename=我的Excel.xls").getBytes("GBK"), "ISO-8859-1")); PrintWriter out = response.getWriter(); out.print(" 中文内容"); out.flush(); out.close(); } }
下载word:(只需要改contentType和文件后缀即可)
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("application/msword;charset=utf-8"); response.addHeader("Content-Disposition", "attachment;"+new String(("filename=我的Excel.doc").getBytes("GBK"), "ISO-8859-1")); PrintWriter out = response.getWriter(); out.print(" 中文内容"); out.flush(); out.close(); }
导出excel:
static void export() throws Exception{ HSSFWorkbook wb = new HSSFWorkbook(); Sheet sheet = wb.createSheet("007"); HSSFCellStyle style = wb.createCellStyle(); //背景颜色(注意不是setFillBackgroundColor) style.setFillForegroundColor(HSSFColor.WHITE.index); //背景颜色填充样式 style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND); //上下左右边框样式 style.setBorderBottom(HSSFCellStyle.BORDER_THIN); style.setBorderLeft(HSSFCellStyle.BORDER_THIN); style.setBorderRight(HSSFCellStyle.BORDER_THIN); style.setBorderTop(HSSFCellStyle.BORDER_THIN); //上下左右边框颜色 style.setRightBorderColor(HSSFColor.GREY_25_PERCENT.index); style.setBottomBorderColor(HSSFColor.GREY_25_PERCENT.index); style.setLeftBorderColor(HSSFColor.GREY_25_PERCENT.index); style.setTopBorderColor(HSSFColor.GREY_25_PERCENT.index); //水平、垂直对齐方式 style.setAlignment(HSSFCellStyle.ALIGN_LEFT); style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); Row row = sheet.createRow((short) 1); Cell cell = row.createCell((short) 1); cell.setCellValue("X"); cell.setCellStyle(style); cell = row.createCell((short) 2); cell.setCellValue("X"); cell.setCellStyle(style); FileOutputStream fileOut = new FileOutputStream("f:workbook.xls"); wb.write(fileOut); fileOut.close(); }
产生验证码(以servlet为例):
package com.tch.excel; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.Random; import javax.imageio.ImageIO; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class AuthImage extends HttpServlet { private static final long serialVersionUID = 1L; private static char[] codeArr = new char[] {'a','b','c','d','e','f','g','h','i', 'j','k','l','m','n','o','p','q','r', 's','t','u','v','w','x','y','z','A', 'B','C','D','E','F','G','H','I','J', 'K','L','M','N','O','P','Q','R','S', 'T','U','V','W','X','Y','Z','0','1', '2','3','4','5','6','7','8','9'}; private Random random = new Random(); public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { int length = codeArr.length; int width = 200; int height = 100; //存放生成的字符 String code = ""; //存放最终的字符组成的字符串验证码 String validateCode = ""; //构建BufferedImage对象,用来存储生成的验证码图片(临时存放在内存中) BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); //获取BufferedImage的Graphics对象,Graphics起着画笔的作用,用来写验证码及其它内容 Graphics graphics = bufferedImage.getGraphics(); //开始在BufferedImage对象上面涂背景色 graphics.setColor(Color.white); graphics.fillRect(0, 0, width-1, height-1); //在BufferedImage对象上面画边框 graphics.setColor(Color.black); graphics.drawRect(0, 0, width-1, height-1); //设置要画的字符串的字体 graphics.setFont(new Font("Comic Sans MS",Font.PLAIN,70)); for(int i=0;i<4;i++){ //随机产生字符 code=""+codeArr[random.nextInt(length)]; //随机产生颜色 graphics.setColor(getRandColor()); //将字符写到BufferedImage对象上(Graphics最终是写到对应的BufferedImage对象上面) graphics.drawString(code, 5+i*50, 70); //添加到验证码字符串里面 validateCode += code; } System.out.println("validateCode : "+validateCode); //释放画笔占用的资源 graphics.dispose(); //将生成的图片通过response的输出流返回给页面 ImageIO.write(bufferedImage, "JPEG", response.getOutputStream()); } //产生随机颜色 private Color getRandColor() { Random random = new Random(); Color color[] = new Color[10]; color[0] = new Color(32, 158, 25); color[1] = new Color(218, 42, 19); color[2] = new Color(31, 75, 208); return new Color(random.nextInt(220), random.nextInt(220), random.nextInt(220)); } }
然后在web.xml中配置该servlet,页面如下(xxx为项目名,servlet/authImage为servlet的映射路径):
<html> <head> <title>导出表格到PDF实例</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <script type="text/javascript" charset="utf-8"> function refreshCode(obj){ obj.src = 'http://localhost:8080/xxx/servlet/authImage?d='+(new Date().getTime()); } </script> </head> <body id="dt_example"> <a href="###"><img src="http://localhost:8080/xxx/servlet/authImage" width="60" height="25" onclick="refreshCode(this);"></a> </body> </html>
任务调度ScheduledExecutorService:
import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; public class ScheduledTask { private static SimpleDateFormat format=new SimpleDateFormat("HH:mm:ss"); UncaughtExceptionHandler exceptionHandler = null; private void task1() { exceptionHandler = new UncaughtExceptionHandler(){ @Override public void uncaughtException(Thread t, Throwable e) { System.out.println("thread: "+t+" , throwable : "+e); } }; ScheduledExecutorService executor = Executors.newScheduledThreadPool(2, new ThreadFactory() { @Override public Thread newThread(Runnable r) { Thread thread = new Thread(r); thread.setUncaughtExceptionHandler(exceptionHandler);//异常处理 return thread; } }); //上次任务和下次任务的开始时间间隔为固定值(这里是6 s),不论任务本身执行多长时间,但是任务时间如果超过时间间隔,就会推迟下次任务的启动时间 executor.scheduleAtFixedRate(new Task("AtFixedRate"), 0, 6, TimeUnit.SECONDS); //从上次任务结束到下次任务的开始时间间隔为固定值(这里是6 s),和任务本身的执行时间有关系 executor.scheduleWithFixedDelay(new Task("WithFixedDelay"), 0, 6, TimeUnit.SECONDS); } public class Task implements Runnable { private String name; public Task(String name){ this.name = name; } public void run(){ System.out.println("线程 : "+name+" 启动"+format.format(new Date())); try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("线程 : "+name+"结束"+format.format(new Date())); } } public static void main(String[] args) { new ScheduledTask().task1(); } }
2种方式实现生产着消费者:
一:使用比较低级的方式:
import java.util.LinkedList; import java.util.Queue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Test2 { public static void main(String[] args) throws InterruptedException { Test2 t = new Test2(); Queue<Integer> container = new LinkedList<Integer>(); ExecutorService e = Executors.newFixedThreadPool(3); e.execute(t.new Producer(container)); e.execute(t.new Consumer(container)); e.shutdown(); } class Producer implements Runnable{ Queue<Integer> container; public Producer(Queue<Integer> container){ this.container = container; } int i=0; Integer get(){ i++; return i; } @Override public void run() { try { while(true){ synchronized(container){ while(container.size()>3){ container.wait(); } Integer j = get(); container.add(j); System.out.println("生产了:"+j); container.notifyAll(); Thread.sleep(500); } } } catch (InterruptedException e) { e.printStackTrace(); } } } class Consumer implements Runnable{ Queue<Integer> container; public Consumer(Queue<Integer> container){ this.container = container; } @Override public void run() { try { while(true){ synchronized(container){ while(container.isEmpty()){ container.wait(); } Integer butter =container.poll(); System.err.println("消费了: "+butter); container.notifyAll(); Thread.sleep(500); } } } catch (InterruptedException e) { e.printStackTrace(); } } } }
二:使用高级点,省事的方式:
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingQueue; public class Test { public static void main(String[] args) { Test t = new Test(); LinkedBlockingQueue<Integer> container = new LinkedBlockingQueue<Integer>(); ExecutorService e = Executors.newFixedThreadPool(3); e.execute(t.new Producer(container)); e.execute(t.new Consumer(container)); e.shutdown(); } class Producer implements Runnable{ LinkedBlockingQueue<Integer> container; public Producer(LinkedBlockingQueue<Integer> container){ this.container = container; } int i=0; Integer get(){ i++; return i; } @Override public void run() { try { while(true){ Integer j = get(); System.out.println("生产了:"+j); container.put(j);//LinkedBlockingQueue会自动处理容器为空或者过大的情况(会等待) Thread.sleep(500); } } catch (InterruptedException e) { e.printStackTrace(); } } } class Consumer implements Runnable{ LinkedBlockingQueue<Integer> container; public Consumer(LinkedBlockingQueue<Integer> container){ this.container = container; } @Override public void run() { try { while(true){ Integer butter =container.take();//LinkedBlockingQueue会自动处理容器为空或者过大的情况(会等待) System.err.println("消费了: "+butter); Thread.sleep(500); } } catch (InterruptedException e) { e.printStackTrace(); } } } }
标准jdbc连接步骤(使用了批处理,以及异常回滚):
void jdbc() throws Exception{ Connection conn = null; PreparedStatement statement = null; try { Class.forName("com.mysql.jdbc.Driver");//加载数据库驱动类 conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "root");//获取连接 statement = conn.prepareStatement("insert into coures(id,name,age) values(?,?,?)");//创建PreparedStatement conn.setSavepoint();//设置保存点 conn.setAutoCommit(false);//关闭事务自动提交 for(int i=0;i<100;i++){ statement.setInt(1, i);//索引从 1 开始 statement.setString(2, "tch"); statement.setInt(3, 23); statement.addBatch();//添加到批处理 } statement.executeBatch();//执行批处理 conn.commit();//没有异常,提交事务 } catch (Exception e) { if(conn != null){ conn.rollback();//出现异常时,回滚到保存点 } e.printStackTrace(); }finally{//关闭资源 if(statement != null){ statement.close(); } if(conn != null){ conn.close(); } } }
最简单的死锁:
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Test { Object o1 = new Object(),o2 = new Object(),o = new Object(); public static void main(String[] args) throws Exception { final Test t = new Test(); ExecutorService e = Executors.newFixedThreadPool(2); e.execute(new Runnable() { @Override public void run() { try { t.syn1(); } catch (Exception e) { e.printStackTrace(); } } }); e.execute(new Runnable() { @Override public void run() { try { t.syn2(); } catch (Exception e) { e.printStackTrace(); } } }); e.shutdown(); } void syn1() throws Exception{ synchronized(o1){ System.out.println("syn1 获得 o1 的锁"); Thread.sleep(50);//让出CPU,让syn2有机会获得o2的锁 synchronized(o2){ System.out.println("syn1 获得 o2 的锁"); } } } void syn2() throws Exception{ synchronized(o2){ System.out.println("syn2 获得 o2 的锁"); Thread.sleep(50);//让出CPU,让syn1有机会获得o1的锁 synchronized(o1){ System.out.println("syn2 获得 o1 的锁"); } } } }
log4j配置:
log4j.properties
log4j.rootLogger=debug,stdout,DAILY_ROLLING_FILE log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n ######################## # DailyRolling File ######################## log4j.appender.DAILY_ROLLING_FILE=org.apache.log4j.DailyRollingFileAppender log4j.appender.DAILY_ROLLING_FILE.Append=true log4j.appender.DAILY_ROLLING_FILE.Threshold=debug log4j.appender.DAILY_ROLLING_FILE.Encoding=UTF-8 #通过读取系统变量来制定日志目标位置 log4j.appender.DAILY_ROLLING_FILE.File=${logDir}/log.txt log4j.appender.DAILY_ROLLING_FILE.DatePattern='.'yyyy-MM-dd log4j.appender.DAILY_ROLLING_FILE.layout=org.apache.log4j.PatternLayout log4j.appender.DAILY_ROLLING_FILE.layout.ConversionPattern=[%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} [%c] %m%n ################### # Console Appender ################### log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender log4j.appender.Threshold=debug log4j.appender.CONSOLE.Target=System.out log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout log4j.appender.CONSOLE.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %5p (%c:%L) - %m%n ################### #指定特定类的输出级别 ################### #指定struts2日志级别 log4j.logger.com.opensymphony.xwork2=info log4j.logger.org.apache.struts2=info #指定某个类的日志级别 log4j.logger.com.test.LogTest=info
getResourceAsStream、getResource用法:
public class ResourceTest { public static void main(String[] args) { //Class.getResource("path") //path不以/开头,表示和当前文件同目录 System.out.println(ResourceTest.class.getResource("").getPath()); //path以/开头,表示classpath路径 System.out.println(ResourceTest.class.getResource("/").getPath()); //ClassLoader.getResource("path") //path不需要以/开头,表示classpath路径 System.out.println(ResourceTest.class.getClassLoader().getResource("").getPath()); //这种方式也可以获取classpath路径 System.out.println(ResourceTest.class.getProtectionDomain().getCodeSource().getLocation().getPath()); } }
注解的用法和处理(自定义注解、使用注解、处理注解)
web.xml加载顺序:
context-param -> listener -> filter -> servlet
web.xml中的listener的加载顺序由该listener在web.xml中的配置顺序决定,filter的顺序由web.xml中的filter-mapping顺序决定,servlet的顺序由web.xml中的servlet-mapping顺序决定
<listener> <listener-class>com.tch.Listener2</listener-class> </listener> <listener> <listener-class>com.tch.Listener1</listener-class> </listener>
可以看出先执行2,2等待3 s之后执行1,1在等待3 s,完全是线性执行的。
Listerner1:
package com.tch; import java.util.concurrent.TimeUnit; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; public class Listener1 implements ServletContextListener { @Override public void contextDestroyed(ServletContextEvent arg0) { System.out.println("1 destroy"); } @Override public void contextInitialized(ServletContextEvent arg0) { System.out.println("1 init"); try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("1 sleep complete"); } }