最近看了挺多关于springmvc框架的文章和书籍,手写了一些springmvc的小deom,没有写适配器,废话不多说上源码
1.首先自定义注解
package com.ant.annotation;
import java.lang.annotation.*;
/***
*@Author : zeng
*@Date : 2018/8/30 1:38
**/
@Target({ElementType.FIELD}) //作用范围:用在成员变量上
@Retention(RetentionPolicy.RUNTIME) //注解会在class字节码文件中存在,在运行时可以通过反射获取到
@Documented //该注解将被包含在javadoc中 @Inherited:说明子类可以继承父类的注解
public @interface AntAutowired {
String value() default "";
}
package com.ant.annotation;
import java.lang.annotation.*;
/***
*@Author : zeng
*@Date : 2018/8/30 1:27
**/
@Target({ElementType.TYPE}) //作用范围:用在接口或类上
@Retention(RetentionPolicy.RUNTIME) //注解会在class字节码文件中存在,在运行时可以通过反射获取到
@Documented //该注解将被包含在javadoc中 @Inherited:说明子类可以继承父类的注解
public @interface AntController {
String value() default "";
}
package com.ant.annotation;
import java.lang.annotation.*;
/***
*@Author : zeng
*@Date : 2018/8/30 1:36
**/
@Target({ElementType.TYPE,ElementType.METHOD}) //作用范围:即可以用在类上也可以用在方法上面
@Retention(RetentionPolicy.RUNTIME) //注解会在class字节码文件中存在,在运行时可以通过反射获取到
@Documented //该注解将被包含在javadoc中 @Inherited:说明子类可以继承父类的注解
public @interface AntRequestMapper {
String value() default "";
}
package com.ant.annotation;
import java.lang.annotation.*;
/***
*@Author : zeng
*@Date : 2018/8/30 1:38
**/
@Target({ElementType.PARAMETER}) //作用范围:用在参数上
@Retention(RetentionPolicy.RUNTIME) //注解会在class字节码文件中存在,在运行时可以通过反射获取到
@Documented //该注解将被包含在javadoc中 @Inherited:说明子类可以继承父类的注解
public @interface AntRequestParam {
String value() default "";
}
package com.ant.annotation;
import java.lang.annotation.*;
/***
*@Author : zeng
*@Date : 2018/8/30 1:27
**/
@Target({ElementType.TYPE}) //作用范围:用在接口或类上
@Retention(RetentionPolicy.RUNTIME) //注解会在class字节码文件中存在,在运行时可以通过反射获取到
@Documented //该注解将被包含在javadoc中 @Inherited:说明子类可以继承父类的注解
public @interface AntService {
String value() default "";
}
代码中都有注释我就不过多解释了
2.web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>Archetype Created Web Application</display-name>
<!-- <load-on-startup>0</load-on-startup> 表示在Tomcat加载的时候会先去找到com.ant.servlet.DispacherServlet的init()方法初始化-->
<!--这个DispacherServlet是自定义的-->
<servlet>
<servlet-name>springMvc</servlet-name>
<servlet-class>com.ant.servlet.DispacherServlet</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springMvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
3.service和Controller
package com.ant.controller;
import com.ant.annotation.AntAutowired;
import com.ant.annotation.AntController;
import com.ant.annotation.AntRequestMapper;
import com.ant.annotation.AntRequestParam;
import com.ant.service.OrderService;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/***
*@Author : zeng
*@Date : 2018/8/30 1:33
**/
@AntController
@AntRequestMapper("/order")
public class OrderController {
@AntAutowired("/orderServiceImpl")
private OrderService orderService;
@AntRequestMapper("/insert")
public void insert(HttpServletRequest request, HttpServletResponse response,
@AntRequestParam("name")String name,
@AntRequestParam("age")String age) throws IOException {
String str = "aa";
PrintWriter pw = response.getWriter();
String result = orderService.insert(name,age);
System.out.println("name:"+name+" ------ "+age);
pw.write(result);
}
}
serviceImpl中没有写什么东西,我们只要能够接收到参数然后返回给页面就证明可以了
package com.ant.service.Impl;
import com.ant.annotation.AntService;
import com.ant.service.OrderService;
/***
*
*@Author : zeng
*@Date : 2018/8/30 1:23
*
**/
@AntService("/orderServiceImpl")
public class OrderServiceImpl implements OrderService {
public String insert(String name,String age) {
String result = name+age;
return result;
}
}
4.我们自定义的DispacherServlet,这里才是大头
package com.ant.servlet;
import com.ant.annotation.*;
import com.ant.controller.OrderController;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
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;
/***
*@Author : zeng
*@Date : 2018/8/30 1:52
**/
public class DispacherServlet extends HttpServlet {
private List<String> classNames = new ArrayList<String>();
private Map<String,Object> beans = new HashMap<String,Object>();
private Map<String,Object> handlerMap = new HashMap<String,Object>();
private Map<String,Object> methodparam = new HashMap<String, Object>();
/***
* 在Tomcat启动成功之前初始化bean
*/
public void init(ServletConfig config) {
//所有的待初始化创建对象的class扫描出来 com.ant.service.Imp.OrderServiceImpl
//1.扫描class
doScanPackage("com.ant");
//2.创建bean
doInstance();
//3.Autowired
doAutowired();
//4.URL映射
handlerMapper();
}
/***
* 1.扫描class
*/
private final void doScanPackage(String basePackage) {
//扫描编译好的类路径下面的所有类(替换斜杠为点 )
URL url = this.getClass().getClassLoader().getResource("/"+basePackage.replaceAll("\\.","/"));
//获取所有文件 D:/springboot/springmvc/com/...
String fileStr = url.getFile();
System.out.println("文件路径:"+fileStr);
File file = new File(fileStr);
String[] files = file.list();
//使用递归查询所有的class文件
for (String path : files) {
File filePath = new File(fileStr+path);
//判断是否是文件夹
if(filePath.isDirectory()){
//递归
doScanPackage(basePackage+"."+path);
}else{
//将类的全限定名存入集合
classNames.add(basePackage+"."+filePath.getName());
}
}
}
/***
* 2.创建bean
*/
private final void doInstance(){
//遍历所有找到的class创建实例对象(根据注解)
for (String className : classNames) {
//去除.class
String cn = className.replace(".class","");
System.out.println("集合路径:"+cn);
try {
Class<?> clazz = Class.forName(cn);
//判断类是否有注解
ok:if(clazz.isAnnotationPresent(AntController.class)){
Object instance = clazz.newInstance();
AntController controller = clazz.getAnnotation(AntController.class);
String key = controller.value();
if(key == null || key.equals("")){
break ok;
}
beans.put(key,instance);
} if(clazz.isAnnotationPresent(AntService.class)){
Object instance = clazz.newInstance();
AntService service = clazz.getAnnotation(AntService.class);
String key = service.value();
beans.put(key,instance);
} if(clazz.isAnnotationPresent(AntRequestMapper.class)){
Object instance = clazz.newInstance();
AntRequestMapper mapper = clazz.getAnnotation(AntRequestMapper.class);
String key = mapper.value();
beans.put(key,instance);
}else{
continue;
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
}
/***
* 3.Autowired
*/
private final void doAutowired() {
//获取Map中所有的注解
for (Map.Entry<String,Object> entry : beans.entrySet()){
//获取实例对象
Object instance = entry.getValue();
Class<?> clazz = instance.getClass();
if(clazz.isAnnotationPresent(AntController.class)){
//拿到所有成员变量
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields){
//判断是否有注解
if(field.isAnnotationPresent(AntAutowired.class)){
//拿到Autowired的value值
AntAutowired autowired = field.getAnnotation(AntAutowired.class);
//从Map获取value(可能报错)
String key = autowired.value();
Object obj = beans.get(key);
field.setAccessible(true);
try {
field.set(instance,obj);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}else{
continue;
}
}
}else{
continue;
}
}
}
/***
* 4.URL映射
*/
private final void handlerMapper() {
//获取路径
for (Map.Entry<String,Object> entry : beans.entrySet()) {
//获取实例对象
Object Instance = entry.getValue();
Class<?> clazz = Instance.getClass();
if (clazz.isAnnotationPresent(AntController.class)){
//获取AntController注解
AntController controller = clazz.getAnnotation(AntController.class);
String classPath = controller.value();
if(!classPath.equals("")){
getMethod(clazz,classPath);
}
}
if(clazz.isAnnotationPresent(AntRequestMapper.class)){
AntRequestMapper mapper = clazz.getAnnotation(AntRequestMapper.class);
String classPath = mapper.value();
if(!classPath.equals("")){
getMethod(clazz,classPath);
}
}else{
continue;
}
}
}
private void getMethod(Class clazz,String paths) {
//获取类里面的所有方法
Method[] methods = clazz.getMethods();
for (Method method : methods) {
if (method.isAnnotationPresent(AntRequestMapper.class)) {
AntRequestMapper methodMapper = method.getAnnotation(AntRequestMapper.class);
String methodPath = methodMapper.value();
String path = (paths == null ? "" : paths) + methodPath;
handlerMap.put(path, method);
methodparam.put(path,methodPath);
} else {
continue;
}
}
}
@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 uri = req.getRequestURI();
//获取项目名称
String context = req.getContextPath();
//只要/order/inser,不要项目名称
String path = uri.replaceAll(context,"");
//获取方法
Method method = (Method) handlerMap.get(path);
if(method == null){
throw new NullPointerException("请求方法不存在");
}
String splitParam = methodparam.get(path).toString();
OrderController instance = (OrderController) beans.get(path.replaceAll(splitParam,""));
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 req,HttpServletResponse rsp,Method method){
Class<?>[] paramClazzs = method.getParameterTypes();
//根据参数的个数,new 一个参数数组,将方法里所有的参数赋值进来
Object[] args = new Object[paramClazzs.length];
int args_i = 0;
int index = 0;
for (Class<?> paramClazz : paramClazzs){
if(ServletRequest.class.isAssignableFrom(paramClazz)){
args[args_i++] = req;
}
if(ServletRequest.class.isAssignableFrom(paramClazz)){
args[args_i++] = rsp;
}
Annotation[] annotations = method.getParameterAnnotations()[index];
if(annotations.length > 0 ){
for (Annotation annotation : annotations){
if(AntRequestParam.class.isAssignableFrom(annotation.getClass())){
AntRequestParam rp = (AntRequestParam) annotation;
args[args_i++] = req.getParameter(rp.value());
}
}
}
index++;
}
return args;
}
}
代码中都有解释,有什么写的不对的地方也请大家指出,一起进步。最后贴上项目的完整结构
有需要完整源码的可以找我QQ:1163449276