一、新建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<String> classNames = new ArrayList<String>();
Map<String,Object> beans= new HashMap<String,Object>();
Map<String,Object> handlerMap=new HashMap<String,Object>();
@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<String,Object> 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<String,Object> 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
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>spring-mvc</display-name>
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.lsh.mvcframe.servlet.DispatcherServlet</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>war</packaging>
<name>springmvc</name>
<groupId>org.lsh</groupId>
<artifactId>springmvc</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>