引入Pom文件
< 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. cy< / groupId>
< artifactId> cy_extspringmvc_day_20< / artifactId>
< version> 0.0 .1 - SNAPSHOT< / version>
< packaging> war< / packaging>
< dependencies>
< ! -- https: / / mvnrepository. com/ artifact/ javax. servlet/ javax. servlet- api -- >
< dependency>
< groupId> javax. servlet< / groupId>
< artifactId> javax. servlet- api< / artifactId>
< version> 3.1 .0 < / version>
< scope> provided< / scope>
< / dependency>
< ! -- https: / / mvnrepository. com/ artifact/ commons- lang/ commons- lang -- >
< dependency>
< groupId> commons- lang< / groupId>
< artifactId> commons- lang< / artifactId>
< version> 2.6 < / version>
< / dependency>
< / dependencies>
< / project>
自定义注解
@Target ( { ElementType. TYPE } )
@Retention ( RetentionPolicy. RUNTIME)
public @interface ExtController {
}
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
@Target ( { ElementType. METHOD, ElementType. TYPE } )
@Retention ( RetentionPolicy. RUNTIME)
public @interface ExtRequestMapping {
String value ( ) default "" ;
}
手写封装工具类
public class ClassUtil {
public static List< Class> getAllClassByInterface ( Class c ) {
List< Class> returnClassList = null;
if ( c. isInterface ( ) ) {
String packageName = c. getPackage ( ) . getName ( ) ;
List< Class< ? >> allClass = getClasses ( packageName) ;
if ( allClass != null) {
returnClassList = new ArrayList < Class> ( ) ;
for ( Class classes : allClass) {
if ( c. isAssignableFrom ( classes) ) {
if ( ! c. equals ( classes) ) {
returnClassList. add ( classes) ;
}
}
}
}
}
return returnClassList;
}
public static String[ ] getPackageAllClassName ( String classLocation, String packageName) {
String[ ] packagePathSplit = packageName. split ( "[.]" ) ;
String realClassLocation = classLocation;
int packageLength = packagePathSplit. length;
for ( int i = 0 ; i < packageLength; i++ ) {
realClassLocation = realClassLocation + File. separator + packagePathSplit[ i] ;
}
File packeageDir = new File ( realClassLocation) ;
if ( packeageDir. isDirectory ( ) ) {
String[ ] allClassName = packeageDir. list ( ) ;
return allClassName;
}
return null;
}
public static List< Class< ? >> getClasses ( String packageName) {
List< Class< ? >> classes = new ArrayList < Class< ? >> ( ) ;
boolean recursive = true ;
String packageDirName = packageName. replace ( '.' , '/' ) ;
Enumeration< URL> dirs;
try {
dirs = Thread. currentThread ( ) . getContextClassLoader ( ) . getResources ( packageDirName) ;
while ( dirs. hasMoreElements ( ) ) {
URL url = dirs. nextElement ( ) ;
String protocol = url. getProtocol ( ) ;
if ( "file" . equals ( protocol) ) {
String filePath = URLDecoder. decode ( url. getFile ( ) , "UTF-8" ) ;
findAndAddClassesInPackageByFile ( packageName, filePath, recursive, classes) ;
} else if ( "jar" . equals ( protocol) ) {
JarFile jar;
try {
jar = ( ( JarURLConnection) url. openConnection ( ) ) . getJarFile ( ) ;
Enumeration< JarEntry> entries = jar. entries ( ) ;
while ( entries. hasMoreElements ( ) ) {
JarEntry entry = entries. nextElement ( ) ;
String name = entry. getName ( ) ;
if ( name. charAt ( 0 ) == '/' ) {
name = name. substring ( 1 ) ;
}
if ( name. startsWith ( packageDirName) ) {
int idx = name. lastIndexOf ( '/' ) ;
if ( idx != - 1 ) {
packageName = name. substring ( 0 , idx) . replace ( '/' , '.' ) ;
}
if ( ( idx != - 1 ) || recursive) {
if ( name. endsWith ( ".class" ) && ! entry. isDirectory ( ) ) {
String className = name. substring ( packageName. length ( ) + 1 , name. length ( ) - 6 ) ;
try {
classes. add ( Class. forName ( packageName + '.' + className) ) ;
} catch ( ClassNotFoundException e) {
e. printStackTrace ( ) ;
}
}
}
}
}
} catch ( IOException e) {
e. printStackTrace ( ) ;
}
}
}
} catch ( IOException e) {
e. printStackTrace ( ) ;
}
return classes;
}
public static void findAndAddClassesInPackageByFile ( String packageName, String packagePath, final boolean recursive,
List< Class< ? >> classes) {
File dir = new File ( packagePath) ;
if ( ! dir. exists ( ) || ! dir. isDirectory ( ) ) {
return ;
}
File[ ] dirfiles = dir. listFiles ( new FileFilter ( ) {
public boolean accept ( File file) {
return ( recursive && file. isDirectory ( ) ) || ( file. getName ( ) . endsWith ( ".class" ) ) ;
}
} ) ;
for ( File file : dirfiles) {
if ( file. isDirectory ( ) ) {
findAndAddClassesInPackageByFile ( packageName + "." + file. getName ( ) , file. getAbsolutePath ( ) , recursive,
classes) ;
} else {
String className = file. getName ( ) . substring ( 0 , file. getName ( ) . length ( ) - 6 ) ;
try {
classes. add ( Class. forName ( packageName + '.' + className) ) ;
} catch ( ClassNotFoundException e) {
e. printStackTrace ( ) ;
}
}
}
}
public static String toLowerCaseFirstOne ( String s) {
if ( Character. isLowerCase ( s. charAt ( 0 ) ) )
return s;
else
return ( new StringBuilder ( ) ) . append ( Character. toLowerCase ( s. charAt ( 0 ) ) ) . append ( s. substring ( 1 ) ) . toString ( ) ;
}
public static Object newInstance ( Class< ? > classInfo)
throws ClassNotFoundException, InstantiationException, IllegalAccessException {
return classInfo. newInstance ( ) ;
}
}
模拟Controller层
@ExtController
@ExtRequestMapping ( "/ext" )
public class ExtIndexController {
@ExtRequestMapping ( "/test" )
public String test ( String name, Integer age) {
System. out. println ( "手写springmvc框架..." ) ;
return "index" ;
}
}
准备静态资源
< % @ page language= "java" contentType= "text/html; charset=UTF-8"
pageEncoding= "UTF-8" % >
< ! DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" >
< html>
< head>
< meta http- equiv= "Content-Type" content= "text/html; charset=UTF-8" >
< title> Insert title here< / title>
< / head>
< body>
< h1> 这是我第一次手写springmvc. . . . . </ h1>
< / body>
< / html>
手写Web项目入口–Web.xml配置springmvc核心转发器
< ? xml version= "1.0" encoding= "UTF-8" ? >
< web- app 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/web-app_2_4.xsd"
version= "2.4" >
< ! -- Spring MVC 核心控制器 DispatcherServlet 配置 -- >
< servlet>
< servlet- name> dispatcher< / servlet- name>
< servlet- class > com. cy. ext. springmvc. servlet. ExtDispatcherServlet
< / servlet- class >
< load- on- startup> 1 < / load- on- startup>
< / servlet>
< servlet- mapping>
< servlet- name> dispatcher< / servlet- name>
< ! -- 拦截所有
public class ExtDispatcherServlet extends HttpServlet {
private ConcurrentHashMap< String, Object> springmvcBeans = new ConcurrentHashMap < String, Object> ( ) ;
private ConcurrentHashMap< String, Object> urlBeans = new ConcurrentHashMap < String, Object> ( ) ;
private ConcurrentHashMap< String, String> urlMethods = new ConcurrentHashMap < String, String> ( ) ;
@Override
public void init ( ) throws ServletException {
List< Class< ? >> classes = ClassUtil. getClasses ( "com.cy.controller" ) ;
try {
findClassMVCAnnotation ( classes) ;
} catch ( Exception e) {
}
handlerMapping ( ) ;
}
@Override
protected void doGet ( HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost ( req, resp) ;
}
@Override
protected void doPost ( HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String requestURI = req. getRequestURI ( ) ;
if ( StringUtils. isEmpty ( requestURI) ) {
return ;
}
Object object = urlBeans. get ( requestURI) ;
if ( object == null) {
resp. getWriter ( ) . println ( " not found 404 url" ) ;
return ;
}
String methodName = urlMethods. get ( requestURI) ;
if ( StringUtils. isEmpty ( methodName) ) {
resp. getWriter ( ) . println ( " not found method" ) ;
}
String resultPage = ( String) methodInvoke ( object, methodName) ;
extResourceViewResolver ( resultPage, req, resp) ;
}
private void extResourceViewResolver ( String pageName, HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
String prefix = "/" ;
String suffix = ".jsp" ;
req. getRequestDispatcher ( prefix + pageName + suffix) . forward ( req, res) ;
}
private Object methodInvoke ( Object object, String methodName) {
try {
Class< ? extends Object > classInfo = object. getClass ( ) ;
Method method = classInfo. getMethod ( methodName) ;
Object result = method. invoke ( object) ;
return result;
} catch ( Exception e) {
return null;
}
}
public void findClassMVCAnnotation ( List< Class< ? >> classes)
throws ClassNotFoundException, InstantiationException, IllegalAccessException {
for ( Class< ? > classInfo : classes) {
ExtController extController = classInfo. getDeclaredAnnotation ( ExtController. class ) ;
if ( extController != null) {
String beanId = ClassUtil. toLowerCaseFirstOne ( classInfo. getSimpleName ( ) ) ;
Object object = ClassUtil. newInstance ( classInfo) ;
springmvcBeans. put ( beanId, object) ;
}
}
}
public void handlerMapping ( ) {
for ( Map. Entry< String, Object> mvcBean : springmvcBeans. entrySet ( ) ) {
Object object = mvcBean. getValue ( ) ;
Class< ? extends Object > classInfo = object. getClass ( ) ;
ExtRequestMapping declaredAnnotation = classInfo. getDeclaredAnnotation ( ExtRequestMapping. class ) ;
String baseUrl = "" ;
if ( declaredAnnotation != null) {
baseUrl = declaredAnnotation. value ( ) ;
}
Method[ ] declaredMethods = classInfo. getDeclaredMethods ( ) ;
for ( Method method : declaredMethods) {
ExtRequestMapping methodExtRequestMapping = method. getDeclaredAnnotation ( ExtRequestMapping. class ) ;
if ( methodExtRequestMapping != null) {
String methodUrl = baseUrl + methodExtRequestMapping. value ( ) ;
urlBeans. put ( methodUrl, object) ;
urlMethods. put ( methodUrl, method. getName ( ) ) ;
}
}
}
}
}
以上完成了简易的SpringMVC框架 实现@Controller和@RequestMapping 不过在带参数传递时需要修改
private ConcurrentHashMap<String, String> urlMethods-->private ConcurrentHashMap<String, ConcurrentHashMap<<String, Object>>> urlMethods,再进行封装一次才能完成