Spring简介及Spring开发环境搭建

什么是Spring?

Java目前最流行的开发框架组合简称SSM:Spring,SpringMVC,MyBatis。有关Spring的“非人类语言”解释,请自行百度。
为什么说是“非人类语言”呢?
因为在我初学Spring的时候,网上查了很多资料,也翻看了一些书籍,对Spring的解释基本上都是用专业术语和抽象语言进行解释。如果你没学过Spring,看再多遍解释你还是不明白,所以这些解释都是非常不友好的。
今天我就现学现卖,说一下我对Spring框架的理解。

Spring:核心价值是IOC和AOP

  • IOC(Inversion of Control)控制反转。是通过Java反射原理去创建对象。实现了创建对象时的解耦合,提高代码的灵活性。Spring可以被理解为一个用于创建和管理对象的工厂,负责创建、管理所有JAVA对象。
    上面这些话翻译成人类语言就是说:
    之前我们用Java创建对象的时候都是用这种形式:

    new AClass();

    这种方式的问题是类名是写死在代码里面的,这种代码的耦合性太强。
    而在Spring里面,创建对象的时候是这样写的:

    xxx.getBean("AClass");

    类名是通过字符串传入的,这样耦合性大大降低。
    这一过程的实现,是由Spring基于Java的反射技术实现的,所以把Spring成为工厂,由这个工厂负责生产对象。

  • AOP(Aspect Oriented Programming)面向切面编程。底层基于动态代理机制实现。简单的来说就是如果系统需要增加某额外功能的时候,在不改变原有代码的情况下,可以通过AOP机制将新的功能织入到程序的切入点(切入点可以精确到方法)上。这是非常好的一种解耦合的机制。作用类似于JAVA拦截器和过滤器。
    我能想到的典型应用场景有两个:

    1. 客户之前委托第三方开发了某JAVA系统,现在委托给你做新功能添加。最稳妥的方式是以AOP的形式将新功能织入到现有系统中。这样不会影响之前的代码结构,后期也便于单独维护自己的代码。
    2. 假如我们想统计下当前所有Service层函数的执行时间,以便优化代码。不可能给每个函数单独增加统计时间的代码。最好的方法是通过AOP,将统计代码织入到函数切入点中。

如果看到这里还不明白,就不要再纠结概念问题了,直接学习技术,学完回过头来再看,就觉得上面的内容很好理解了。

Spring开发环境搭建

Spring开发环境搭建基于Maven。过程非常简单,只需要两步即可完成:

  1. 添加Spring依赖
    在Maven的pom.xml中添加如下依赖:

    <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.2.RELEASE</version>
    </dependency>
  2. 创建Spring配置文件applicationContext.xml
    在resources文件夹下新建applicationContext.xml文件,并将以下内容复制进去:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans   xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    </beans>

    applicationContext.xml在Eclipse里面只能自己创建空xml,然后撰写。在Intellij IDEA编辑器里面,可以直接从模板创建。或许这就是为什么越来越多的人转向Intellij IDEA的原因。

MAVEN的安装及通过Eclipse建立一个简单的MAVEN项目

MAVEN好学吗?

话说那天在B站上看到个视频说MAVEN很重要,是学习JAVA中必须学习的内容。进而搜索了下,搜到了个100多小时的教程。瞬间被吓到了~~
看视频的体量,确实是很重要,估计也很难。
然而,大家千万不要和我一样被误导。
任何一门技术做到极致都是很难的,但是MAVEN入门并不难,看完这个帖子,估计你也能把MAVEN用起来。至于用到什么程度,那就看你后面自己怎么深入了。

1.什么是MAVEN

maven英文原意是:专家、内行的意思。
有关MAVEN的介绍,大家自己百度下。
MAVEN的读音是[ˈmeɪvn](“mei wen”),别读成“ma wen”。
我始终认为,一个技术人员的英文水平很大程度上决定了他的高度...
说多了,咱们开始进入主题!

2.为什么要用MAVEN

如果用一句话介绍MAVEN的话,就是帮助JAVA项目管理jar包的工具。以前jar包需要东找西找,jar包之间也有着各种依赖关系,特别容易搞错。
有了MAVEN就一站式搞定,简单的配置一下,jar包导入和依赖关系等都帮你自动搞定。
当然MAVEN还有更高级的功能,大家自行深入学习哈。

3.MAVEN安装

安装文件下载
MAVEN是APACHE的项目,可以通过以下网址下载MAVEN安装文件。
https://maven.apache.org/
我写这篇文章的时候MAVEN的最新版本是3.6.3,加之我是Windows系统,所以选择下载:apache-maven-3.6.3-bin.zip
file
下载完成后,我解压到以下位置:
F:\apache-maven-3.6.3
file
配置环境变量
两个地方:

  1. 增加MAVEN_HOME变量,值为:F:\apache-maven-3.6.3
  2. PATH变量追加增加:F:\apache-maven-3.6.3\bin
    修改MAVEN本地仓库
    这个地址说的是如果自动下载了jar包,这些jar包保存在本地电脑上的位置。
    这个地址默认是在C盘,一般都会改放在其它盘符。
    修改F:\apache-maven-3.6.3\conf\settings.xml
    file
    修改MAVEN远程仓库地址
    这个地址说的是从哪里下载jar包。
    默认的地址是国外服务器地址,下载速度太慢。所以改为阿里云的镜像地址(啰嗦下,阿里云里面各种镜像基本上都是与国外服务器实时同步的,可以说是个高速版的大宝库。建议大家自行探索下)。
    增加以下内容至settings.xml

    <mirror>
    <id>alimaven</id>
    <name>aliyun maven</name>
    <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
    <mirrorOf>central</mirrorOf>
    </mirror>

    file

    4.Eclipse中配置MAVEN

    A. 最新版的Eclipse中默认带了MAVEN插件,只需要将第三步中修改的settings.xml文件地址配置到插件上即可。
    file
    B.这个地方勾选上,每次启动Eclipse都会自动更新jar包仓库。
    file

到此为止,MAVEN的安装和配置就完成了!!!欢呼!!欢呼!!

5.MAVEN中Web项目的目录结构

先通过Eclipse新建一个基于MAVEN的web项目
A.从MAVEN新建项目
file
B.使用默认的位置
file
C.选择apache下的webapp骨架
file
D.填写项目信息
file
然后呢?你就会开心的发现,在你的项目里面,已经自动帮你下载好了各种Web项目可能用到的jar包
file
还没完,你还需要手动建些文件夹
以下是MAVEN对于web项目的目录结构要求
file
从Eclipse里面可以看到,MAVEN默认创建的骨架中还少几个文件夹。不要问为什么?我也不知道。反正大家按照提示手工建立那几个文件夹就是了。

6.使用MAVEN配置MySQL数据库

MAVEN的核心就是项目创建时自动生成的那个pom.xml文件。
MAVEN的使用也基本上都是围绕这个XML文件展开的。
比如说我们现在的项目要链接MySQL数据库,在没有MAVEN的时候,需要手工下载导入jar包。现在有MAVEN了,这个工作就变得很简单了。只需要将下面的代码加到pom.xml的<dependencies>标签下面

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.6</version>
</dependency>

然后ctrl+s保存下,和MySQL相关的jar包就自动下载并加载好了。
这下体会到MAVEN的意义了吧?

7.使用MAVEN配置Oracle数据库

说了MySQL,为啥还要专门说Oracle呢?
是因为我第一次使用MAVEN的时候就是想添加Oracle依赖,但是无论如何都添加不上,一直报错。
经过多方查找,竟然是因为版权!
Oracle估计没有开放版权,换句话说,你想用Oracle的jar包,你就得自己下载,然后自己导入到MAVEN仓库中,再通过MAVEN添加依赖。
具体做法如下:

  1. 在Oracle官网,或者本地安装的Oracle中找到对应的jar包。由于我本地安装了Oracle,确定jar包位置:F:\ORACLE_WORKPLACE\Oracle18c\jdbc\lib\ojdbc8.jar
  2. 打开cmd,运行以下代码:
    mvn install:install-file -DgroupId=com.oracle -DartifactId=ojdbc8 -Dversion=11.2.0.1.0 -Dpackaging=jar -Dfile=F:\ORACLE_WORKPLACE\Oracle18c\jdbc\lib\ojdbc8.jar

    意思就是说把这个jar包导入到MAVEN仓库。

  3. 导入成功后,在pom.xml中添加以下依赖即可。
    <dependency>
    <groupId>com.oracle</groupId>
    <artifactId>ojdbc8</artifactId>
    <version>11.2.0.1.0</version>
    </dependency>
  4. 既然Oracle出现这个问题,估计其他的依赖也有可能出现类似的问题,不过目前还未发现。所以这里先给大家提个醒。

8.从哪里找依赖的代码?

你可能会问,你怎么知道依赖里面的细节怎么写?
哈哈,给你个网站 https://mvnrepository.com/
所有的依赖都是从这里面查出来的。

9.大功告成,测试一下

package com.royotech.view;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;

public class InsertPerson {
    public static void main(String[] args) throws Exception{
        //加载驱动
        Class.forName("oracle.jdbc.OracleDriver");
        String username = "hr";
        //建立连接
        String password = "123123";
        String url = "jdbc:oracle:thin:@localhost:1521:orcl";
        Connection conn = DriverManager.getConnection(url, username, password);
        //新建发送SQL的工具
        String sql = "insert into t_person values(seq_person.nextval,'李小美','女','28','13838758888','金澳科技')";
        PreparedStatement pstm = conn.prepareStatement(sql);
        //发送并执行SQL
        int rows = pstm.executeUpdate();
        System.out.println("影响行数:" + rows);
        //处理结果集
        //释放资源
        pstm.close();
        conn.close();
    }
}

哈哈,成功了!
file

写在最后

当前是技术大爆发的时代,每个月甚至每天都会有新的技术、框架涌现出来。
从技术创作者的角度,他肯定是希望技术被大众使用,那么他就会尽可能降低初学者学习的门槛。
所以大家在遇到新生事物的时候,不要被吓倒,勇敢向前,你会发现你比你自己想象的更聪明!

MyBatis项目环境搭建及第一个MyBatis程序

1. 导入相关jar包。

需要导入的jar包有两部分,一个是MyBatis的jar包。
另外由于MyBatis是操作数据库的,我们以MySQL数据库作为示范,所以还要导入MySQL数据库的jar包。
导入jar包的方式有很多种,最简单的就是去官网下载jar包,然后复制到代码目录里。
但这里我们通过添加MAVEN依赖的方式导入。

2. 通过MAVEN导入依赖。

至于MAVEN是什么,请参照本站有关MAVEN的文章。要说的是,MAVEN其实很简单。
需要添加的MAVEN依赖如下:

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.3</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.6</version>
</dependency>

3. 导入并撰写配置文件mybatis-config.xml

  • mybatis-config.xml 用于配置mybatis的基本参数(数据库接口类型、用户名、密码)
  • 为了对应MAVEN目录结构,mybatis-config.xml放在resources目录下。
    基本上就是固定格式

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configuration
    PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
    <environments default="development">
    <!-- 数据库环境:开发环境 -->
    <environment id="development">
      <transactionManager type="JDBC"/> <!-- JDBC:手动完成事物管理; MANAGED:由第三方完成事物管理 -->
      <dataSource type="POOLED">        <!-- POOLED:使用数据库连接池;UNPOOLED:不使用数据库连接池 -->
        <property name="driver" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/java_all"/>
        <property name="username" value="root"/>
        <property name="password" value="123123"/>
      </dataSource>
    </environment>
    </environments>
    </configuration>

4. 创建Entity类和DAO接口

MyBatis的存在意义就是代替DAO接口实现类,所以不需要再创建DAO接口实现类了。

创建Entity类

/** 
 * 定义实体类
 * 1. 实体类定义在entity包下
 * 2. 实体类必须实现Serializable接口
 * 3. 实体类属性名字和数据库字段名一致,这样可以自动赋值
 * 4. 实体类属性数值类型使用包装类,并提供get、set方法
 * 5. 实体类必须提供无参数的构造方法
 * 6. 实体类可以重载toString方法,这样方便println直接使用。
 */
package com.royotech.entity;

import java.io.Serializable;

public class Person implements Serializable{
    private Integer id;
    private String name;
    private String birthday;
    private String telephone;
    private String address;

    public Person() {
        super();
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getBirthday() {
        return birthday;
    }

    public void setBirthday(String birthday) {
        this.birthday = birthday;
    }

    public String getTelephone() {
        return telephone;
    }

    public void setTelephone(String telephone) {
        this.telephone = telephone;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "Person [id=" + id + ", name=" + name + ", birthday=" + birthday + ", telephone=" + telephone
                + ", address=" + address + "]";
    }
}

创建DAO接口

/**
 * 
 * DAO:Data Access Object,DAO接口是Entity类和数据库之间的连接纽带,封装增删改查的操作。
 * 
 * DAO接口:实体类名+DAO,所有DAO接口都在DAO包下。
 *
 * 一个表 一个实体 一个DAO接口
 */

package com.royotech.dao;

import com.royotech.entity.Person;

public interface PersonDAO {
    public Person selectPersonById(Integer id);
}

5. 撰写XXXMapper.xml文件

撰写PersonDAOMapper.xml映射文件

  • XXXMapper.xml 配置一个DAO接口方法要执行的SQL语句。XXXMapper.xml文件和DAO接口一一对应。
  • 为了对应MAVEN目录结构,XXXMapper.xml放在resources/mappers子目录下。
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.royotech.dao.PersonDAO"> <!-- 对应的DAO接口的全类名 -->
    <select id = "selectPersonById" resultType="com.royotech.entity.Person"> <!-- id对应类下面的方法名;resultType对应该方法的返回值类型-->
        select *
        from t_person
        where id = #{id}<!-- 方法中形参的名字 -->
    </select>
    </mapper>

6. 在mybatis-config.xml中注册mapper

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
  <environments default="development">
    <!-- 数据库环境:开发环境 -->
    <environment id="development">
      <transactionManager type="JDBC"/> <!-- JDBC:手动完成事物管理; MANAGED:由第三方完成事物管理 -->
      <dataSource type="POOLED">        <!-- POOLED:使用数据库连接池;UNPOOLED:不使用数据库连接池 -->
        <property name="driver" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/java_all"/>
        <property name="username" value="root"/>
        <property name="password" value="123123"/>
      </dataSource>
    </environment>
  </environments>
  <mappers>
    <mapper resource="mappers/PersonDAOMapper.xml"/>
  </mappers>
</configuration>

7. 大功告成,测试一下结果吧。

建立一个SelectPerson.java文件

package com.royotech.view;

import java.io.InputStream;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import com.royotech.dao.PersonDAO;
import com.royotech.entity.Person;

public class SelectPerson { 
    public static void main(String[] args) throws Exception{
        //1. 读取配置文件
        InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
        //2. 获取SqlSessionFactory
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
        //3. 获取SqlSession
        SqlSession sqlSession = factory.openSession();
        //4. 获取PersonDAO实现类对象
        PersonDAO dao = sqlSession.getMapper(PersonDAO.class);
        //5. 调用DAO的方法
        Person p = dao.selectPersonById(3);
        System.out.println(p);

        //6. 关闭sqlSession
        sqlSession.close();
    }
}

数据库结构、数据和运行结果如下:
file

JAVA三层架构及基于三层架构的代码组织形式

看了很多教程和书籍,将JAVA三层架构进行一下总结。
欢迎同行提出宝贵意见,大家一起进步!

首先要说的是,关于Java三层架构的叫法有很多,中英文都演化出了很多不同的版本,但总体来说意思是一样的,所以不要太纠结于名称和叫法,重要的是对三层架构理念的理解。

JAVA三层架构如下:

  1. 视图层(或:表现层)
    英文的:View或Presentation
    用于接受用户输入的数据,以及显示结果。
  2. 业务逻辑层(或:服务层)
    英文的:Service或Application
    根据功能(业务)不同,执行不同的逻辑判断。
  3. 持久化层(或:数据访问层)
    英文的:DAO或Data
    用于访问数据库中的数据。

学Java学的是什么?

其实Java的语法和其它语言相比并无特殊之处,相比较于现在流行的Python等其它语言,甚至算不上优美。写惯了Python、Perl、PHP代码,会觉得Java非常繁琐。

既然从优美的角度Java并不占优势,我们就要从实用性的角度去学习这门语言了。

很多刚刚学习Java的人会觉得Java这门语言里面有很多“脱裤子放屁”的事情。本来一个文件,一行代码就能搞定的事情,它非要搞得很复杂。然而这就是学习Java的核心所在,学习Java其实就是学架构,就是学思想。很多初学阶段看似“脱裤子”放屁的事情,在项目实战中却是及其重要的。

根据Java的三层架构,演绎出以下常用的Java代码组织架构。

JAVA代码组织架构

  1. DAO层
    1. 数据库中的每一张表对应Java中的一个实体类(实体类常用英文是:Entity)。
    2. 每个Entity实体类又对应一个DAO接口及这个DAO接口的impl实现类。
  2. Service层
    1. 数据库中的每一张表对应一个Service服务类。
    2. XXXService服务类封装对t_xxx表的业务功能操作。
    3. 先定义Service接口,再编写这个Service接口对应的impl实现类。
  3. View层
    1. 负责提供一个功能入口,接受用户输入;显示结果。
    2. 一个功能对应一个View类,如XXXView

规则定好了,看下实际效果

file
对着上面这张图,再详细解释下:
假设我们数据库中只有一张数据表t_person表,所有的业务逻辑都围绕着这一张数据表来。

  1. DAO层
    1. 建立entity包,并在包下建立Person实体类,并注意:
      1. 实体类定义在entity包下
      2. 实体类必须实现Serializable接口
      3. 实体类属性必须私有,且数据类型使用包装类,并提供get、set方法。
      4. 实体类必须提供无参的构造方法
    2. 建立dao包,并在包下建立PersonDAO接口。
    3. 建立dao.impl子包,并在包下建立PersonDAOImpl类,用于实现PersonDAO接口。
  2. Service层
    1. 建立service包,并在包下建立UserService接口。
    2. 建立service.impl子包,并在包下建立UserServiceImpl类,用于实现UserService接口。
  3. View层
    1. 建立view包
    2. 在包下建立InsertPerson和SelectPerson两个类。用于完成插入和查询两个操作过程中与用户的交互。
    3. 如果是Web项目,再创建对应的JSP页面。

MySQL新建数据库时utf8_general_ci、utf8_bin、utf8_unicode_ci的区别

创建数据库时的三要素

现在各种基于MySQL数据库的开源框架非常多,基本上大家都是先安装再二次开发。

在安装开源框架的时候,需要先在MySQL里面新建一个数据库,新建数据库的时候需要确定三个重要的信息:
file

  1. Database name
  2. Database charset
  3. Database collation

这个三个信息中文直译和对应的意思分别是:

  1. Database name
    数据库名称。就是新建的这个数据库的名字是什么。
  2. Database charset
    数据库字符集。这个数据库使用哪种字符集存储数据库。对于中文项目或者可能包含非英语的国际语言的项目而言,一般都会选择UTF-8,这个基本上有点开发经验的人都应该知道。
  3. Database collation
    数据库整理规则( 排序规则 )。这个选择起来可能就有些晕了,我们来看看可选项有哪些?
    file
    在众多选项中,多数人应该会在utf8_bin、utf8_general_ci、utf8_unicode_ci三者之间由于不定。

选哪个?

要想确定选哪个,其实看看三者的英文全称就能略知一二了。

  • utf8_bin是utf8 binary的缩写。该种排序方式区分字母大小写。
  • utf8_general_ci是utf8 general case insensitive的缩写。该种方式不区分字母大小写,排序效率高,且对绝大多数语言的字符能够做到有效的排序。
  • utf8_unicode_ci是utf8_unicode case insensitive的缩写。不区分大小写,排序效率较utf8_general_ci而言稍低,但对语言字符排序的支持比utf8_general_ci更好。

所以

一般情况下,选择utf8_general_ci就可以了。这也是目前绝大多数项目的首选。
如果遇到某些涉及大量非主流外文的项目的,可以考虑使用utf8_unicode_ci编码。
utf8_bin由于区分大小写,除非有特殊的要求,一般不建议使用。