package org.chengxi.mvnframework.servlet;
import org.chengxi.mvnframework.annotation.*;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
class Handler{
//保存方法对应的实例
protected Object controller;
//保存映射的方法
protected Method method;
protected Pattern pattern;
//保存方法的参数顺序
protected Map<String, Integer> paramIndexMapping;
protected Handler(Object controller, Method method, Pattern pattern){
this.controller = controller;
this.method = method;
this.pattern = pattern;
paramIndexMapping = new HashMap<String, Integer>();
putParamIndexMapping(method);
}
//提取方法中加了@RequestParam注解的参数
public void putParamIndexMapping(Method method){
//提取方法中加了注解的参数
Annotation[][] pa = method.getParameterAnnotations();
for(int i=0; i<pa.length; i++){
for(Annotation a: pa[i]){
if(a instanceof RequestParam){
String paramName = ((RequestParam) a).value();
if(!"".equals(paramName)){
paramIndexMapping.put(paramName,i);
}
}
}
}
//提取方法中的resp和req参数
Class<?>[] paramsTypes = method.getParameterTypes();
for(int i=0; i<paramsTypes.length; i++){
Class<?> type = paramsTypes[i];
if(type == HttpServletRequest.class || type == HttpServletResponse.class){
paramIndexMapping.put(type.getName(), i);
}
}
}
}
public class DispatcherServlet extends HttpServlet {
private Properties p = new Properties();
private List<String> classNames = new ArrayList<String>();
private Map<String, Object> ioc = new HashMap<String, Object>();
private List<Handler> handlerMapping = new ArrayList<Handler>();
@Override
public void init(ServletConfig config) throws ServletException {
//获取属性文件,类似于获取application.xml文件所在路径
String application = config.getInitParameter("contextConfigLocation");
//1.加载配置文件
try {
doLoadConfig(application);
} catch (IOException e) {
e.printStackTrace();
}
//扫描配置文件中描述的相关的所有类
doScanner(p.getProperty("scanPackage"));
//3.实例化所有被扫描到的类并且存放到IOC容器中(自己实现容器)
try {
doInstance();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
//4.依赖注入,DI从IOC容器中找到加上了@Autowired注解的属性并找到其在IOC容器中对应的实例
try {
doAutowired();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
//5.把在@Controller中加了@RequestMapping注解的方法和URL构造成一个对应关系map
initHandlerMapping();
System.out.println(ioc);
System.out.println(handlerMapping);
System.out.println(classNames);
}
@Override
public void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
//6.等待用户请求,根据url找到对应的method,通过反射机制进行调用并执行返回响应
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
doDispatcher(req, resp);
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
private void doLoadConfig(String location) throws IOException {
InputStream is = this.getClass().getClassLoader().
getResourceAsStream(location);
p.load(is);
if(null != is){
is.close();
}
}
private void doScanner(String packageName){
URL url = this.getClass().getClassLoader().getResource("/" + packageName.replaceAll("\\.","/"));
File dir = new File(url.getFile());
for(File f: dir.listFiles()){
if(f.isDirectory()){
doScanner(packageName + "." + f.getName());
}
else{
classNames.add(packageName + "." + f.getName().replace(".class","").trim());
}
}
}
private void doInstance() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
if(classNames.isEmpty()){
return ;
}
for(String className: classNames){
Class<?> clazz = Class.forName(className);
//只初始化controller容器和service容器
if(clazz.isAnnotationPresent(Controller.class)){
//默认首字母小写称为beanName
String beanName = lowerFirst(clazz.getSimpleName());
ioc.put(beanName, clazz.newInstance());
}
else if(clazz.isAnnotationPresent(Service.class)){
//第一种形式:默认首字母小写
//第二种形式:注解自己提供名字(优先)
//第三种形式:利用接口本身全称作为key,其对应实现类作为值
Service service = clazz.getAnnotation(Service.class);
String beanName = service.value();
Object instance = clazz.newInstance();
//注解本身提供名字@service("sss")
if(!"".equals(beanName.trim())){
ioc.put(beanName, instance);
continue;
}
Class<?>[] interfaces = clazz.getInterfaces();
for(Class<?> inter: interfaces){
ioc.put(inter.getName(), instance);
}
}
}
}
private void doAutowired() throws IllegalAccessException {
if(ioc.isEmpty()){
return;
}
for(Map.Entry<String, Object> entry: ioc.entrySet()){
//获取所有字段
Field[] fields = entry.getValue().getClass().getDeclaredFields();
for(Field field: fields){
if(!field.isAnnotationPresent(Autowired.class)){
continue;
}
Autowired autowired = field.getAnnotation(Autowired.class);
String beanName = autowired.value().trim();
if("".equals(beanName)){
beanName = field.getType().getName();
}
//即使是private也要进行强制注入
field.setAccessible(true);
//开始赋值
field.set(entry.getValue(), io