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. 其他页面
    在这里插入图片描述
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Huathy-雨落江南,浮生若梦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值