1. 程式人生 > 其它 >JavaEE實驗框架原理

JavaEE實驗框架原理

實驗一: Tomcat Embedded 啟動(實現一個Servlet)

  • 要求:使用Tomcat實現一個Servlet。 通過http://localhost:<學號後五位>/Test訪問這個Servlet,返回文字“學號:<學號>,學生姓名:<學生姓名>”

初始目錄

原始碼

 
         import java.io.File;
         import java.io.IOException;
         import java.io.Writer;
         
         import javax.servlet.ServletException;
         import javax.servlet.http.HttpServlet;
         import javax.servlet.http.HttpServletRequest;
         import javax.servlet.http.HttpServletResponse;
         
         import org.apache.catalina.Context;
         import org.apache.catalina.LifecycleException;
         import org.apache.catalina.startup.Tomcat;
         
         public class DemoServlet{
         
             public static void main(String[] args)
                     throws LifecycleException, InterruptedException, ServletException {
                 Tomcat tomcat = new Tomcat();
                 tomcat.setPort(16584); //設定埠號,學號後五位做埠號
         
                 Context ctx = tomcat.addContext("/", new File(".").getAbsolutePath());
         
                 Tomcat.addServlet(ctx, "Test", new HttpServlet() {
                     private static final long serialVersionUID = 1L;
         
                     @Override
                     protected void service(HttpServletRequest request, HttpServletResponse response)
                             throws ServletException, IOException {
                         response.setCharacterEncoding("UTF-8");
                         response.setContentType("text/plain");
                         try (Writer writer = response.getWriter()) {
                             writer.write("2019216584:<2019216584>,丁帥帥:<丁帥帥>");  // 響應請求的內容
                             writer.flush();
                         }
                     }
                 });
                 
                 ctx.addServletMappingDecoded("/*", "Test"); // 對映訪問路徑
         
                 tomcat.start();
                 tomcat.getServer().await();
             }
         
         }
      

編譯

javac  -cp ".;tomcat-embed-core.jar;annotations-api.jar"  -encoding "UTF-8" DemoServlet.java

執行

java  -cp ".;tomcat-embed-core.jar;annotations-api.jar"  DemoServlet

截圖

測試

http://localhost:16584/Test

截圖

結構圖

實驗二:Java的動態特性實現Java的動態特性實現

  • 實驗要求:實驗通過位元組碼工具Javassist實現Java的動態特性。為一個已經編譯好的Java類(.class檔案),新增一個方法sayHi()
    ,在螢幕上顯示 "Hi! <學號>-<姓名>"

原始碼

  // 被加方法的類,可以是別的類
       public class User{
           private int id;
           private String name;
       }
 import javassist.*;
import java.lang.reflect.Method;

public class DemoModifyByteCode{
    public static void main(String[] args) throws Exception {
	ClassPool pool = ClassPool.getDefault();

	try {
        CtClass ct = pool.get("User"); //獲得要修改的類物件

		CtMethod sayHi = CtNewMethod.make("public void sayHi(){System.out.println(\"Hi! 2019216584-丁帥帥\");}",ct); 
		ct.addMethod(sayHi);
		Class clazz = ct.toClass();
		User u = new User();
		Method getName = User.class.getDeclaredMethod("sayHi",new Class[]{});
		getName.invoke(u);
		//u.getName(); //不能直接呼叫
	    //ct.writeFile();
	}
	catch (NotFoundException e) {
		System.out.println(e);
	}
    }
}

編譯

javac -encoding UTF-8  User.java
javac -cp ".;javassist.jar"  -encoding "UTF-8" DemoModifyByteCode.java

執行

java  -cp ".;javassist.jar"  DemoModifyByteCode

截圖

實驗三: 框架實現方法實驗(反射與註解)

原始碼

// 註解(不用修改)
import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RunTest{
    	//引數預設為空
        String value() default "";
}
// 監聽程式(不需要修改)
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.io.File;
import java.io.FileInputStream;
import java.util.List;
import java.lang.reflect.*;
//import javassist.*;

public class ClassMonitor {
    public static void main(String[] args) throws Exception {
        // 需要監聽的檔案目錄(只能監聽目錄)
        String path = "./classes";
       
        WatchService watchService = FileSystems.getDefault().newWatchService();
        Path p = Paths.get(path);
        p.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY,  
                StandardWatchEventKinds.ENTRY_DELETE,  
                StandardWatchEventKinds.ENTRY_CREATE);  
        
        Thread thread = new Thread(() -> {
            try {  
                while(true){  
                    WatchKey watchKey = watchService.take();  
                    List<WatchEvent<?>> watchEvents = watchKey.pollEvents();  
                    for(WatchEvent<?> event : watchEvents){  
                        //根據事件型別採取不同的操作  
                        System.out.println("["+path+"/"+event.context()+"]檔案發生了["+event.kind()+"]事件"); 
						
						if(event.kind().equals(StandardWatchEventKinds.ENTRY_CREATE)||
                        event.kind().equals(StandardWatchEventKinds.ENTRY_MODIFY))
						{
							System.out.println(event.context());
						    String s = event.context().toString();
							if(s.contains(".class")) 
							{
								try{
								Thread.currentThread().sleep(1000);
							    Class clazz = Class.forName(s.replace(".class",""));
                                File newfile = new File(s);
                                byte[] bytes = new byte[(int)newfile.length()];
                                new FileInputStream(newfile).read(bytes);
                  

                                
								System.out.println("類的名字是:"+clazz.getName());
								
								System.out.println("類的屬性是:");
								Field[] fields = clazz.getDeclaredFields();
								for(Field fd : fields)
								{
									System.out.println(fd);
								}
								
								System.out.println("類的方法是:");
								//獲取該類的所有方法,不包括父類(僅自定義)
                                 Method[] declaredMethods = clazz.getDeclaredMethods();
								 for(Method md : declaredMethods)
								 {
									System.out.println(md);
                                    RunTest declaredAnnotation = md.getDeclaredAnnotation(RunTest.class);
                                    //獲取到他的值
                                    if(declaredAnnotation != null){
                                          String value = declaredAnnotation.value();
                                          System.out.println(value);
                                          md.invoke(clazz.getConstructor().newInstance());                                          
                                        }
								 }
								clazz = null;
								}
								catch(Exception e){
									System.out.println(e);
								}
							}
							
						}
						
                    }  
                    watchKey.reset();  
                }  
            } catch (InterruptedException e) {  
                e.printStackTrace();  
            }
        });
        thread.setDaemon(false);
        thread.start();
        
        // 增加jvm關閉的鉤子來關閉監聽
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            try {
                watchService.close();
            } catch (Exception e) {
            }
        }));
    }
}
// 測試類
public class Test{
    public int id;
    public String name;

    @RunTest("Test Run")
    public void print()
    {
        System.out.println("==============");
        System.out.println("測試註解");
    }
    @RunTest("測試註解的變數")
    public void show()
    {
        System.out.println("Show test world");
    }

    @RunTest
    public void show2()
    {
        System.out.println("show TTTTT");
    }
}

編譯

javac -encoding "UTF-8" RunTest.java
javac -encoding "UTF-8" ClassMonitor.java
javac -encoding "UTF-8" Test.java

執行

java ClassMonitor

測試

mkdir classes
copy Test.class classes

觀察執行java ClassMonitor的視窗變化

截圖

世界不會因為你的疲憊,而停下它的腳步