一、新建maven web项目
二、程序目录结构
Autowried注解
package org.lsh.mvcframe.annotation;
import java.lang.annotation.*;
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowried {
String value() default "";
}
Controller注解
package org.lsh.mvcframe.annotation;
import java.lang.annotation.*;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Controller {
String value() default "";
}
RequestMapping注解
package org.lsh.mvcframe.annotation;
import java.lang.annotation.*;
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestMapping {
String value() default "";
}
RequestParam注解
package org.lsh.mvcframe.annotation;
import java.lang.annotation.*;
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestParam {
String value();
}
Service注解
package org.lsh.mvcframe.annotation;
import java.lang.annotation.*;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Service {
String value() default "";
}
DispatcherServlet
package org.lsh.mvcframe.servlet;
import org.lsh.demo.controller.HelloController;
import org.lsh.mvcframe.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.*;
public class DispatcherServlet extends HttpServlet{
List classNames = new ArrayList();
Map beans= new HashMap();
Map handlerMap=new HashMap();
@Override
public void init(ServletConfig config){
scanPackage("org.lsh");
doInstance();
doIoc();
buildUrlMapping();
}
public void scanPackage(String packagePath){
//扫描编译好的类路径下的所有的类.class
URL url=this.getClass().getClassLoader().getResource("/"+packagePath.replaceAll("\\.","/"));
String fileStr=url.getFile();
File file=new File(fileStr);
String[] filesStr=file.list();
for (String path:filesStr){
File filePath =new File(fileStr+path);
if(filePath.isDirectory()){
scanPackage(packagePath+"."+path);
}else{
classNames.add(packagePath+"."+filePath.getName());
}
}
}
public void doInstance(){
if(classNames.size()<=0){
return;
}
for(String className:classNames){
String cn=className.replace(".class","");
try {
Class> clazz=Class.forName(cn);
if(clazz.isAnnotationPresent(Controller.class)){
Object instance=clazz.newInstance();
RequestMapping requestMapping=clazz.getAnnotation(RequestMapping.class);
String value=requestMapping.value();
beans.put(value,instance);
}else if(clazz.isAnnotationPresent(Service.class)){
Object instance=clazz.newInstance();
Service service=clazz.getAnnotation(Service.class);
String value=service.value();
beans.put(value, instance);
}else{
continue;
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
}
public void doIoc(){
if(beans.entrySet().size()<=0){
return;
}
for(Map.Entry entry:beans.entrySet()){
Object instance = entry.getValue();
Class> clazz = instance.getClass();
if (clazz.isAnnotationPresent(Controller.class)) {
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(Autowried.class)) {
Autowried autowried = field.getAnnotation(Autowried.class);
String value = autowried.value();
field.setAccessible(true);
try {
field.set(instance, beans.get(value));
} catch (IllegalAccessException e) {
e.printStackTrace();
}
} else {
continue;
}
}
} else {
continue;
}
}
}
public void buildUrlMapping(){
if(beans.entrySet().size()<=0){
return;
}
for(Map.Entry entry:beans.entrySet()){
Object instance = entry.getValue();
Class> clazz = instance.getClass();
if(clazz.isAnnotationPresent(Controller.class)){
RequestMapping requestMapping=entry.getValue().getClass().getAnnotation(RequestMapping.class);
String controllerPath=requestMapping.value();
Method[] methods =clazz.getMethods();
for (Method method: methods) {
if(method.isAnnotationPresent(RequestMapping.class)){
RequestMapping methodRequestMapping = method.getAnnotation(RequestMapping.class);
String methodPath=methodRequestMapping.value();
handlerMap.put(controllerPath+methodPath, method);
}else{
continue;
}
}
}else{
continue;
}
}
}
private static Object[] hand(HttpServletRequest request,HttpServletResponse response,Method method){
//拿到当前待执行的方法有哪些参数
Class>[] paramClazzs=method.getParameterTypes();
//根据参数的个数,new 一个参数数组,将方法里的所有参数赋值到args来
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++] =request;
}
if(ServletResponse.class.isAssignableFrom(paramClazz)){
args[args_i++] =response;
}
// 从0-3判断有没有RequestParam注解,很明显paramClazz为0和1时,不是,
//当为2和3时为@RequestParam,需要解析
Annotation[] paramAns=method.getParameterAnnotations()[index];
if(paramAns.length>0){
for (Annotation paramAn:paramAns){
if(RequestParam.class.isAssignableFrom(paramAn.getClass())){
RequestParam rp=(RequestParam) paramAn;
args[args_i++]=request.getParameter(rp.value());
}
}
}
index++;
}
return args;
}
@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();
String path=uri.replace(context,"");
Method method = (Method) handlerMap.get(path);
HelloController instance =(HelloController)beans.get("/"+path.split("/")[1]);
Object[] arg = hand(req, resp, method);
try {
method.invoke(instance,arg);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
HelloController
package org.lsh.demo.controller;
import org.lsh.mvcframe.annotation.Autowried;
import org.lsh.mvcframe.annotation.Controller;
import org.lsh.mvcframe.annotation.RequestMapping;
import org.lsh.mvcframe.annotation.RequestParam;
import org.lsh.demo.service.HelloService;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Controller
@RequestMapping("/hello")
public class HelloController {
@Autowried("helloService")
private HelloService helloService;
@RequestMapping("/login")
public void login(HttpServletRequest request, HttpServletResponse response,
@RequestParam("username") String username, @RequestParam("password") String password) throws IOException {
String result=helloService.sayHello("123","123");
response.getWriter().println(result);
}
}
HelloService
package org.lsh.demo.service;
public interface HelloService {
public String sayHello(String username,String password);
}
HelloServiceImpl
package org.lsh.demo.service.impl;
import org.lsh.mvcframe.annotation.Service;
import org.lsh.demo.service.HelloService;
@Service("helloService")
public class HelloServiceImpl implements HelloService{
public String sayHello(String username, String password) {
return "Hello,"+username;
}
}
web.xml
spring-mvc
DispatcherServlet
org.lsh.mvcframe.servlet.DispatcherServlet
0
DispatcherServlet
/*
pom.xml
4.0.0
war
springmvc
org.lsh
springmvc
1.0-SNAPSHOT
javax.servlet
javax.servlet-api
3.0.1
provided