springMVC相当于spring+servlet
springBoot更多的偏向于注解
解读springMVC源码我们可以学习到:
设计模式:
单例模式
工厂模式
适配器模式
1、springIOC容器(装的是bean),控制反转,依赖注入,底层相当于一个HashMap
当我们尝试下面动作时:
Object object = new Object();
spring将我们创造的对象放到一个容器中,存储到内存中,使用HashMap
Class<> clazz = class.forname("类的位置")
---启动成功后所有的bean都会放到HashMap中来
map.put(“key”,“object”)
IOC==大MAP
War xxx.war -->.class
@Service
public class Aservice{
}
@Controller
public class Acontroller{
@Autowired
privite Aservice aservice;
}
tomcat: object.class 启动的过程中,加载ioc容器(Map对象)---把我们所有的声明注解的类全部实例化 例如new 对象,
1)Aservice aservice = new Aservice();
2)Map.put("aservice",aservice)
3)Acontroller acontroller = new Acontroller();
4)Map.put("acontroller",acontroller)
5)初始化Autowired在map中去寻找
Aservice aservice = map.get("aservice")此过程就是依赖注入
启动过程中bean的初始化
tomcat启动成功-->
调用
注解的定义:
@Docunmented注解是不是包含在javaDOC中
@Retendion什么时候使用该注解 source、class、runtime
@Target注解用于什么地方
@Inherited
反射机制:
1.Class<?> clazz = class.forname("类的位置")
2.Aservice aservice =clazz.newInstance() 反射创建实例
3.Class> clazz = aservice.getClass() 根据实例拿到类
4.Field[] fields = clazz.getDeclaredFields() 拿到类里面定义的所有属性
5.Medthod [] medthod = clazz.getMedthods() 获取所有方法
6.medthod.invoke(a.args[])
7.request.getRequestURI() 获取请求路径
接下来中重点来了----上代码:
一、定义注解
spring框架中的@Autowired
package supmain.annotation;
import java.lang.annotation.*;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SupmainAutowiredanno {
String value() default "";
}
@Controller
package supmain.annotation;
import java.lang.annotation.*;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SupmainControlleranno {
String value() default "";
}
@RequrstMapping
package supmain.annotation;
import java.lang.annotation.*;
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SupmainRequestmappinganno {
String value() default "";
}
@RequestParam
package supmain.annotation;
import java.lang.annotation.*;
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SupmainRequestParamanno{
String value() default "";
}
@Service
package supmain.annotation;
import java.lang.annotation.*;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SupmainServiceanno {
String value() default "";
}
dao层在这里太麻烦,就不写了,毕竟我们可以使用mybatis框架代替,那是另外的事情
直接上service层
简单定义一个service接口
package supmain.Service;
public interface SupmainService {
String query(String name ,String pwd);
}
service的实现类
package supmain.Service.impl;
import supmain.Service.SupmainService;
import supmain.annotation.SupmainServiceanno;
@SupmainServiceanno("SupmainServiceImpl")//在tomcat启动的时候加载,map.put("SupmainServiceImpl",new SupmainServiceImpl())
public class SupmainServiceImpl implements SupmainService {
@Override
public String query(String name, String pwd) {
return "name ==== "+name+"pwd===="+pwd;
}
}
接下来是controller层
package supmain.Controller;
import supmain.Service.SupmainService;
import supmain.annotation.SupmainAutowiredanno;
import supmain.annotation.SupmainControlleranno;
import supmain.annotation.SupmainRequestParamanno;
import supmain.annotation.SupmainRequestmappinganno;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@SupmainControlleranno
@SupmainRequestmappinganno("/supmain")
public class SupmainController {
@SupmainAutowiredanno("SupmainServiceImpl") //map.get("SupmainServiceImpl")
private SupmainService supmainService;//springMVC使用的key是supmainService
@SupmainRequestmappinganno("/query")
public void query(HttpServletRequest request, HttpServletResponse response,
@SupmainRequestParamanno("name") String name,
@SupmainRequestParamanno("pwd")String pwd){
try {
PrintWriter writer = response.getWriter();
String str = supmainService.query(name,pwd);
writer.write(str);
} catch (IOException e) {
e.printStackTrace();
}
}
}
最后上大餐来了----大家都知道SpringMVC最重要的核心部分是DispatcherServlet
话不多BB,那么现在就来献上此核心代码--------->>>
package supmain.servlet;
import supmain.Controller.SupmainController;
import supmain.annotation.*;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
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.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.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class DispatcherServlet extends HttpServlet {
List classnames = new ArrayList();
//这就是我们的IOC
Map beans = new HashMap();
//init保证在tomcat启动的时候扫描所有的类,要实例化的bean map ioc
//handerMap
Map handerMap = new HashMap();
public void init(ServletConfig servletConfig){
//1.先要扫描
basePackageScan("supmain");
//2.实例化,创建bean
doInstance();
//3.注入属性
doAutowired();
//4.映射
doUrlMapping();
}
public void doUrlMapping(){
for (Map.Entry entry:beans.entrySet()){
Object instance = entry.getValue();
//反推,为了进行逻辑判断
Class> clazz = instance.getClass();
//只有控制类才有mapping请求路径
if (clazz.isAnnotationPresent(SupmainControlleranno.class)) {
//获取类上mapping注解的value
SupmainRequestmappinganno requestmappinganno1 = clazz.getAnnotation(SupmainRequestmappinganno.class);
String classPath = requestmappinganno1.value();
Method[] methods = clazz.getMethods();
for (Method method : methods){
if (method.isAnnotationPresent(SupmainRequestmappinganno.class)){
SupmainRequestmappinganno requestmappinganno2 = method.getAnnotation(SupmainRequestmappinganno.class);
String methodPath = requestmappinganno2.value();
String requestPath = classPath+methodPath;
handerMap.put(requestPath,method);
}else {
continue;
}
}
}else {
continue;
}
}
}
public void doAutowired(){
for (Map.Entry entry:beans.entrySet()){
Object instance = entry.getValue();
//反推,为了进行逻辑判断
Class> clazz = instance.getClass();
if (clazz.isAnnotationPresent(SupmainControlleranno.class)){
//得到所有的变量
Field[] fields = clazz.getDeclaredFields();
for (Field field :fields){
if (field.isAnnotationPresent(SupmainAutowiredanno.class)){
SupmainAutowiredanno autowiredanno = field.getAnnotation(SupmainAutowiredanno.class);
String key = autowiredanno.value();
//拿到对象实例
Object bean = beans.get(key);
//注入 先打破封装
field.setAccessible(true);
try {
field.set(instance,bean);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}else {
continue;
}
}
}else {
continue;
}
}
}
public void doInstance(){
for (String classname: classnames){
//去掉后缀名class
String cn = classname.replace(".class","");
//System.out.println(cn+"大家打开短短两开门v");
try {
Class> clazz = Class.forName(cn);
if (clazz.isAnnotationPresent(SupmainControlleranno.class)){
//控制类
//实例化对象
Object instance = clazz.newInstance();
//拿到注解对象
SupmainRequestmappinganno requestmappinganno = clazz.getAnnotation(SupmainRequestmappinganno.class);
//拿到注解中的key
String key = requestmappinganno.value();
//创建map
beans.put(key,instance);
}else if (clazz.isAnnotationPresent(SupmainServiceanno.class)){
//服务类
//实例化对象
Object instance = clazz.newInstance();
//拿到注解对象
SupmainServiceanno serviceanno = clazz.getAnnotation(SupmainServiceanno.class);
//拿到注解中的key
String key = serviceanno.value();
//创建map
beans.put(key,instance);
}else {
continue;
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
private void basePackageScan(String basePackage){
//扫描编译好的类路径
URL url = this.getClass().getClassLoader().
getResource(basePackage.replaceAll("\\.","/"));
// System.out.println("奶大大大大大大大大大嘎达"+url);
String fileStr = url.getFile();
File file = new File(fileStr);
String [] fileStrs = file.list();
// System.out.println(fileStr+"dadadadadada");
for (String path:fileStrs){
//System.out.println("你好你的路径是567------"+path);
File filepath =new File(fileStr+File.separator+path);
//System.out.println(filepath);
if (filepath.isDirectory()){
//System.out.println("你好你的路径是------"+basePackage+"."+path);
basePackageScan(basePackage+"."+path);
}else {
//System.out.println("你好你的路径是123------"+basePackage+"."+path);
classnames.add(basePackage+"."+filepath.getName());
}
}
}
@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 {
String url = req.getRequestURI();
//得到上下文路径
String context = req.getContextPath();
//将上下文路径从路径中切掉
String path = url.replace(context,"");
//得到该方法
Method method = (Method) handerMap.get(path);
SupmainController instance = (SupmainController) beans.get("/"+path.split("/")[1]);
Object[] args = hand(req,resp,method);
try {
method.invoke(instance,args);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
private static Object[] hand(HttpServletRequest request,HttpServletResponse response,Method method){
//拿到当前执行的方法中有哪些参数
Class>[] paramClazzs = method.getParameterTypes();
// System.out.println("paramClazzs中的数据为:"+paramClazzs.toString());
//根据参数的个数,new 一个参数的数组,将方法里的所有参数赋值到args来
Object[] args = new Object[paramClazzs.length];
int args_i = 0;
int index = 0;
for (Class> paraClazz : paramClazzs){
System.out.println("paraClazz的数据为:"+paraClazz);
if (ServletRequest.class.isAssignableFrom(paraClazz)){
args[args_i++]=request;
}
if (ServletResponse.class.isAssignableFrom(paraClazz)){
args[args_i++]=response;
}
Annotation[] paramAns = method.getParameterAnnotations()[index];
if (paramAns.length>0){
for (Annotation paramAn:paramAns) {
if (SupmainRequestParamanno.class.isAssignableFrom(paramAn.getClass())) {
SupmainRequestParamanno requestParamanno = (SupmainRequestParamanno) paramAn;
args[args_i++] = request.getParameter(requestParamanno.value());
}
}
}
index++;
}
return args;
}
}
最后我的代码结构示意图是这样的,大家可以直接把代码按照我这样的结构拷贝过去,应该就可以使用了
如果本文章能够帮助到大家,我很开心!嘻嘻....