public class WzxDispatchServlet extends HttpServlet {
private Properties contextConfig = new Properties();
private List<String> classNames = new ArrayList();
//ioc容器 key默认是首字母小写类名, value实例对象
private Map<String, Object> ioc = new HashMap<String, Object>(16);
private Map<String, Method> handlerMapping = new HashMap<String, Method>(16);
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//6、委派,根据url去找到一个对应的method并通过resp返回
try {
doDispatch(req, resp);
} catch (Exception e) {
e.printStackTrace();
resp.getWriter().write("500 Exception , Detail : " + Arrays.toString(e.getStackTrace()));
}
}
private void doDispatch(HttpServletRequest req, HttpServletResponse resp) throws Exception {
String url = req.getRequestURI();
String contextPath = req.getContextPath();
url = url.replaceAll(contextPath, "").replaceAll("/+", "/");
if(!this.handlerMapping.containsKey(url)){
resp.getWriter().write("404 Not Found !");
return;
}
Map<String, String[]> params = req.getParameterMap();
Method method = this.handlerMapping.get(url);
//获取形参列表
Class<?> [] parameterTypes = method.getParameterTypes();
Object [] paramValues = new Object[parameterTypes.length];
for (int i = 0; i < parameterTypes.length; i++) {
Class paramterType = parameterTypes[i];
if(paramterType == HttpServletRequest.class){
paramValues[i] = req;
}else if(paramterType == HttpServletResponse.class){
paramValues[i] = resp;
}else if(paramterType == String.class){
//通过运行时的状态去拿到你
Annotation[] [] pa = method.getParameterAnnotations();
for (int j = 0; j < pa.length ; j ++) {
for(Annotation a : pa[i]){
if(a instanceof WzxRequestParam){
String paramName = ((WzxRequestParam) a).value();
if(!"".equals(paramName.trim())){
String value = Arrays.toString(params.get(paramName))
.replaceAll("\\[|\\]","")
.replaceAll("\\s+",",");
paramValues[i] = value;
}
}
}
}
}
}
String beanName = method.getDeclaringClass().getSimpleName();
method.invoke(ioc.get(toLowerFirstCase(beanName)), paramValues);
}
@Override
public void init(ServletConfig config) throws ServletException {
//1、加载配置文件
doLoadConfig(config.getInitParameter("contextConfigLocation"));
//2、扫描相关的类
doScanner(contextConfig.getProperty("scanpackage"));
//===============以上为ioc部分=============
//3、初始化ioc容器,将扫描到的相关的类实例化,保存ioc容器中
doInstance();
//Aop在DI之前(是新生成的代理对象)
//===============以上为DI部分=============
//4、完成依赖注入DI
doAutowired();
//===============以上为mvc部分=============
//5、初始化handerMapping;(url与方法映射关系)
doInitHandlerMapping();
System.out.println("wzx spring context ");
}
private void doInitHandlerMapping() {
if(ioc.isEmpty()){ return; }
for(Map.Entry<String, Object> entry : ioc.entrySet()){
Class<?> clazz = entry.getValue().getClass();
//判断是不是controller
if (!clazz.isAnnotationPresent(WzxController.class)){ continue; }
//url拼接,提取class上的url
String baseUrl = "";
if (clazz.isAnnotationPresent(WzxController.class)){
WzxRequestMapping requestMapping = clazz.getAnnotation(WzxRequestMapping.class);
baseUrl = requestMapping.value();
}
//只获取public的方法
for(Method method : clazz.getMethods()){
if (!method.isAnnotationPresent(WzxRequestMapping.class)) { continue;}
WzxRequestMapping requestMapping = method.getAnnotation(WzxRequestMapping.class);
//url拼接,类+方法 (正则替换,多/转换成单/)
String url = ("/" + baseUrl +"/" + requestMapping.value()).replaceAll("/+", "/");
handlerMapping.put(url, method);
System.out.println("Mapped : " + url +"," + method);
}
}
}
private void doAutowired() {
if(ioc.isEmpty()){return;}
for(Map.Entry<String, Object> entry : ioc.entrySet()){
//把所有的private/protected/public都获取
for(Field field : entry.getValue().getClass().getDeclaredFields()){
if(!field.isAnnotationPresent(WzxAutowired.class)){ continue; }
WzxAutowired autowired = field.getAnnotation(WzxAutowired.class);
String beanName = autowired.value().trim();
if("".equals(beanName)){
//获取字段的类型
beanName = field.getType().getName();
}
field.setAccessible(true);
try {
field.set(entry.getValue(), ioc.get(beanName));
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
private void doInstance() {
//用反射
if(classNames.isEmpty()){return;}
try {
for (String className : classNames) {
Class<?> clazz = Class.forName(className);
if (clazz.isAnnotationPresent(WzxController.class)) {
String beanName = clazz.getSimpleName();
//获取到对象实例
Object instance = clazz.newInstance();
//放到ioc容器中
ioc.put(toLowerFirstCase(beanName), instance);
} else if(clazz.isAnnotationPresent(WzxService.class)){
//2、多个包下出现相同的类名,只能自己起一个全局唯一的名字
//获取自定义命名
String beanName = clazz.getAnnotation(WzxService.class).value();
//1、默认的类名首字母小写
if("".equals(beanName.trim())){
beanName = clazz.getSimpleName();
}
Object instance = clazz.newInstance();
ioc.put(toLowerFirstCase(beanName), instance);
//3、若果是接口,判断它又多少个实现类,如果只有一个就选择它,如果多个只能抛异常
for(Class<?> i : clazz.getInterfaces()){
if(ioc.containsKey(i.getName())){
throw new Exception("The " + i.getName() + "is exists !");
}
ioc.put(i.getName(), instance);
}
} else {
continue;
}
}
}catch (Exception e){
e.printStackTrace();
}
}
private void doScanner(String scanpackage) {
//扫描所有class文件
URL url = this.getClass().getClassLoader().getResource("/" + scanpackage.replaceAll("\\.", "/"));
File classPath = new File(url.getFile());
//当成一个classPath文件夹
for (File file : classPath.listFiles()){
if(file.isDirectory()){
doScanner(scanpackage + "." + file.getName());
}else {
if (!file.getName().endsWith(".class")) {continue;}
String className = scanpackage + "." +file.getName().replace(".class", "");
//Class.forName(className),缓存className
classNames.add(className);
}
}
}
private void doLoadConfig(String contextConfigLocation) {
InputStream is = this.getClass().getClassLoader().getResourceAsStream(contextConfigLocation);
try {
contextConfig.load(is);
} catch (IOException e) {
e.printStackTrace();
}finally {
if(is != null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private String toLowerFirstCase(String source){
if (source.isEmpty()){return null;}
char[] sourceArray = source.toCharArray();
sourceArray[0] += 32;
return String.valueOf(sourceArray);
}
}
网友评论