spring入門—學習springMVC模擬實現

本文爲個人學習筆記,如有錯誤還請大佬指教!🙏

編寫流程

  1. 讀取配置文件 得到 需要掃描的基址包路徑
  2. 掃描包,獲取類名
  3. 初始化需要IOC容器管理的類,並將其保存到IOC容器中
  4. 執行依賴注入,即完成@Autowired
  5. 構建HandlerMapper,完成URL與Method的關聯映射

1. 創建普通的JavaWeb工程,並導入相關依賴 與 項目結構預覽

  1. 導入gson包
    在這裏插入圖片描述

2. 編寫註解類

  1. Autowired.java
@Target(ElementType.FIELD)		//說明此註解用於字段上
@Retention(RetentionPolicy.RUNTIME)	//運行時保留策略
public @interface Autowired {
	String value() default "";
}
  1. Component.java
@Target(ElementType.TYPE)		//說明此註解用在類上
@Retention(RetentionPolicy.RUNTIME)
public @interface Component {
	String value() default "";
}
  1. Controller.java
@Target(ElementType.TYPE)		//此註解用於類上
@Retention(RetentionPolicy.RUNTIME)
public @interface Controller {
	String value() default "";
}
  1. RequestMapping.java
@Target({ElementType.TYPE,ElementType.METHOD})		//說明此註解用在方法上
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestMapping {
	String value() default "";
}
  1. RequestParam.java
@Target(ElementType.PARAMETER)	//說明該註解用在方法的形參上
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestParam {
	String value() default "";
}
  1. ResponseBody.java
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ResponseBody {
	String value() default "";
}

3. 編寫配置文件(application.properties)

# 掃描的基址包路徑  此行註釋,若不支持中文,右鍵 -> Properties -> Text file encoding -> UTF-8
basePackage=com.hx.spring.mvc

4. 編寫HandleMapperInfo.java類,用於存放方法的信息

package com.hx.spring.mvc.core;

import java.lang.reflect.Method;
import java.util.Arrays;

public class HandleMapperInfo {
	private Object obj;			//方法所屬的對象
	private Method method;		//對應的方法
	private Object[] args;		//這個方法要的參數
	public Object getObj() {
		return obj;
	}
	public void setObj(Object obj) {
		this.obj = obj;
	}
	public Method getMethod() {
		return method;
	}
	public void setMethod(Method method) {
		this.method = method;
	}
	public Object[] getArgs() {
		return args;
	}
	public void setArgs(Object[] args) {
		this.args = args;
	}
	
	@Override
	public String toString() {
		return "HandleMapperInfo [obj=" + obj + ", method=" + method + ", args=" + Arrays.toString(args) + "]";
	}
	
	public HandleMapperInfo(Object obj, Method method) {
		super();
		this.obj = obj;
		this.method = method;
	}
	public HandleMapperInfo() {
		super();
	}
}

5. 編寫HandleRequest.java類處理請求

package com.hx.spring.mvc.core;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.hx.spring.mvc.core.annotation.RequestParam;

/**
 * 處理請求的類
 * @author Huathy
 * @date 2020年3月12日
 */
public class HandleRequest {
	/**
	 * 處理請求的方法
	 * @param req
	 * @param method
	 * @param resp
	 * @return
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 */
	public static Object[] handle(HttpServletRequest req,Method method,HttpServletResponse resp) throws InstantiationException, IllegalAccessException{
		int count = method.getParameterCount();		//獲取這個方法的參數個數
		if( count <= 0 ){
			return null;	//沒有參數,無需注值
		}
		Object[] objs = new Object[count];	//準備存放這個形參所需要的參數
		
		//取出當前方法的形參名
		Parameter[] params = method.getParameters();	//獲取當前方法的參數
		String pname = null;		//形參名
		RequestParam reqParam;		//註解
		String paramValue = null;	//參數值
		String typeName = null;		//形參的類型名稱
		int index = 0;				//形參索引下標
		Map<String,String[]> paramsMap = null;
		Map<String,String> map = null;
		
		Class<?> clazz = null;
		Field[] fields = null;		//類中的屬性
		Object instance = null;		//對應類的實例化對象
		String attrName = null;		//屬性名
		for( Parameter param : params ){
			//System.out.println( param.getName() +"\t"+ param.getModifiers() +"\t" + param.getType());
			//!!!!!!!這裏需要項目右擊  complite處做修改!!!!!!!!!
			pname = param.getName();
			typeName = param.getType().getSimpleName();
			
			//判斷此形參是否有@ReuqestParam註解
			reqParam = param.getAnnotation(RequestParam.class);
			if( reqParam != null ){
				pname = reqParam.value();	//有則通過這個裏面給定的名稱從request中取值
			}
			
			//根據參數名,從請求中取值
			paramValue = req.getParameter(pname);
			
			if( "Integer".equals(typeName) ){
				objs[index] = Integer.valueOf(paramValue);
			}else if( "int".equals(typeName) ){
				objs[index] = Integer.parseInt(paramValue);
			}else if( "Float".equals(typeName) ){
				objs[index] = Float.valueOf(paramValue);
			}else if( "float".equals(typeName) ){
				objs[index] = Float.parseFloat(paramValue);
			}else if( "Double".equals(typeName) ){
				objs[index] = Double.valueOf(paramValue);
			}else if( "double".equals(typeName) ){
				objs[index] = Double.parseDouble(paramValue);
			}else if( "String".equals(typeName) ){
				objs[index] = paramValue;
			}else if( "Map".equals(typeName) ){
				paramsMap = req.getParameterMap();
				map = new HashMap<String, String>();
				for( Entry<String,String[]> entry : paramsMap.entrySet() ){
					map.put(entry.getKey(), entry.getValue()[0]);
				}
				objs[index] = map;
			}else if( "HttpServletRequest".equals(typeName) || "ServletRequest".equals(typeName) ){
				objs[index] = req;
			}else if( "HttpServletResponse".equals(typeName) || "ServletResponse".equals(typeName) ){
				objs[index] = resp;
			}else if( "HttpSession".equals(typeName) ){
				objs[index] = req.getSession();
			}else if( "ServletContext".equals(typeName) ){
				objs[index] = req.getServletContext();
			}else{	//當成實體類注值
				clazz = param.getType();
				fields = clazz.getDeclaredFields();		//獲取這個類中的所有屬性
				
				instance = clazz.newInstance();		//實例化對象
				
				for(Field fd : fields){			//循環所有屬性注值
					fd.setAccessible(true); 	//設置可訪問,強問
					attrName = fd.getName();	//獲取屬性的名稱
					paramValue = req.getParameter(attrName);
					typeName = fd.getType().getSimpleName();	//獲取屬性的類型名稱
					
					if(paramValue == null){
						continue;		//說明這個屬性不需要注值
					}
					//如果不爲空,則有需要判斷屬性的類型
					if( "Integer".equals(typeName) ){
						fd.set(instance, Integer.valueOf(paramValue));
					}else if( "int".equals(typeName) ){
						fd.set(instance, Integer.parseInt(paramValue));
					}else if( "Float".equals(typeName) ){
						fd.set(instance, Float.valueOf(paramValue));
					}else if( "float".equals(typeName) ){
						fd.set(instance, Float.parseFloat(paramValue));
					}else if( "Double".equals(typeName) ){
						fd.set(instance, Double.valueOf(paramValue));
					}else if( "double".equals(typeName) ){
						fd.set(instance, Double.parseDouble(paramValue));
					}else {
						fd.set(instance, paramValue);
					}
				}
				objs[index] = instance;
			}
			++ index;
		}
		return objs;
	}
}

6. 編寫HandleResponse.java類處理響應

package com.hx.spring.mvc.core;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

/**
 * 處理響應的類
 * @author Huathy
 * @date 2020年3月12日
 */
public class HandleResponse {
	/**
	 * 404
	 * @param resp
	 * @param url
	 * @throws IOException
	 */
	protected static void send404(HttpServletResponse resp ,String url) throws IOException {
		PrintWriter out = resp.getWriter();
		out.print("<h1>HTTP/1.1 404 File Not Found - "+ url +"</h1>");
		out.flush();
	}
	
	/**
	 * 以字節方式返回
	 * @param resp
	 * @param bt
	 * @throws IOException
	 */
	protected static void sendDate(HttpServletResponse resp ,byte[] bt) throws IOException {
		ServletOutputStream sos = resp.getOutputStream();
		sos.write(bt);
		sos.flush();
	}
	
	/**
	 * 以json格式返回
	 * @param resp
	 * @param obj
	 * @throws IOException
	 */
	protected static void sendJson(HttpServletResponse resp,Object obj) throws IOException {
		PrintWriter out = resp.getWriter();
		Gson gson = new GsonBuilder().serializeNulls().create();
		out.print( gson.toJson(obj) );
		out.flush();
	}
}

7. 封裝判空方法StringUtil.java

package com.hx.spring.mvc.util;
//由於經常調用封裝以下判空方法
public class StringUtil {
	//爲空判斷
	public static boolean checkNull(String ... strs){
		if(strs == null){
			return true;
		}
		for( String str : strs ){
			if(str == null || "".equals(str)){
				return true;
			}
		}
		return false;
	}
}

8. 編寫業務層接口與實現類

  1. IPersonBiz接口
package com.hx.spring.mvc.biz;

import com.hx.spring.mvc.entity.Person;

public interface IPersonBiz {
	public Person findByPid(Integer pid);
}
  1. 實現類 PersonBizImpl.java
package com.hx.spring.mvc.biz.impl;

import com.hx.spring.mvc.biz.IPersonBiz;
import com.hx.spring.mvc.core.annotation.Autowired;
import com.hx.spring.mvc.core.annotation.Component;
import com.hx.spring.mvc.dao.IPersonDao;
import com.hx.spring.mvc.entity.Person;

@Component
public class PersonBizImpl implements IPersonBiz {
	@Autowired
	private IPersonDao personDao;
	
	@Override
	public Person findByPid(Integer pid) {
		return personDao.findByPid(pid);
	}

}

9. 編寫控制器 DemoController.java

package com.hx.spring.mvc.controller;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpSession;

import com.hx.spring.mvc.biz.IPersonBiz;
import com.hx.spring.mvc.core.annotation.Autowired;
import com.hx.spring.mvc.core.annotation.Controller;
import com.hx.spring.mvc.core.annotation.RequestMapping;
import com.hx.spring.mvc.core.annotation.RequestParam;
import com.hx.spring.mvc.core.annotation.ResponseBody;
import com.hx.spring.mvc.entity.Person;

@Controller		//說明是個控制器
@RequestMapping("/demo")
public class DemoController{
	
	@Autowired
	private IPersonBiz personBizImpl;
	
	@RequestMapping("find")
	public String find(){
		return "redirect:/back/dept.html";
	}
	
	@RequestMapping("finds")
	public String finds(){
		return "/back/emp.html";
	}
	
	@RequestMapping("/find1")
	public String find1(String ename,Integer age){
		System.out.println(ename + "\t" +age);
		return "redirect:/back/emp.html";
	}
	
	@RequestMapping("/find2")
	@ResponseBody	//說明以json格式返回數據
	public Person find2(String ename,HttpSession session){
		Person person = personBizImpl.findByPid(101);
		session.setAttribute("person", person);
		System.out.println( session.getAttribute("person") );
		return person;
	}
	
	@RequestMapping("/find3")
	@ResponseBody
	public List<Person> find3(Person p){
		System.out.println(p);
		List<Person> list = new ArrayList<>();
		list.add( new Person(101,"huathy",18,"123456778") );
		list.add( new Person(102,"huasy",20,"123456778") );
		list.add( new Person(102,"qq",20,"123456778") );
		return list;
	}
	
	@RequestMapping("/find4")
	public String find4(@RequestParam("name")String ename){
		System.out.println(ename);
		return "/back/dept.html";
	}
	
	@RequestMapping("/find5")
	@ResponseBody
	public List<Person> find5(Person p, String company){
		System.out.println(p);
		System.out.println(company);
		List<Person> list = new ArrayList<>();
		list.add( new Person(101,"huathy",18,"123456778") );
		list.add( new Person(102,"huasy",20,"123456778") );
		list.add( new Person(102,"qq",20,"123456778") );
		return list;
	}
	
	@RequestMapping("/find6")
	@ResponseBody
	public List<Person> find6(Map<String,String> map){
		System.out.println(map);
		List<Person> list = new ArrayList<>();
		list.add( new Person(101,"huathy",18,"123456778") );
		list.add( new Person(102,"huasy",20,"123456778") );
		list.add( new Person(102,"qq",20,"123456778") );
		return list;
	}
}

10. 編寫HxFrameworkCore.java

package com.hx.spring.mvc.core;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;

import com.hx.spring.mvc.core.annotation.Autowired;
import com.hx.spring.mvc.core.annotation.Component;
import com.hx.spring.mvc.core.annotation.Controller;
import com.hx.spring.mvc.core.annotation.RequestMapping;
import com.hx.spring.mvc.util.StringUtil;

public class HxFrameworkCore {
	
	private String contextConfigLocation;		//配置文件路徑
	private String basePackage;					//要掃描的包的基址路徑
	private Set<String> classNames = new HashSet<String>();		//掃描到的類路徑
	private Map<String,Object> instanceObject = new HashMap<String,Object>();		//用來存放實例化後的類
	private Map<String,HandleMapperInfo> handleMapper = new HashMap<String,HandleMapperInfo>();		//用來存放url與method的關聯映射
	
	public HxFrameworkCore(String contextConfigLocation) {
		this.contextConfigLocation = contextConfigLocation;
		init();
	}
	
	/**
	 * 初始化方法
	 */
	private void init() {
		//1. 讀取配置文件  ->  需要掃描的基址包路徑
		doLoadConfig();
		//2. 掃描包,獲取類名
		doScannerPackage();
		//3. 初始化需要IOC容器管理的類,並將其保存到IOC容器中
		doInstanceObject();
		//4. 執行依賴注入,即完成@Autowired
		doAutowired();
		//5. 構建HandlerMapper,完成URL與Method的關聯映射
		initHandlerMapper();
	}
	/**
	 * 1. 讀取配置文件  ->  要掃描的包路徑
	 */
	private void doLoadConfig() {
		try (InputStream is = this.getClass().getClassLoader().getResourceAsStream(contextConfigLocation)){
			Properties properties = new Properties();
			properties.load(is);
			basePackage = properties.getProperty("basePackage");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 2. 掃描包,獲取類名
	 */
	private void doScannerPackage() {
		if(StringUtil.checkNull(basePackage)){
			throw new RuntimeException("配置文件獲取失敗,請配置與contextConfigLocation參數!");
		}
		//System.out.println(basePackage);
		URL url = this.getClass().getClassLoader().getResource(basePackage.replaceAll("\\.", "/"));
		//System.out.println(url);
		File dist = new File(url.getFile());
		//System.out.println(dist.getAbsolutePath());
		getClassInfo(basePackage,dist);
		//System.out.println(classNames);
	}
	
	/**
	 * 獲取指定文件夾下的所有文件及其子文件夾中的文件
	 * @param basePackage
	 * @param dist
	 */
	private void getClassInfo(String basePackage, File dist) {
		if(dist.isDirectory()){			//判斷是否是一個目錄
			for(File fl : dist.listFiles()){	//循環獲取當前文件夾下的文件或子文件夾
				if( fl.isDirectory() ){
					getClassInfo(basePackage + "." + fl.getName() , fl);
				}else{
					classNames.add( basePackage + "." + fl.getName().replace(".class", "") );	//獲取類名,替換掉“.class”
				}
			}
		}
	}
	
	/**
	 * 3. 初始化需要IOC容器管理的類,並將其保存到IOC容器中
	 */
	private void doInstanceObject() {
		if(classNames.isEmpty()){
			return;
		}
		
		Class<?> cls = null;
		Class<?>[] interfaces = null;
		String beanName = null;
		String temp;
		Object instance = null;
		for(String calssName : classNames){
			try {
				cls = Class.forName(calssName);
				
				beanName = toFirstLowerCase(cls.getSimpleName()); //默認就是將類名第一個字母轉爲小寫
				
				//判斷這個類上是否有@Component、@Controller註解,若有則實例化,否則不管
				if( cls.isAnnotationPresent(Controller.class) ){	//如果有
					temp = cls.getAnnotation(Controller.class).value();
					if( !StringUtil.checkNull(temp) ){
						beanName = temp;
					}
					instanceObject.put(beanName, cls.newInstance());
				}else if( cls.isAnnotationPresent(Component.class) ){
					instance = cls.newInstance();
					temp = cls.getAnnotation(Component.class).value();
					if( !StringUtil.checkNull(temp) ){
						beanName = temp;
					}
					instanceObject.put(beanName, instance);
					
					//如果這個類上有實現其他接口,爲了方便到時候可以將該實現類注入到對應的接口,即可以根據接口注值,我們將實現類與接口名相關聯
					//到時候可以通過接口名直接找到對應的實現類注入
					interfaces = cls.getInterfaces();
					for(Class<?> itfs : interfaces){
						instanceObject.put(itfs.getSimpleName(), instance);
					}
				}
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			} catch (InstantiationException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * 將給定的字串第一個字母轉爲小寫
	 * @param name
	 * @return
	 */
	private String toFirstLowerCase(String name){
		char[] chs = name.toCharArray();
		chs[0] += 32;
		return String.valueOf( chs );
	}

	/**
	 *  4. 執行依賴注入,即完成@Autowired
	 */
	private void doAutowired() {
		if(instanceObject.isEmpty()){
			return;
		}
		
		//要獲取這個對象中的屬,然後看這個屬性上有沒有@Autowired註解,有才需要處理
		Field[] fields = null;
		Class<?> cls = null;
		Autowired awd = null;
		String beanName = null;
		
		for(Entry<String,Object> entry : instanceObject.entrySet()){
			cls = entry.getValue().getClass();		//獲取當前對象的類信息
			fields = cls.getDeclaredFields();		//獲取當前類中的所有屬性
			
			for( Field fd : fields ){		//喜歡所有屬性判斷有沒有@Autowired註解
				if( !fd.isAnnotationPresent(Autowired.class) ){
					continue;
				}
				
				awd = fd.getAnnotation(Autowired.class);	//獲取這個註解
				beanName = awd.value().trim();		//獲取這個註解上配置的名字
				
				//注意:此時所有的屬性都是私有的,並且沒有給該私有屬性提供公有的setter方法,這個時候需要 強吻(強行訪問)   即設置可訪問
				fd.setAccessible(true);
				
				if(!StringUtil.checkNull(beanName)){		//如果指定了注入的bean名稱
					if(!instanceObject.containsKey(beanName)){	//如果需要注入的這個bean沒有交給IOC容器管理
						throw new RuntimeException(cls.getName() + "." + fd.getName() + "注值失敗,沒有對應的實體類" + beanName);
					}
					try {
						fd.set(entry.getValue(), instanceObject.get(beanName));
					} catch (IllegalArgumentException e) {
						e.printStackTrace();
					} catch (IllegalAccessException e) {
						e.printStackTrace();
					}
				}else{
					//根據類型注值
					beanName = fd.getType().getSimpleName();	//獲取該字段所屬類的類名
					try {
						fd.set(entry.getValue(), instanceObject.get(beanName));
					} catch (IllegalArgumentException e) {
						e.printStackTrace();
					} catch (IllegalAccessException e) {
						e.printStackTrace();
					}
				}
			}
		}
	}
	
	/**
	 * 5. 構建HandlerMapper,完成URL與Mehtod的關聯映射
	 */
	private void initHandlerMapper() {
		if( instanceObject.isEmpty() ){
			return;
		}
		Class<?> cls = null;
		String baseUrl = "";
		Method[] methods = null;
		RequestMapping reqMapper = null;
		String url = null;
		
		for(Entry<String,Object> entry : instanceObject.entrySet()){
			cls = entry.getValue().getClass();		//獲取當前對象的類信息
			
			//判斷這個類上有無@Controller註解
			if( !cls.isAnnotationPresent(Controller.class) ){
				continue;
			}
			
			reqMapper = cls.getAnnotation(RequestMapping.class);	//判斷這個類上是否有@RequestMapping註解
			if( reqMapper != null ){	//若不爲空,則取出配置
				baseUrl = reqMapper.value();
				
				if( !baseUrl.startsWith("/") ){		//說明用戶忘記打"/"
					baseUrl = "/" +baseUrl;
				}
			}
			
			//獲取這個類中的所有方法
			methods = cls.getDeclaredMethods();
			if(methods == null || methods.length <= 0){
				continue;
			}
			
			for( Method method : methods ){		//判斷是否有@RequestMapping註解
				if( !method.isAnnotationPresent(RequestMapping.class) ){
					continue;
				}
				reqMapper = method.getAnnotation(RequestMapping.class);
				
				url = reqMapper.value();
				if(!url.startsWith("/")){	//如果沒有打"/"
					url = "/" + url;
				}
				url = baseUrl + url;
				
				handleMapper.put(url.replace("/+", "/"), new HandleMapperInfo(entry.getValue(),method));
			}
		}
		System.out.println(handleMapper);
	}
	
	/**
	 * 根據請求地址獲取處理方法
	 * @param url
	 * @return
	 */
	public HandleMapperInfo getMapper(String url){
		return handleMapper.getOrDefault(url, null);
	}

	public Set<String> getClassNames() {
		return classNames;
	}

	public Map<String, Object> getInstanceObject() {
		return instanceObject;
	}
}

11. 編寫分發器DispatcherServlet.java

package com.hx.spring.mvc.core;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.hx.spring.mvc.core.annotation.ResponseBody;
import com.hx.spring.mvc.util.StringUtil;

public class DispatcherServlet extends HttpServlet{
	private static final long serialVersionUID = 4519806829458692203L;

	private HxFrameworkCore frameworkCore = null;
	
	@Override
	public void init(ServletConfig config){
		String configName = "application.properties";
		String temp = config.getInitParameter("contextConfigLocation");
		if( !StringUtil.checkNull(temp) ){
			configName = temp;
		}
		//讀取配置文件,掃描解析註解
		frameworkCore = new HxFrameworkCore(configName);
	}
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doPost(req, resp);
	}
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		// 獲取請求地址
		String url = req.getRequestURI();
		// 獲取項目名
		String contextPath = req.getContextPath();
		// 獲取請求的資源地址
		url = url.replace(contextPath, "").replaceAll("/+", "/");	//處理多餘的“/”
		if( url.contains("?") ){		//說明請求地址中有帶參數
			url = url.substring(0, url.indexOf("?"));
		}
		
		// 獲取有沒有處理這個請求的方法
		HandleMapperInfo mapperInfo = frameworkCore.getMapper(url);
		
		if(mapperInfo == null){	//說明此路徑沒有配置對應的處理方法,則先判斷是否是靜態資源,若也不是,則報錯404
			handleStaticResource(req.getServletContext().getRealPath("") + url.substring(1), resp);// 當作靜態資源處理
			return;
		}
		
		try {
			//若有,則激活此方法,處理這個方法需要的參數,然後獲得此方法的返回值
			Method method = mapperInfo.getMethod();
			
			//處理這個方法所需參數
			Object[] args = HandleRequest.handle(req, method, resp);
			
			Object obj = method.invoke(mapperInfo.getObj(), args);
			
			// 判斷這個方法是否以json格式返回
			if(method.isAnnotationPresent(ResponseBody.class)){
				HandleResponse.sendJson(resp, obj);		//以json格式返回
				return;
			}
			
			if( method.isAnnotationPresent(ResponseBody.class) ){
				//說明以json格式返回
			}else{
				//若沒有,則將這個返回對象當作是一個靜態資源
				String path = String.valueOf(obj);
				if( path.startsWith("redirect:") ){	//說明要以重定向方式
					path = path.replace("redirect:", "");
					if( path.startsWith("/") ){
						path = contextPath + path;
					}
					resp.sendRedirect(path);
					return;
				}
				//否則以內部轉發的方法
				if( path.startsWith("/") ){
					path = contextPath + path;
				}
				System.out.println(path);
				req.getRequestDispatcher(path).forward(req, resp);
			}
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 處理靜態資源的方法
	 * @param url
	 * @param resp
	 * @throws IOException
	 */
	private void handleStaticResource(String url,HttpServletResponse resp) throws IOException{
		File file = new File(url);
		if( !file.exists() || !file.isFile() ){
			HandleResponse.send404(resp, url);
			return;
		}
		
		try(FileInputStream fis = new FileInputStream(file)){
			byte[] bt = new byte[fis.available()];
			fis.read(bt);
			HandleResponse.sendDate(resp, bt);
		}catch(Exception e){
			e.printStackTrace();
		}
	}
}

12. 配置WEB-INF下的web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://xmlns.jcp.org/xml/ns/javaee"
	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
	id="WebApp_ID" version="3.1">
	<display-name>200311mySpringMvc</display-name>
	
	<!-- 配置servlet -->
	<servlet>
		<servlet-name>DispathcherServlet</servlet-name>
		<servlet-class>com.hx.spring.mvc.core.DispatcherServlet</servlet-class>
		<init-param>	<!-- 初始化參數 -->
			<param-name>contextConfigLocation</param-name>
			<param-value>application.properties</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>DispathcherServlet</servlet-name>
		<url-pattern>/*</url-pattern>
	</servlet-mapping>
	
	
	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
	</welcome-file-list>
</web-app>

13. 編寫網頁進行測試

  1. index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1> <a href="demo/find" target="_blank">find</a> </h1>
<h1> <a href="demo/finds" target="_blank">finds</a> </h1>
<hr/>
<h1> <a href="demo/find1?ename=huathy&age=20" target="_blank">find1</a> </h1>
<h1> <a href="javascript:find2()" >find2</a> </h1>
<h1> <a href="javascript:find3()" >find3</a> </h1>
<h1> <a href="demo/find4?name=huathy" target="_blank">find4</a> </h1>
<hr/>
<h1> <a href="javascript:find5()" >find5</a> </h1>
<h1> <a href="javascript:find6()" >find6</a> </h1>

<script type="text/javascript" src="js/jquery-1.12.4.min.js"></script>
<script type="text/javascript">
	function find2(){
		$.post("demo/find2",{
			name : 'huathy'
		},function(data){
			console.log(data);
		},"json");
	}

	function find3(){
		$.post("demo/find3",{
			pid : 101,
			pname : 'huathy',
			age : 20,
			tel : '123456789'
		},function(data){
			console.log(data);
		},"json");
	}
	
	function find5(){
		$.post("demo/find5",{
			pid : 101,
			pname : 'huathy',
			age : 20,
			tel : '123456789',
			company : 'huathy科技'
		},function(data){
			console.log(data);
		},"json");
	}
	
	function find6(){
		$.post("demo/find6",{
			pid : 101,
			pname : 'huathy',
			age : 20,
			tel : '123456789'
		},function(data){
			console.log(data);
		},"json");
	}
</script>
</body>
</html>
  1. 其他頁面
    在這裏插入圖片描述
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章