1.四大注解的定义
(1)Controller注解:该注解使用在一个类上面,参数为value,值为访问该controller的名称,默认为空,如果为空
则值为该controller类名的首字母小写的值。代码如下:

  1. @Documented
  2. @Target(ElementType.TYPE)
  3. @Inherited
  4. @Retention(RetentionPolicy.RUNTIME)
  5. public @interface Controller {
  6. String value() default "";
  7. }

(2)Service注解:该注解使用在一个类上面(使用在接口的实现类上面),参数为value,值为该service的名称。默认为空,
如果为空则值为该service的类名的首字母小写的值。代码如下:

  1. @Documented
  2. @Inherited
  3. @Target(ElementType.TYPE)
  4. @Retention(RetentionPolicy.RUNTIME)
  5. public @interface Service {
  6. String value() default "";
  7. }

(3)RequestMapping注解:该注解定义使用在一个方法上面,参数为value,值为该方法的访问名称,默认为空,如果
为空,则值为该方法的方法名首字母小写的值。代码如下:

  1. @Documented
  2. @Inherited
  3. @Target(ElementType.METHOD)
  4. @Retention(RetentionPolicy.RUNTIME)
  5. public @interface RequestMapping {
  6. String value() default "";
  7. }

(4)Autowired注解:该注解定义使用到类的成员变量上面,没有参数,表示该变量字段注入值。代码如下:

  1. @Documented
  2. @Inherited
  3. @Target(ElementType.FIELD)
  4. @Retention(RetentionPolicy.RUNTIME)
  5. public @interface Autowired {
  6.  
  7. }

2.包扫描方法说明
当我们获取到一个指定的包名时,我们要去获取该包路径下面的所有文件,如果该文件为文件夹,在递归调用该方法,直到
获取到指定包路径下面的所有文件,判读文件是否以class结尾,如果文件以class结尾,则将该文件的完整路径(包名+文件名)
保存到list中。
(1)先将包名中的所以有"."替换为"/",得到包的路径。

  1. private String replacePackageName(String packageName){
  2. return packageName.replaceAll("\\.", "/");
  3. }

(2)递归调用扫描方法,获取所有文件。

  1. private void scanPackage(String packageName){
  2. //替换包名中的 .
  3. String packageName1 = replacePackageName(packageName);
  4. //获取当前的统一资源定位符
  5. URL url = this.getClass().getClassLoader().getResource(packageName1);
  6. //获取此URL的文件名
  7. String pathFile= url.getFile();
  8. //通过将给定路径名字符串转换成抽象路径名来创建一个新 File 实例
  9. File file = new File(pathFile);
  10. //返回由此抽象路径名所表示的目录中的文件和目录的名称所组成字符串数组。
  11. String[] files = file.list();
  12. for(String filePath : files){
  13. //根据目录名称和文件名称创建新的File对象
  14. File eachFile = new File(pathFile+"/"+filePath);
  15. if(eachFile.isDirectory()){
  16. //如果为文件夹,则将新的名称作为包名,再次调用该方法。
  17. scanPackage(packageName+"."+eachFile.getName());
  18. }else{
  19. //判断文件的扩展名是否为class,如果是,则将该文件的包名和文件名一起保存到集合中。
  20. if(getFileExtendName(eachFile.getName()).equals("class"))
  21. packageNames.add(packageName+"."+eachFile.getName());
  22. continue;
  23. }
  24. }
  25. }
  1. private String getFileExtendName(String fileName){
  2. //判断传入的文件名是否为空,或者长度是否小于等于0
  3. if(fileName == null ||fileName.length() <=0)
  4. return null;
  5. //获取文件中最后一个 . 出现的地方的下标
  6. int lastIndex = fileName.lastIndexOf(".");
  7. //判断下标是否为正常的值
  8. if(lastIndex > -1 && lastIndex <(fileName.length()-1))
  9. //截取文件的扩展名
  10. return fileName.substring(lastIndex+1);
  11. return fileName;
  12. }

3.实例化第二步扫描到的所有类中配有controller和service注解的类

  1. private void saveClass() throws Exception{
  2. //判断集合是否为空
  3. if(packageNames.size() <=0){
  4. return;
  5. }
  6. for(String pkn:packageNames){
  7. //根据类的全限定名通过反射获取指定类的class对象
  8. Class<?> object = Class.forName(pkn.replace(".class", "").trim());
  9. //判断该类是否有controller注解
  10. if(object.isAnnotationPresent(Controller.class)){
  11. //实例化该class的类对象
  12. Object instance = object.newInstance();
  13. //获取controller注解的对象
  14. Controller controller = object.getAnnotation(Controller.class);
  15. //获取该注解的参数的值
  16. String key = controller.value();
  17. //判断注解的值是否为空
  18. if(key.equals("")){
  19. //获取该类的类名首字母小写作为值。
  20. key=object.getSimpleName().substring(0, 1).toLowerCase()+object.getSimpleName().substring(1);
  21. }
  22. //将类的名称和类的实例放到map对象中
  23. classMap.put(key, instance);
  24. //判断该对象是否有service注解
  25. }else if(object.isAnnotationPresent(Service.class)){
  26. //获取该类的实例
  27. Object instance = object.newInstance();
  28. //获取service的对象实例
  29. Service service = object.getAnnotation(Service.class);
  30. //获取注解的值
  31. String key = service.value();
  32. //判断注解的值是否为空
  33. if(key.equals("")){
  34. //获取该类的类名首字母小写作为值。
  35. key=object.getSimpleName().substring(0, 1).toLowerCase()+object.getSimpleName().substring(1);
  36. }
  37. //将类的名称和类的实例放到map对象中
  38. classMap.put(key, instance);
  39. }else{
  40. continue;
  41. }
  42. }
  43. }

4.根据所有的类对象获取方法

  1. private void handlerMap(){
  2. //判断类的集合是否为空
  3. if(classMap.size() <=0){
  4. return;
  5. }
  6. //遍历该map对象
  7. for (Map.Entry<String,Object> entry : classMap.entrySet()) {
  8. //获取该类是否有controller注解
  9. if(entry.getValue().getClass().isAnnotationPresent(Controller.class)){
  10. //获取controller注解对象
  11. Controller controller = entry.getValue().getClass().getAnnotation(Controller.class);
  12. //获取controller注解的值
  13. String value = controller.value();
  14. //判断注解的值是否为空
  15. if(value.equals("")){
  16. //获取该类的类名首字母小写作为值。
  17. value=entry.getValue().getClass().getSimpleName().substring(0, 1).toLowerCase()+entry.getValue().getClass().getSimpleName().substring(1);
  18. }
  19. //反射获取该类下面的所有方法
  20. Method[] methods = entry.getValue().getClass().getMethods();
  21. for (Method method : methods) {
  22. //判断该方法是否有RequestMapping注解
  23. if(method.isAnnotationPresent(RequestMapping.class)){
  24. //获取RequestMapping对象
  25. RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
  26. //获取注解的值
  27. String rvalue = requestMapping.value();
  28. //判断注解的值是否为空
  29. if(rvalue.equals("")){
  30. //获取该类的类名首字母小写作为值。
  31. rvalue=method.getClass().getSimpleName().substring(0, 1).toLowerCase()+method.getClass().getSimpleName().substring(1);
  32. }
  33. //将controller的名称和方法的名称保存到集合中
  34. methodMap.put("/"+value+rvalue, method);
  35. }else{
  36. continue;
  37. }
  38. }
  39. }else{
  40. continue;
  41. }
  42. }
  43. }

5.实例化类中的有Autowired注解的成员变量

  1. private void ioc(){
  2. //判断集合是否为空
  3. if(classMap.size() <=0){
  4. return;
  5. }
  6. //变量所有的类
  7. for (Map.Entry<String, Object> entry : classMap.entrySet()) {
  8. //获取本类下面所有的成员变量
  9. Field[] fileds =entry.getValue().getClass().getDeclaredFields();
  10. for (Field field : fileds) {
  11. //设置该成员变量可以编辑
  12. field.setAccessible(true);
  13. //判断该成员对象是否有Autowired注解
  14. if(field.isAnnotationPresent(Autowired.class)){
  15. try {
  16. //设置该成员变量可以编辑
  17. field.setAccessible(true);
  18. //获取包名
  19. String packString= field.getType().getPackage().getName();
  20. //获取实现类的类名
  21. String className= field.getType().getSimpleName()+"Impl";
  22. //反射该类对象
  23. Class<?> obj = Class.forName(packString+".impl."+className);
  24. String value="";
  25. //判断该类是否有controller注解
  26. if(obj.isAnnotationPresent(Controller.class)){
  27. //获取controller的值
  28. value= obj.getAnnotation(Controller.class).value();
  29. if(value.equals("")){
  30. //获取该类的类名首字母小写作为值。
  31. value=obj.getSimpleName().substring(0, 1).toLowerCase()+obj.getSimpleName().substring(1);
  32. }
  33. //判断该类是否有service注解
  34. }else if(obj.isAnnotationPresent(Service.class)){
  35. //获取service的值
  36. value= obj.getAnnotation(Service.class).value();
  37. if(value.equals("")){
  38. //获取该类的类名首字母小写作为值。
  39. value=obj.getSimpleName().substring(0, 1).toLowerCase()+obj.getSimpleName().substring(1);
  40. }
  41. }
  42. //给成员变量赋值实例
  43. field.set(entry.getValue(), classMap.get(value));
  44. } catch (IllegalArgumentException | IllegalAccessException | ClassNotFoundException e) {
  45. e.printStackTrace();
  46. }
  47. }
  48. }
  49. }
  50. }

6.写前端控制器
前端控制器是一个servlet,所有的路径访问都提交到该servlet,由该servlet负责转发。在该servlet的初始化init方法中执行上面步骤。
然后在post方法中拦截请求。获取地址,进行转发。

  1. private void ioc(){
  2. //判断集合是否为空
  3. if(classMap.size() <=0){
  4. return;
  5. }
  6. //变量所有的类
  7. for (Map.Entry<String, Object> entry : classMap.entrySet()) {
  8. //获取本类下面所有的成员变量
  9. Field[] fileds =entry.getValue().getClass().getDeclaredFields();
  10. for (Field field : fileds) {
  11. //设置该成员变量可以编辑
  12. field.setAccessible(true);
  13. //判断该成员对象是否有Autowired注解
  14. if(field.isAnnotationPresent(Autowired.class)){
  15. try {
  16. //设置该成员变量可以编辑
  17. field.setAccessible(true);
  18. //获取包名
  19. String packString= field.getType().getPackage().getName();
  20. //获取实现类的类名
  21. String className= field.getType().getSimpleName()+"Impl";
  22. //反射该类对象
  23. Class<?> obj = Class.forName(packString+".impl."+className);
  24. String value="";
  25. //判断该类是否有controller注解
  26. if(obj.isAnnotationPresent(Controller.class)){
  27. //获取controller的值
  28. value= obj.getAnnotation(Controller.class).value();
  29. if(value.equals("")){
  30. //获取该类的类名首字母小写作为值。
  31. value=obj.getSimpleName().substring(0, 1).toLowerCase()+obj.getSimpleName().substring(1);
  32. }
  33. //判断该类是否有service注解
  34. }else if(obj.isAnnotationPresent(Service.class)){
  35. //获取service的值
  36. value= obj.getAnnotation(Service.class).value();
  37. if(value.equals("")){
  38. //获取该类的类名首字母小写作为值。
  39. value=obj.getSimpleName().substring(0, 1).toLowerCase()+obj.getSimpleName().substring(1);
  40. }
  41. }
  42. //给成员变量赋值实例
  43. field.set(entry.getValue(), classMap.get(value));
  44. } catch (IllegalArgumentException | IllegalAccessException | ClassNotFoundException e) {
  45. e.printStackTrace();
  46. }
  47. }
  48. }
  49. }
  50. }

7.配置web.xml文件

  1. <servlet>
  2. <servlet-name>dispatcherServlet</servlet-name>
  3. <servlet-class>com.jack.servlet.DispatcherServlet</servlet-class>
  4. <init-param>
  5. <param-name>configxml</param-name>
  6. <param-value>com/jack/test/minimvc.xml</param-value>
  7. </init-param>
  8. <load-on-startup>0</load-on-startup>
  9. </servlet>
  10. <servlet-mapping>
  11. <servlet-name>dispatcherServlet</servlet-name>
  12. <url-pattern>/</url-pattern>
  13. </servlet-mapping>

SpringMvc注解开发的更多相关文章

  1. SpringMVC注解开发初步

    一.(补充)视图解析器---XmlViewResolver 作用:分离配置信息. 在视图解析器---BeanNameViewResolver的基础之上进行扩充,新建一个myView.xml分离信息 在 ...

  2. Spring+SpringMVC+MyBatis深入学习及搭建(十六)——SpringMVC注解开发(高级篇)

    转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/7085268.html 前面讲到:Spring+SpringMVC+MyBatis深入学习及搭建(十五)——S ...

  3. springmvc学习笔记(13)-springmvc注解开发之集合类型參数绑定

    springmvc学习笔记(13)-springmvc注解开发之集合类型參数绑定 标签: springmvc springmvc学习笔记13-springmvc注解开发之集合类型參数绑定 数组绑定 需 ...

  4. springmvc学习笔记(12)-springmvc注解开发之包装类型參数绑定

    springmvc学习笔记(12)-springmvc注解开发之包装类型參数绑定 标签: springmvc springmvc学习笔记12-springmvc注解开发之包装类型參数绑定 需求 实现方 ...

  5. springmvc学习笔记(10)-springmvc注解开发之商品改动功能

    springmvc学习笔记(10)-springmvc注解开发之商品改动功能 标签: springmvc springmvc学习笔记10-springmvc注解开发之商品改动功能 需求 开发mappe ...

  6. Spring+SpringMVC+MyBatis深入学习及搭建(十五)——SpringMVC注解开发(基础篇)

    转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/7065294.html 前面讲到:Spring+SpringMVC+MyBatis深入学习及搭建(十四)--S ...

  7. 2.SpringMVC注解开发

    1.创建SpringMVC项目 配置web.xml <?xml version="1.0" encoding="UTF-8"?> <web-a ...

  8. springMVC注解初步

    一.(补充)视图解析器---XmlViewResolver 作用:分离配置信息. 在视图解析器---BeanNameViewResolver的基础之上进行扩充,新建一个myView.xml分离信息 在 ...

  9. SpringMVC-Mybatis整合和注解开发

    SpringMVC-Mybatis整合和注解开发SpringMVC-Mybatis整合整合的思路在mybatis和spring整合的基础上 添加springmvc.spring要管理springmvc ...

随机推荐

  1. CentOS系统安装遇到的一些问题

    Vi操作:按ESC键 跳到命令模式,然后: :w 保存文件但不退出vi:w file 将修改另外保存到file中,不退出vi:w! 强制保存,不推出vi:wq 保存文件并退出vi:wq! 强制保存文件 ...

  2. 如何使用linq读取DataTable集合?AsQueryable() 和 AsEnumerable()区别?

    一.准备工作 引入linq和data 相关的using命名空间 DataTable dt=new DataTable();//dt的来源可以是多个地方,比如:数据库,Excel等等.我这里使用Exce ...

  3. ADO.NET系列之Command对象

    ADO.NET系列之Connection对象 ADO.NET系列之Command对象 ADO.NET系列之DataAdapter对象 ADO.NET系列之事务和调用存储过程 上一篇<ADO.NE ...

  4. asp.net—策略模式

    一.什么是策略模式 定义:定义一系列算法,把一个个算法封装成独立类并实现同一个接口,使得它们之间可以相互替换. 二.怎么使用策略模式 首先模拟一个场景:有一个用户想买车.  可以有多种方式买车: (1 ...

  5. c#位运算小例子笔记

    关于位运算,网上有挺多好的博客介绍过,我就不多解释了 这里只记录一个小例子,是在理解位运算时候写的,帮助自己加深一下印象,做个笔记mark一下 具体场景 摇骰子游戏 1每个骰子有6个点,1-3为小,4 ...

  6. hdu 4325 Flowers(区间离散化)

    http://acm.hdu.edu.cn/showproblem.php?pid=4325 Flowers Time Limit: 4000/2000 MS (Java/Others)    Mem ...

  7. zoj2893 Evolution(矩阵快速幂)

    题意:就是说物种进化,有N种物种,编号是0——N-1,M次进化后,问你编号为N-1的物种有多少数量:其中要注意的就是i物种进化到j物种的概率是p:(那么剩下的不要忘了):所以单位矩阵初始化对角线的值为 ...

  8. Codeforces450 B. Jzzhu and Sequences (找规律)

    题目链接:https://vjudge.net/problem/CodeForces-450B Jzzhu has invented a kind of sequences, they meet th ...

  9. Java原子操作类汇总

    当程序更新一个变量时,如果是多线程同时更新这个变量,可能得到的结果与期望值不同.比如:有一个变量i,A线程执行i+1,B线程也执行i+1,经过两个线程的操作后,变量i的值可能不是期望的3,而是2.这是 ...

  10. css单行文本及多行文本溢出显示省略号

    关于文本溢出的相关属性: 1. text-overflow: clip|ellipsis|string;   该属性规定当文本溢出包含元素时发生的事情. clip : 修剪文本. ellipsis : ...