简化版SpringMVC

简化版SpringMVC

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>Web Application</display-name>

<servlet>

<servlet-name>mvc</servlet-name>

<servlet-class>com.aop.mvc.action.DispatcherServlet</servlet-class>

<init-param>

<param-name>contextConfigLocation</param-name>

<param-value>application.properties</param-value>

</init-param>

<load-on-startup>1</load-on-startup>

</servlet>

<servlet-mapping>

<servlet-name>mvc</servlet-name>

<url-pattern>/*</url-pattern>

</servlet-mapping>

</web-app>

pom.xml

<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/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<groupId>com.aop.demo</groupId>

<artifactId>SpringAop-Demo</artifactId>

<version>0.0.1-SNAPSHOT</version>

<packaging>jar</packaging>

<name>SpringAop-Demo</name>

<url>http://maven.apache.org</url>

<properties>

<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

</properties>

<dependencies>

<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

<version>3.8.1</version>

<scope>test</scope>

</dependency>

<dependency>

<groupId>javax.servlet</groupId>

<artifactId>servlet-api</artifactId>

<version>2.4</version>

<scope>provided</scope>

</dependency>

</dependencies>

<build>

<finalName>${artifactId}</finalName>

<resources>

<resource>

<directory>${basedir}/src/main/resources</directory>

<includes>

<include>**/*</include>

</includes>

</resource>

<resource>

<directory>${basedir}/src/main/java</directory>

<excludes>

<exclude>**/*.java</exclude>

<exclude>**/*.class</exclude>

</excludes>

</resource>

</resources>

</build>

</project>

application.properties

scanPackage=com.aop.mvc

com.aop.mvc.annotaion

import java.lang.annotation.Documented;

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

@Target({ ElementType.FIELD })

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface AutoWirted {

String value() default "";

}

@Target({ ElementType.TYPE })

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface Controller {

String value() default "";

}

@Target({ ElementType.TYPE, ElementType.METHOD })

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface RequestMapping {

String value() default "";

}

@Target({ ElementType.PARAMETER })

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface RequestParam {

String value() default "";

}

@Target({ ElementType.TYPE })

@Retention(RetentionPolicy.RUNTIME)

@Documented

public @interface Service {

String value() default "";

}

DemoService.java

package com.aop.mvc.servlet.impl;

import com.aop.mvc.annotaion.Service;

import com.aop.mvc.servlet.IDemoService;

@ Service

public class DemoService implements IDemoService {

public String get (String name) {

return "My name is " + name;

}

}

package com.aop.mvc.servlet;

public interface IDemoService {

String get(String name);

}

DispatcherServlet.java

package com.aop.mvc.action;

import java.io.File;

import java.io.IOException;

import java.io.InputStream;

import java.lang.reflect.Field;

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;

import java.util.Map.Entry;

import java.util.Properties;

import javax.servlet.ServletConfig;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import com.aop.mvc.annotaion.AutoWirted;

import com.aop.mvc.annotaion.Controller;

import com.aop.mvc.annotaion.RequestMapping;

import com.aop.mvc.annotaion.Service;

public class DispatcherServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

/** 资源文件 */

private Properties contextConfig = new Properties();

/** 扫描到的所有类 */

private List<String> classNames = new ArrayList<String>();

/** 实例化类集合 */

private Map<String, Object> ioc = new HashMap<String, Object>();

/** url ==> 优化:List handlerMapping */

private Map<String, Method> handlerMapping = new HashMap<String, Method>();

@ 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 {

try {

// 6.等待请求

doDispatch(req, resp);

} catch (Exception e ) {

e.printStackTrace();

}

}

private void doDispatch (HttpServletRequest req, HttpServletResponse resp) throws Exception {

String url = req.getRequestURI();

String contextPath = req.getContextPath();

url = url.replace(contextPath, "").replaceAll("/+", "/");

// 判读HandlerMapping中有返回调用, 没有就404

if (!handlerMapping.containsKey(url)) {

resp.getWriter().write("404 Not Found!");

return ;

}

Method me = handlerMapping.get(url);

// me.invoke(req.getParameterMap(), ???);

System .out .println(me);

}

@ Override

public void init (ServletConfig config) throws ServletException {

System .out .println("======================Begin========================");

// 1.加载配置文件

doLoadConfig(config.getInitParameter("contextConfigLocation"));

// 2.扫描到所有的相关类

doScanner(contextConfig.getProperty("scanPackage"));

// 3.初始化刚刚扫描到的类

doInstance();

// 4.实现依赖注入

doAutowired();

// 5.初始化HadlerMapping

initHandlerMapping();

System .out .println("=============== Spring is init OK!");

}

private void initHandlerMapping () {

if (ioc.isEmpty())

return ;

// 对Controller进行处理

for (Entry<String, Object> entry : ioc.entrySet()) {

Class clazz = entry.getValue().getClass();

// 判断有没有加@Controller注解的

if (!clazz.isAnnotationPresent(Controller .class ))

continue ;

String baseUtl = "";

if (clazz.isAnnotationPresent(RequestMapping .class )) {

RequestMapping requestParam = clazz.getAnnotation(RequestMapping .class );

baseUtl = requestParam.value();

}

Method [] method = clazz.getMethods();

for (Method meth : method) {

if (meth.isAnnotationPresent(RequestMapping .class )) {

RequestMapping requestParam = meth.getAnnotation(RequestMapping .class );

String url = requestParam.value();

url = (baseUtl + url);

handlerMapping.put(url, meth);

System .out .println("Mapped:" + url + "," + method);

}

}

}

}

private void doAutowired () {

if (ioc.isEmpty())

return ;

for (Entry<String, Object> entry : ioc.entrySet()) {

Field [] fields = entry.getValue().getClass().getDeclaredFields();

for (Field field : fields) {

// 授权, 只要加了Autowired的

if (!field.isAnnotationPresent(AutoWirted .class ))

continue ;

AutoWirted autoWirted = field.getAnnotation(AutoWirted .class );

String beanName = autoWirted.value().trim();

if ("".equals(beanName)) {

beanName = field.getType().getName();

}

// 执行强制授权

field.setAccessible(true );

// 进行赋值操作

try {

field.set(entry.getValue(), ioc.get(beanName));

} catch (Exception e ) {

e.printStackTrace();

continue ;

}

}

}

}

private void doInstance () {

// 将扫描到的类初始化

if (classNames.isEmpty())

return ;

// 通过反射初始化

try {

for (String className : classNames) {

Class clazz = Class .forName (className);

// 有注解的类初始化

if (clazz.isAnnotationPresent(Controller .class )) {

Object obj = clazz.newInstance();

// 初始化后放入ioc容器中

// 默认是类名的首字母小写

String beanName = lowerFirstCase(clazz.getSimpleName());

ioc.put(beanName, obj);

} else if (clazz.isAnnotationPresent(Service .class )) {

// 1.默认首字母小写

// 2.如果是接口, 要把他的实现类赋值给它

// 3.如果自定义,就优先用自定义的名字

Service service = clazz.getAnnotation(Service .class );

String beanName = service.value();

if ("".equals(beanName.trim())) {

// 如果自定义名字为空,取默认值

beanName = lowerFirstCase(clazz.getSimpleName());

}

Object instance = clazz.newInstance();

ioc.put(beanName, instance);

// 解决子类引用赋值父类的问题

Class [] interfaces = clazz.getInterfaces();

for (Class i : interfaces) {

ioc.put(i.getName(), instance);

}

} else {

continue ;

}

}

} catch (Exception e ) {

e.printStackTrace();

}

}

private void doScanner (String scanPackage) {

URL url = this .getClass().getClassLoader().getResource("/" + scanPackage.replaceAll("\\.", "/"));

File classDir = new File(url.getFile());

// 递归扫描指定文件下的类

for (File file : classDir.listFiles()) {

if (file.isDirectory()) {// 判断是否文件夹

doScanner(scanPackage + "." + file.getName());

} else {// 如果不是文件夹

String className = scanPackage + "." + file.getName().replace(".class", "");

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 (null != is) {

try {

is.close();

} catch (IOException e ) {

e.printStackTrace();

}

}

}

}

/** 自定义首字母小写 */

private String lowerFirstCase (String str) {

char [] chars = str.toCharArray();

chars[0] += 32;

return String .valueOf (chars);

}

}

DemoAction.java

package com.aop.mvc.action;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import com.aop.mvc.annotaion.AutoWirted;

import com.aop.mvc.annotaion.Controller;

import com.aop.mvc.annotaion.RequestMapping;

import com.aop.mvc.annotaion.RequestParam;

import com.aop.mvc.servlet.IDemoService;

/**

* @Theme 纯手写实现SpringMVC

* @author http://localhost:8080/SpringAop-Demo/demo/query.json

*/

@Controller

@ RequestMapping ("/demo")

public class DemoAction {

@AutoWirted

private IDemoService demoService;

@ RequestMapping ("/query.json")

public void query (HttpServletRequest req, HttpServletResponse resp, @RequestParam ("name") String name) {

String result = demoService.get(name);

try {

resp.getWriter().write(result);

} catch (Exception e ) {

// TODO : handle exception

}

}

@ RequestMapping ("/add.json")

public void add (HttpServletRequest req, HttpServletResponse resp, @RequestParam ("a") Integer a, @RequestParam ("b") Integer b) {

try {

resp.getWriter().write(a + "+" + b + "=" + (a + b));

} catch (Exception e ) {

// TODO : handle exception

}

}

@ RequestMapping ("/remove.json")

public void remove (HttpServletRequest req, HttpServletResponse resp, @RequestParam ("id") Integer id) {

try {

} catch (Exception e ) {

// TODO : handle exception

}

}

}

相关推荐
喵叔哟17 分钟前
重构代码中引入外部方法和引入本地扩展的区别
java·开发语言·重构
尘浮生23 分钟前
Java项目实战II基于微信小程序的电影院买票选座系统(开发文档+数据库+源码)
java·开发语言·数据库·微信小程序·小程序·maven·intellij-idea
不是二师兄的八戒1 小时前
本地 PHP 和 Java 开发环境 Docker 化与配置开机自启
java·docker·php
爱编程的小生1 小时前
Easyexcel(2-文件读取)
java·excel
带多刺的玫瑰1 小时前
Leecode刷题C语言之统计不是特殊数字的数字数量
java·c语言·算法
计算机毕设指导62 小时前
基于 SpringBoot 的作业管理系统【附源码】
java·vue.js·spring boot·后端·mysql·spring·intellij-idea
Gu Gu Study2 小时前
枚举与lambda表达式,枚举实现单例模式为什么是安全的,lambda表达式与函数式接口的小九九~
java·开发语言
Chris _data2 小时前
二叉树oj题解析
java·数据结构
牙牙7052 小时前
Centos7安装Jenkins脚本一键部署
java·servlet·jenkins
paopaokaka_luck2 小时前
[371]基于springboot的高校实习管理系统
java·spring boot·后端