手写spring+springmvc+mybatis框架篇【开篇】

知音专栏

程序员的出路

写程序时该追求什么,什么是次要的?

如何准备Java初级和高级的技术面试

算法的力量,李开复聊算法的重要性

我们平日开发时所用的SSM框架,可是你真的了解它吗?技术革新,换代应接不暇,只有理解了源码才能保证在技术快速更迭的时代中真正站稳脚跟。

本系列文章抽丝剥茧,源码分析百度有很多,在这里只列举几个我收录的优秀的博客推荐给大家,本文不过多的分析源码,更注重将代码理解后的实现。

话不多说,开启正题。(由于本人是小白,理解的不深所以写出来的东西比较浅显易懂。如果有错误还望各位大佬指出来,帮助我提高)

项目介绍:此项目是在手写SSM框架的基础上开发了一个简单的登录功能。

首先是spring框架的实现,spring的依赖注入特性是集成其他所有框架的基础。在spring2.5版本之前,只支持配置文件注入。在2.5之后加入了@Autowired注解,实现了注解注入。我们的这个spring框架当然是都支持啦。首先是xml版本注入。目前支持的是构造器注入和set属性注入。

实现思路:

用dom4j解析xml文件。获取各个节点的属性和内容。

用枚举定义IOC的bean的规则,用BeanFacory的getBean方法读取配置信息,如果xml读取到的属性和IOCRULES的枚举内容匹配的话,用BeanDefinitionMap对象保存,然后用反射实例化一个对象。

读取在xml文件中读取到的扫包路径,扫描此路径下的有注解的类按照自下而上的顺序存储在componentList中。

将componentList对象按照顺序实例化出对象。

一些高大上的名词,其实就是一些对象或者数据结构。比如我们常说的spring容器其实就指的是一个map对象集合,在spring源码其实就是DefaultListableBeanFactory类中如下对象


private final Map<String, BeanDefinition> beanDefinitionMap
= new ConcurrentHashMap<String, BeanDefinition>(256);

将这些对象实例化之后就是我们说的注入。再比如springmvc中的handlerMapping,其实就是map集合,key是方法名,value是@RequestMapping的路径。再比如...还有很多,在实战之前我先提出几个我自己想到的问题,希望大家看的时候带着问题提来看:

spring有xml配置,也有注解配置,那么先实例化的是哪种版本呢?

构造器注入,属性注入如何实现的?

在指定包的路径下有那么多要注入的bean,service层调用dao,所以dao层一定要在service之前注入,然后在service层属性注入的时候才能将dao层注入,那么如何保证实例化的顺序呢?这也是难点。

我们使用的时候只需要用@Autowired标记接口,即可使用。但是我们知道接口并不能实例化对象,那么spring是如何做到的呢?而且有的接口有实现类,在mybatis中连实现类都没有,如何实现的呢?

效果图

手写spring+springmvc+mybatis框架篇【开篇】

手写spring+springmvc+mybatis框架篇【开篇】

下面开始实战:

  1. 项目必须用jdk1.8,不然会报错.里面一些方法只有1.8才有。

  2. 用到了lombok这个jar包,主要是简化了代码量,一个注解就可以省略getset方法。

  3. 解析xml用的dom4j,在小型xml文件的解析和操作中dom4j是最佳选择

  4. 在最后的demo中,RegisterServiceImpl,UserServiceImpl,RegisterService,UserService等文件没有真正的使用。只是考虑多层注入的时候,为了测试注入的顺序是否是对的。在dao层真正用的是UserMapper这个接口。

先介绍一下工具类吧。省的代码中出现的时候大家看不懂


package spring.Utils;

/**
* Created by Xiao Liang on 2018/6/27.
* 注解工具类:判断注解是否为空
*/
public class  AnnotationUtils {
   public  static <T>  boolean isEmpty(T t){
       return  t == null ? true : false;
   }
}

package spring.Utils;

/**
* @ClassName ConvertUtis
* @Description 根据传入的属性和类名,将属性名强转为类名的属性
* @Data 2018/7/4
* @Author xiao liang
*/
public class ConvertUtis {

   public static Object  convert(String className,String parameter){
       if (className.equals("String")){
           return parameter;
       }
       else if (className.equals("Integer")){
           return Integer.valueOf(parameter);
       }
       else if (className.equals("int")){
           return Integer.valueOf(parameter);
       }
       else if (className.equals("Float")){
           return Float.valueOf(parameter);
       }
       else if (className.equals("Double")){
           return Integer.valueOf(parameter);
       }
       else if (className.equals("Long")){
           return Long.valueOf(parameter);
       }
       else if (className.equals("Short")){
           return Short.valueOf(parameter);
       }
       else if (className.equals("Byte")){
           return Byte.valueOf(parameter);
       }
       else if (className.equals("Boolean")){
           return Boolean.valueOf(parameter);
       }
       return null;

   }
}
package spring.Utils;

/**
* @ClassName GetMethodName
* @Description 根据属性名拼接set方法
* @Data 2018/7/4
* @Author xiao liang
*/
public class GetMethodName {
   public   static  String getSetMethodNameByField(String propertyName) {
       String methodName = "set" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
       return methodName;
   }
}
package spring.Utils;

/**
* @ClassName isBasicType
* @Description 判断是不是基本数据类型
* @Data 2018/7/4
* @Author xiao liang
*/
public class isBasicTypeUtils {
   public static boolean  isBasicType(String typeName){
       if (typeName.equals("String")){
           return true;
       }
       else if(typeName.equals("Integer")){
           return true;
       }
       else if(typeName.equals("int")){
           return true;
       }
       else if(typeName.equals("Long")){
           return true;
       }
       else if(typeName.equals("Short")){
           return true;
       }
       else if(typeName.equals("Float")){
           return true;
       }
       else if(typeName.equals("Double")){
           return true;
       }
       else if(typeName.equals("Byte")){
           return true;
       }
       return false;
   }
}
package spring.Utils;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
*  @Author xiao liang
*  @Desprition 在链表中添加数据,添加时保证只有一个相同的实例
*/
public class ListAddUtils {
   public static <T> void add(List<T> list ,T t) {
       Set<T> set1 = new HashSet<>(list);
       if (set1.add(t)){
           list.add(t);
       }
   }
}
package spring.Utils;
/**
*  @Author xiao liang
*  判断字符串是否为空
*/
public class StringUtils {
   public static boolean isEmpty(String string) {
       if ((string == null) || "".equals(string)) {
           return true;
       }
       return false;
   }
}

还有一个常量类。

package spring.constants;

import spring.xml.FileSystemXmlApplicationContext;
/**
* Created by Xiao Liang on 2018/6/27.
* @Description :保存的是各个配置文件的路径
*/
public interface Constants {
   String PATH = FileSystemXmlApplicationContext.class.getResource("/").getPath();
   String contextConfigLocation = "application.xml";
   String springmvcConfigLocation = "spring-mvc.xml";
   String mybatisConfigLocation = "MyUserMapper.xml";
}

还有三个xml文件:

application.xml


<?xml version="1.0" encoding="UTF-8"?>
<beans>
   <bean id="hostess" class="spring.Person">
       <property name ="userName" value = "admin"></property>
       <property name ="passWord" value = "admin"></property>
   </bean>
   <bean class="spring.mybatis.JDBCUtils" id="dataSource">
       <property name="user" value="root"></property>
       <property name="password" value="qinliang"></property>
       <property name="driver" value="com.mysql.jdbc.Driver"></property>
       <property name="url" value="jdbc:mysql://localhost:3306/test"></property>
   </bean>

   <component-scan base-package="spring.demo" >
   </component-scan>

</beans>

springmvc.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans>
   <bean id="viewResolver" class="spring.springmvc.ViewResolver">
       <property name="prefix" value="/WEB-INF/views/"></property>
       <property name="suffix" value=".jsp"></property>
   </bean>
</beans>

MyUserMapper.xml


<?xml version="1.0" encoding="UTF-8"?>
<mapper namespace="spring.demo.repository.UserMapper">

   <select id="queryUser" resultType="spring.dataObject.User">
       select * from login_user where username = #{username} AND password = #{password}
   </select>

</mapper>

这是一个maven项目,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/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.myspring</groupId>
   <artifactId>start</artifactId>
   <version>1.0-SNAPSHOT</version>
   <packaging>war</packaging>
   <name>start Maven Webapp</name>
   <!-- FIXME change it to the project's website -->
   <url>http://www.example.com</url>

   <properties>
       <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
       <maven.compiler.source>1.8</maven.compiler.source>
       <maven.compiler.target>1.8</maven.compiler.target>
   </properties>

   <dependencies>
       <dependency>
           <groupId>junit</groupId>
           <artifactId>junit</artifactId>
           <version>4.11</version>
           <scope>test</scope>
       </dependency>

       <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
       <dependency>
           <groupId>org.projectlombok</groupId>
           <artifactId>lombok</artifactId>
           <version>1.18.0</version>
           <scope>provided</scope>
       </dependency>
       <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
       <dependency>
           <groupId>org.slf4j</groupId>
           <artifactId>slf4j-api</artifactId>
           <version>1.7.25</version>
       </dependency>

       <dependency>
           <groupId>org.slf4j</groupId>
           <artifactId>slf4j-simple</artifactId>
           <version>1.7.25</version>
       </dependency>

       <dependency>
           <groupId>javax.servlet</groupId>
           <artifactId>servlet-api</artifactId>
           <version>2.5</version>
       </dependency>

       <dependency>
           <groupId>javax.servlet.jsp</groupId>
           <artifactId>jsp-api</artifactId>
           <version>2.1.3-b06</version>
       </dependency>

       <dependency>
           <groupId>dom4j</groupId>
           <artifactId>dom4j</artifactId>
           <version>1.6.1</version>
       </dependency>

       <!-- https://mvnrepository.com/artifact/jstl/jstl -->
       <dependency>
           <groupId>jstl</groupId>
           <artifactId>jstl</artifactId>
           <version>1.2</version>
       </dependency>
       <!--数据库连接池和数据库连接-->
       <dependency>
           <groupId>mysql</groupId>
           <artifactId>mysql-connector-java</artifactId>
           <version>5.1.8</version>
       </dependency>

   </dependencies>

   <build>
       <finalName>start</finalName>
       <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
           <plugins>
               <plugin>
                   <artifactId>maven-clean-plugin</artifactId>
                   <version>3.0.0</version>
               </plugin>
               <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
               <plugin>
                   <artifactId>maven-resources-plugin</artifactId>
                   <version>3.0.2</version>
               </plugin>
               <plugin>
                   <artifactId>maven-compiler-plugin</artifactId>
                   <version>3.7.0</version>
               </plugin>
               <plugin>
                   <artifactId>maven-surefire-plugin</artifactId>
                   <version>2.20.1</version>
               </plugin>
               <plugin>
                   <artifactId>maven-war-plugin</artifactId>
                   <version>3.2.0</version>
               </plugin>
               <plugin>
                   <artifactId>maven-install-plugin</artifactId>
                   <version>2.5.2</version>
               </plugin>
               <plugin>
                   <artifactId>maven-deploy-plugin</artifactId>
                   <version>2.8.2</version>
               </plugin>
           </plugins>
       </pluginManagement>
   </build>
</project>

下面是项目的业务逻辑代码,可以过一下,就是最简单的三层架构。业务逻辑代码中中有一些为了测试用,并没有实际的意义


package spring.demo.controller;

import spring.annotation.MyAutowired;
import spring.annotation.MyController;
import spring.annotation.MyModelAttribute;
import spring.annotation.MyRequestMapping;
import spring.dataObject.User;
import spring.demo.service.UserService;
import spring.springmvc.MyModelAndView;
import spring.springmvc.MyModelMap;
import spring.xmlRules.RequestMethod;
/**
* Created by Xiao Liang on 2018/6/27.
*/
@MyController
public class LoginController {

   @MyAutowired
   private UserService userService;
   //测试用的@MyRequstParam(value = "userName") String userName,  @MyRequstParam(value = "passWord") Integer passWord
   //返回值只支持MyModelAndView,数据模型和视图模型相结合
   @MyRequestMapping(value = "/hello", method = RequestMethod.POST)
   public MyModelAndView login(@MyModelAttribute("User") User user) {
       MyModelAndView myModelAndView = new MyModelAndView("success");
       MyModelMap myModel = new MyModelMap();
       User user1 = userService.queryUser("admin", "admin");
       myModel.addAttribute("test", user1.getUserName());
       myModelAndView.setModelMap(myModel);
       return myModelAndView;
   }
   @MyRequestMapping("/hello22")
   public String test() {
       return "success";
   }
}
package spring.demo.controller;

import spring.annotation.MyAutowired;
import spring.annotation.MyController;
import spring.annotation.MyRequestMapping;
import spring.demo.service.RegisterService;
import spring.demo.service.UserService;
/**
* Created by Xiao Liang on 2018/6/27.
*/
@MyController
public class RegisterController {
   @MyAutowired
   private UserService userService;
   @MyAutowired
   private RegisterService registerService;
   @MyRequestMapping("/register")
   public void regeister(){
       userService.queryUser("","");
       registerService.register();
   }
}
package spring.demo.service;

import spring.dataObject.User;
/**
* Created by Xiao Liang on 2018/6/27.
*/
public interface UserService {
    User queryUser(String userName, String passWord);
}

package spring.demo.service;

/**
* Created by Xiao Liang on 2018/6/27.
*/
public interface RegisterService {
   void register();
}

package spring.demo.service.impl;

import spring.annotation.MyAutowired;
import spring.annotation.MyService;
import spring.dataObject.User;
import spring.demo.repository.RegisterDao;
import spring.demo.repository.UserDao;
import spring.demo.repository.UserMapper;
import spring.demo.service.UserService;
/**
* Created by Xiao Liang on 2018/6/27.
*/
@MyService
public class UserServiceImpl implements UserService {
   @MyAutowired
   private UserDao userDao;
   @MyAutowired
   private RegisterDao registerDao;
   @MyAutowired
   private UserMapper userMapper;
   @Override
   public User queryUser(String userName, String passWord) {
       return userMapper.queryUser(userName,passWord);
   }
}

package spring.demo.service.impl;

import spring.annotation.MyAutowired;
import spring.annotation.MyService;
import spring.demo.repository.RegisterDao;
import spring.demo.service.RegisterService;
/**
* Created by Xiao Liang on 2018/6/27.
*/
@MyService
public class RegisterServiceImpl implements RegisterService{
   @MyAutowired
   private RegisterDao registerDao;
   @Override
   public void register() {
       registerDao.register();
   }
}
package spring.demo.repository;

/**
* Created by Xiao Liang on 2018/6/27.
*/
public interface UserDao {
     void test();
}
package spring.demo.repository;

/**
* Created by Xiao Liang on 2018/6/27.
*/
public interface RegisterDao {
    void register();
}

package spring.demo.repository.impl;

import spring.annotation.MyRepository;
import spring.demo.repository.UserDao;
/**
* Created by Xiao Liang on 2018/6/27.
*/
@MyRepository
public class UserDaoImpl implements UserDao {
   @Override
   public void test() {
       System.out.println("我是UserDao");
   }
}
package spring.demo.repository.impl;

import spring.annotation.MyRepository;
import spring.demo.repository.RegisterDao;
/**
* Created by Xiao Liang on 2018/6/27.
*/
@MyRepository
public class RegisterDaoImpl implements RegisterDao{
   @Override
   public void register() {
       System.out.println("我是RegisterDao");
   }
}

package spring.demo.repository;

import spring.dataObject.User;
/**
* @ClassName UserMapper
* @Description
* @Data 2018/7/7
* @Author xiao liang
*/
public interface UserMapper {
   User queryUser(String userName,String passWord);
}

我将此项目上传到了github,需要的童鞋可以点击下方阅读原文自行下载。

原文地址:https://blog.51cto.com/u_15127600/2757712

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


开发过程中是不可避免地会出现各种异常情况的,例如网络连接异常、数据格式异常、空指针异常等等。异常的出现可能导致程序的运行出现问题,甚至直接导致程序崩溃。因此,在开发过程中,合理处理异常、避免异常产生、以及对异常进行有效的调试是非常重要的。 对于异常的处理,一般分为两种方式: 编程式异常处理:是指在代
说明:使用注解方式实现AOP切面。 什么是AOP? 面向切面编程,利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。 通俗描述:不通过修改源代码方式,在主干功能里面添加新功能。 AOP底层使用动态代理。 AOP术语 连接点
Spring MVC中的拦截器是一种可以在请求处理过程中对请求进行拦截和处理的机制。 拦截器可以用于执行一些公共的操作,例如日志记录、权限验证、数据转换等。在Spring MVC中,可以通过实现HandlerInterceptor接口来创建自定义的拦截器,并通过配置来指定拦截器的应用范围和顺序。 S
在 JavaWeb 中,共享域指的是在 Servlet 中存储数据,以便在同一 Web 应用程序的多个组件中进行共享和访问。常见的共享域有四种:ServletContext、HttpSession、HttpServletRequest、PageContext。 ServletContext 共享域:
文件上传 说明: 使用maven构建web工程。 使用Thymeleaf技术进行服务器页面渲染。 使用ResponseEntity实现下载文件的功能。 @Controller public class FileDownloadAndUpload { @GetMapping(&quot;/file/d
创建初始化类,替换web.xml 在Servlet3.0环境中,Web容器(Tomcat)会在类路径中查找实现javax.servlet.ServletContainerInitializer接口的类,如果找到的话就用它来配置Servlet容器。 Spring提供了这个接口的实现,名为SpringS
在 Web 应用的三层架构中,确保在表述层(Presentation Layer)对数据进行检查和校验是非常重要的。正确的数据校验可以确保业务逻辑层(Business Logic Layer)基于有效和合法的数据进行处理,同时将错误的数据隔离在业务逻辑层之外。这有助于提高系统的健壮性、安全性和可维护
什么是事务? 事务(Transaction)是数据库操作最基本单元,逻辑上一组操作,要么都成功,要么都失败,如果操作之间有一个失败所有操作都失败 。 事务四个特性(ACID) 原子性 一组操作要么都成功,要么都失败。 一致性 一组数据从事务1合法状态转为事务2的另一种合法状态,就是一致。 隔离性 事
什么是JdbcTemplate? Spring 框架对 JDBC 进行封装,使用 JdbcTemplate 方便实现对数据库操作。 准备工作 引入jdbcTemplate的相关依赖: 案例实操 创建jdbc.properties文件,配置数据库信息 jdbc.driver=com.mysql.cj.
SpringMVC1.MVC架构MVC是模型(Model)、视图(View)、控制器(Controller)的简写,是一种软件设计规范是将业务逻辑、数据、显示分离的方法来写代码MVC主要作用是:降低了视图和业务逻辑之间的双向耦合MVC是一个架构模型,不是一种设计模式。1.model(模型)数据模型,提供要展示的数据,因此包
SpringMVC学习笔记1.SpringMVC应用1.1SpringMVC简介​SpringMVC全名叫SpringWebMVC,是⼀种基于Java的实现MVC设计模型的请求驱动类型的轻量级Web框架,属于SpringFrameWork的后续产品。​MVC全名是ModelViewController,是模型(model)-视图(view)-控制器(co
11.1数据回显基本用法数据回显就是当用户数据提交失败时,自动填充好已经输入的数据。一般来说,如果使用Ajax来做数据提交,基本上是没有数据回显这个需求的,但是如果是通过表单做数据提交,那么数据回显就非常有必要了。11.1.1简单数据类型简单数据类型,实际上框架在这里没有
一、SpringMVC简介1、SpringMVC中重要组件DispatcherServlet:前端控制器,接收所有请求(如果配置/不包含jsp)HandlerMapping:解析请求格式的.判断希望要执行哪个具体的方法.HandlerAdapter:负责调用具体的方法.ViewResovler:视图解析器.解析结果,准备跳转到具体的物
1.它们主要负责的模块Spring主要应用于业务逻辑层。SpringMVC主要应用于表现层。MyBatis主要应用于持久层。2.它们的核心Spring有三大核心,分别是IOC(控制反转),DI(依赖注入)和AOP(面向切面编程)。SpringMVC的核心是DispatcherServlet(前端控制器)。MyBatis的核心是ORM(对
3.注解开发Springmvc1.使用注解开发要注意开启注解支持,2.注解简化了,处理映射器和处理适配器,只用去管视图解析器即可案例代码:1.web.xml,基本不变可以直接拿去用<!--调用DispatcherServlet--><servlet><servlet-name>springmvc</servlet-name>
拦截器概述SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。开发者可以自己定义一些拦截器来实现特定的功能。**过滤器与拦截器的区别:**拦截器是AOP思想的具体应用。过滤器servlet规范中的一部分,任何javaweb工程都可以使用
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:xsi="
学习内容:1、SSH&SSM2、Spring3、Struts2&SpringMVC4、Hibernate&MyBatis学习产出:1.SSH和SSM都是有Spring框架的,他们两个差不多。2.Spring分为四个模块,持久层,表示层,检测层,还有核心层,核心层分为2个关键核心功能。分别为,控制反转(IOC),依赖注入(DI),和面向切面编程
一、SpringMVC项目无法引入js,css的问题具体原因是css和js等被SpringMVC拦截了:解决方案:在spring-mvc.xml中配置<mvc:default-servlet-handler/><?xmlversion="1.0"encoding="UTF-8"?><beansxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
开发环境:Eclipse/MyEclipse、Tomcat8、Jdk1.8数据库:MySQL前端:JavaScript、jQuery、bootstrap4、particles.js后端:maven、SpringMVC、MyBatis、ajax、mysql读写分离、mybatis分页适用于:课程设计,毕业设计,学习等等系统介绍