在CentOS8中配置JDK13、Tomcat9、MySQL5.6环境

准备和前提

1. 通过fileZilla和服务器建立连接。

连接方法参考:http://www.moonlightgate.com/archives/170

2. 安装JDK

2.1 安装思路。

JDK在Linux下的安装思路和在Windows下的安装思路类似:
A. 安装软件。其实就是上传文件和解压文件。
B. 配置两个环境变量:JAVA_HOME、BIN目录。

2.2 上传、解压、移动。

a. 压缩包jdk-13.0.1_linux-x64_bin.tar.gz上传到/usr/local/tmp目录
b. 解压压缩包

tar zxvf jdk-13.0.1_linux-x64_bin.tar.gz

c. 解压后的目录移动到/usr/local/jdk13

mv jdk-13.0.1 /usr/local/jdk13

2.3 配置环境变量。

vim /etc/profile

在文件中找到export部分,注释export行并增加以下内容:

#export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE HISTCONTROL
export JAVA_HOME=/usr/local/jdk13
export PATH=$JAVA_HOME/bin:$PATH

export的作用是增加新的或修改已经存在的环境变量。
如果是修改已经存在的环境变量,需要注意在环境变量末尾加:$变量名。记住是冒号:(在Windows中是分号;)。

2.4 解析profile文件或重启服务器。

解析命令如下:

source /etc/profile

如果不解析,则配置不生效。

2.5 JDK安装完毕,测试一下。

file

3. 安装Tomcat

3.1 上传、解压、移动

a. 压缩包apache-tomcat-9.0.30.tar.gz上传到/usr/local/tmp目录
b. 解压压缩包

tar zxvf apache-tomcat-9.0.30.tar.gz

c. 解压后的目录移动到/usr/local/apache-tomcat-9

mv apache-tomcat-9.0.30 /usr/local/apache-tomcat-9

3.2 配置环境变量

vim /etc/profile

在文件中找到export部分,在上面的基础上修改为下面内容:

#export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE HISTCONTROL
export JAVA_HOME=/usr/local/jdk13
export PATH=$JAVA_HOME/bin:$PATH

export TOMCAT_HOME=/usr/local/apache-tomcat-9
export CATALINA_HOME=/usr/local/apache-tomcat-9

4.3 解析profile文件或重启服务器。

解析命令如下:

source /etc/profile

如果不解析,则配置不生效。

4.4 Tomcat安装完毕,启动Tomcat。

file
注意:绿色的以.sh结尾的文件,是Linux中的可执行文件。运行.sh文件的命令为
./XXX.sh

4.5 配置防火墙,访问Tomcat。

方法A:直接停掉防火墙

systemctl stop firewalld

方法B:在firewalld里面放行8080端口

运行以下命令:

firewall-cmd --zone=public --add-port=8080/tcp --permanent

这条命令运行完成后,会将8080端口放行的内容添加到 /etc/firewalld/zones/public.xml中:
file
注意:在CentOS7之前的版本中,放行端口号是通过配置iptables完成的。
然后重启防火墙:

firewall-cmd --reload

4.6 大功告成,测试一下

file

4. 安装MySQL

4.1 上传、解压、移动

a. 压缩包mysql-5.6.46-linux-glibc2.12-x86_64.tar.gz上传到/usr/local/tmp目录
b. 解压压缩包

tar zxvf mysql-5.6.46-linux-glibc2.12-x86_64.tar.gz

c. 解压后的目录移动到/usr/local/mysql

mv mysql-5.6.46-linux-glibc2.12-x86_64 /usr/local/mysql

4.2 创建mysql专用用户组和用户,给mysql文件夹赋权

a. 创建用户组(groupadd 用户组名)

groupadd mysql

b. 创建用户(useradd -r用户名称 -g用户组名称)

useradd -r -g mysql mysql

c. 保证命令行当前在/usr/local/mysql中,为mysql目录赋权(注意最后的.前面有个空格)

[root@localhost mysql]# chgrp -R mysql .
[root@localhost mysql]# chown -R mysql .

4.3 注册MySQL服务

a. 确保/etc/my.cnf不存在,如果存在删除。
b. 保证命令行当前在/usr/local/mysql中,执行如下命令初始化数据库。

./scripts/mysql_install_db --user=mysql

运行完成后,会在/usr/local/mysql/support-files下自动生成一个my-default.cnf文件。
c. 复制上面的my-default.cnf文件到/etc/my.cnf

cp my-default.cnf /etc/my.cnf

d. 复制MySQL启动文件到自启动文件夹/etc/rc.d/init.d/下

cp mysql.server /etc/rc.d/init.d/mysql

注:mysql为service名称,其实可以按照个人爱好随便写。

4.4 启动MySQL

service mysql start

此时,如果在命令行里面输入mysql命令,还是无法使用的,原因是mysql命令文件目前位于/usr/local/mysql/bin文件夹下,想要直接在命令行里面使用mysql命令,mysql命令必须出现在/usr/bin/文件夹下。
这时只需要按照如下方法添加软连接即可:

ln -s /usr/local/mysql/bin/mysql /usr/bin/mysql

4.5 使用mysql命令报错解决

使用mysql命令时,可能会报如下错误:

mysql: error while loading shared libraries: libncurses.so.5: cannot open shared object file: No such file or directory

使用如下命令通过yum安装libncurses即可:

yum install libncurses*

4.6 修改MySQL的root用户密码

第一步:进入mysql数据库

use mysql

第二步:更新root用户的密码为111111

update user set  password = password("111111") where User = "root"

第三步:刷新权限使设定生效

flush privileges;

4.7 大功告成,本地测试一下:

file

4.8 配置以可以进行远程连接

截止到4.7,还是只能本机访问的,如果需要远程访问,还需要做如下配置。
第一步:赋予root用户远程连接权限。

grant all privileges on *.* to root@'%' identified by '111111' with grant option;
flush privileges;

第二步:开启3306端口。

firewall-cmd --zone=public --add-port=3306/tcp --permanent
firewall-cmd --reload

这时候,通过MySQL客户端就可以访问MySQL数据库啦。

终于来了!SSM整合!第二个SpringMVC撰写!

第一步:Spring整合MyBatis

请参考:http://www.moonlightgate.com/archives/88

第二步:将SpringMVC整合进入Spring和MyBatis

  1. 修改UserServiceImpl.java
package com.royotech.service.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

@Service
public class UserServiceImpl implements UserService{
    @Autowired
    private PersonDAO personDAO;

    @Override
    public List<Person> select() {
        return personDAO.selectAll();
    }
}
  1. applicationContext.xml头部增加scanner语句。
<context:component-scan base-package="com.royotech.service"></context:component-scan>
  1. web.xml增加filter
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
  1. 撰写controller
package com.royotech.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import com.royotech.entity.Person;
import com.royotech.service.UserService;

@Controller //作用:将当前类的对象交给Spring工厂创建
@RequestMapping("user")   //请求路径
public class UserController {
    @Autowired
    private UserService userService;
    @RequestMapping("select") //请求路径
    public String select(Model model) {
        List<Person> listPerson = userService.select();
        model.addAttribute("listPerson",listPerson);
        return "forward:/list.jsp";
    }
}
  1. 撰写list.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Welcome!</title>
</head>
<body>
    <c:forEach var="person" items="${listPerson}">
        ${person.id},${person.name},${person.birthday},${person.telephone},${person.address}<br/>
    </c:forEach>
</body>
</html>
  1. 大功告成,测试结果如下:
    file

为什么要用SpringMVC?撰写第一个SpringMVC程序

为什么要使用SpringMVC?

SpringMVC作为SSM三剑客中的一个S,其盛行有着以下几方面原因:

  1. Struts2的没落。
    在SSM之前,我们经常说SSH - Struts2、Spring、Hibernate;而现在谈SSM,是指SpringMVC、Spring、MyBatis。SpringMVC是活生生的把Struts2挤下了神坛。Struts2没落的原因有很多,有其重大安全漏洞导致的客户流失,也有框架使用繁琐不适合当代快速开发趋势的原因。
  2. 与Spring的血缘关系。
    SpringMVC与Spring之间有着天然的血缘关系,因此SpringMVC与Spring的结合更紧密,兼容性更好,整合也更容易。
  3. 开发更高效。
    当代程序语言除了“拼性能”外,还要“拼优美”。SpringMVC相较于Struts2而言其程序架构更加优美,开发时代码也更加优美。

说了这么多,还是让我们写一个最简单的SpringMVC程序,看看他的优美之处在哪里?

撰写第一个SpringMVC程序

第一步:添加依赖。

我们依然是基于Maven开发,运行SpringMVC程序的最小依赖如下:

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.2.2.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.2.1.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>5.2.1.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.0.1</version>
    </dependency>

这个不用记忆,固定模式。

第二步:配置web.xml

然后配置下WEB-INF目录下的web.xml,这些内容也不用记忆,也是固定模式。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
    <servlet>
        <servlet-name>mvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:mvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>mvc</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>
</web-app>

第三步:编写Controller

创建Controller包,并在下面建立UserController.java
扫盲一下:
struts和SpringMVC本质上都是对Java Servlet功能的封装和集成。
struts2地址习惯以.action结尾,控制器名字习惯以XxxAction方式命名。
SpringMVC地址习惯以.do结尾,控制器名字习惯以XxxController方式命名。

package com.royotech.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller //作用:将当前类的对象交给Spring工厂创建
@RequestMapping("user")   //请求路径
public class UserController {
    @RequestMapping("select") //请求路径
    public String select() {
        return "forward:/list.jsp"; //forward转发到的位置
    }
}

第四步:配置mvc.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"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <!-- 配置SpringMVC启用注解,哪个包下的内容要使用SpringMVC,就在这里写哪个包的位置 -->
    <context:component-scan base-package="com.royotech.controller"></context:component-scan>
</beans>

第五步:大功告成,测试一下!

新建userController跳转到的list.jsp文件:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Welcome!</title>
</head>
<body>
    Hello!SpringMVC!
</body>
</html>

在浏览器中输入:
http://localhost:8080/JAVA_ALL/user/select.do
注意:

  1. JAVA_ALL是项目名称,区分大小写。
  2. SpringMVC的Controller默认以.do结尾,不加.do访问不到。
    运行结果如下:
    file

第三个Spring程序撰写,整合Spring和MyBatis

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

请参考:http://www.moonlightgate.com/archives/59

搭建Spring开发环境

请参考:http://www.moonlightgate.com/archives/79

第一个Spring程序的撰写,理解SpringIOC

请参考:http://www.moonlightgate.com/archives/81

第二个Spring程序的撰写,理解SpringAOP

请参考:http://www.moonlightgate.com/archives/86

第三个Spring程序的撰写,整合Spring和MyBatis

第一步:添加依赖。

    <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>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.2.2.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>5.2.2.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>2.0.3</version>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.21</version>
    </dependency>

第二步:建表、定义对应的实体类
数据库名:java_all,表名:t_person,表结构如下:
file

在entity包下新建实体类Person

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接口

package com.royotech.dao;

import java.util.List;

import com.royotech.entity.Person;

public interface PersonDAO {
    public List<Person> selectAll();
}

第四步:applicationContext.xml下增加对应的bean标签

    <!-- 1.创建数据源(之前在mybatis-config.xml中配置) -->
    <bean id="ds" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="url" value="jdbc:mysql://localhost:3306/java_all?useUnicode=true&characterEncoding=utf8"></property>
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="username" value="root"></property>
        <property name="password" value="123123"></property>
    </bean>
    <!-- 2.创建SqlSessionFactory对象 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="ds"></property>
        <!-- 相当于mybaits-config.xml中的mapper注册,可以使用通配符* -->
        <property name="mapperLocations" value="classpath:mappers/*Mapper.xml"></property>
        <property name="typeAliasesPackage" value="com.royotech.entity"></property>
    </bean>
    <!-- 3.创建DAO对象 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!-- 提供DAO接口包名,自动创建该包下所有DAO接口的实现类对象 -->
        <!-- DAO类名的首字母小写,就是从工厂中获取该接口对应实现类对象的id -->
        <property name="basePackage" value="com.royotech.dao"></property>
    </bean>

第五步:在view包下建立SelectPersonSpringMyBatis对象

package com.royotech.view;

import java.util.List;

import org.springframework.context.support.ClassPathXmlApplicationContext;

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

public class SelectPersonSpringMyBatis {    
    public static void main(String[] args) throws Exception{
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        PersonDAO personDAO = (PersonDAO)ac.getBean("personDAO");
        List<Person> listPerson = personDAO.selectAll();
        for(Person person : listPerson) {
            System.out.println(person);
        }
    }
}

运行一下,大功告成:
file

程序使用Spring和MyBatis前后的对比

  1. MyBatis用于替换DAO.impl包下的实现类,也就是DAO实现类。替代方法是使用mybatis-config.xml和mapper.xml文件。
  2. Spring和MyBatis整合后,mybatis-config.xml文件也省略了,其中对应的内容被写进了Spring配置文件applicationContext.xml文件中。

第二个Spring程序的撰写,理解SpringAOP

搭建Spring开发环境

有关Spring开发环境的搭建,请参考:http://www.moonlightgate.com/archives/79

撰写第一个Spring程序,理解SpringIOC工厂机制

撰写第二个Spring程序前,需要首先理解SpringIOC机制,请参考:http://www.moonlightgate.com/archives/81

撰写第二个Spring程序

第一步:在Maven的pom.xml中添加AOP依赖,代码如下:

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.5</version>
</dependency>

第二步:确定目标类,编写核心功能(也可以理解为这是当前系统已经有的功能)
service包下新建UserService接口

package com.royotech.service;

public interface UserService {
    public boolean login(String username, String password);
}

service.impl子包下新建UserServiceImpl类,实现UserService接口。

package com.royotech.service.impl;

import com.royotech.service.UserService;

public class UserServiceImpl implements UserService{
    @Override
    public boolean login(String username, String password) {
        System.out.println("我是核心功能:我登陆成功了!我的名字:"+username+",我的密码:"+password);
        return true;
    }
}

第三步:编写新功能类。
在aop包下新建MyAdvice类,作为新功能。

package com.royotech.aop;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class MyAdvice implements MethodInterceptor{

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("我是织入功能:开始统计啦!");
        invocation.proceed();//执行被切入类(目标类)中的既有方法的方法体。
        System.out.println("我是织入功能:统计结束啦!");
        return true;
    }

}

第四步:编写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"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- 1. 配置目标类 -->
    <bean id="userServiceImpl" class="com.royotech.service.impl.UserServiceImpl"></bean>
    <!-- 2. 配置额外功能类 -->
    <bean id="myAdvice" class="com.royotech.aop.MyAdvice"></bean>
    <aop:config>
        <!-- 3. 确定切入点 --> 
        <aop:pointcut id="pcut" expression="execution(boolean com.royotech.service.impl.UserServiceImpl.login(java.lang.String,java.lang.String))"></aop:pointcut>
        <!-- 4. 将额外功能织入切入点 -->
        <aop:advisor advice-ref="myAdvice" pointcut-ref="pcut"/>  
    </aop:config>
</beans>

注意,xml头部需要添加aop相关内容。

第五步:大功告成,测试一下
在view包下新建PersonSpringAOP.java

package com.royotech.view;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.royotech.service.UserService;

public class PersonSpringAOP {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); 
        //这里面用接口,不能用UserServiceImpl类
        //因为本质上讲动态代理自动生成的隐藏对象应该与目标类实现同样的接口
        //因此动态代理对象和目标类不是同类对象,只是继承了相同的方法。
        UserService userService = (UserService)ac.getBean("userServiceImpl");
        userService.login("ROYOTECH", "123123");
    }
}

运行一下,看看结果,欧耶!!!
file

理解为什么使用SpringAOP

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

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

实体类为什么要实现Serializable接口?

疑问

刚刚学习Java的时候,我们学习三层架构,三层架构中的一层就是持久化层,持久化层里面有实体类(Entity)、DAO接口、DAO接口实现类等概念。有关三层架构的理解,请参考:http://www.moonlightgate.com/archives/58
在我们建实体类的时候,往往都要实现Serializable接口,这是为什么呢?

回顾

在学习Java基础的时候,你是肯定接触过Serializable接口的。
一般都是在学习输入、输出流的时候,估计那个时候你也没太搞明白为什么要实现Serializable接口。

解释

Serializable直译过来就是“序列化”。估计听到这个解释就更懵!
经过研究,我将对象需要实现Serializable接口的原因总结如下:
A. Java对象跳出JVM就需要Serializable序列化。
所有在Java中创建的对象都是运行在JVM(Java虚拟机)中的,如果这个对象或者说这个对象的数据要跳出JVM,需要保存到数据库或者文件中的时候,这个对象就需要Serializable序列化。
B. Serializable序列化是JVM内环境和JVM外环境的翻译机。
在JVM内部,对象是以只有JVM能看懂的class文件形式存在的,而class文件在JVM外部是无法被解读的。比如我们随便用记事本打开一个class文件,看到的会是类似下面的这种乱码:
file
Serializable序列化的意思就是将对象以二进制的形式翻译一下,然后保存到JVM外部,因为二进制是计算机都能理解的语言。

总结

总结下,如果一个对象要跳出JVM保存,就需要进行Serializable序列化。
实体类作为和数据库打交道的对象,自然是需要将数据保存到JVM外的数据库上的,所以实体类实现Serializable接口就可以理解了。
但实际上,实体类实现Serializable接口是个约定俗成的事情,即使不继承,也不会影响实体类的运行,因为实体类和数据库打交道最终是通过拼接而成的SQL语句,而非直接将数据序列化传输给数据库。

第一个Spring程序的撰写,理解SpringIOC工厂机制

搭建Spring开发环境

有关Spring开发环境的搭建,请参考:http://www.moonlightgate.com/archives/79

撰写第一个Spring程序

第一步:在entity包下定义Person实体类。

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 + "]";
    }
}

备注:

  1. 实体类的创建可以通过Eclipse自动生成代码的方式快速完成。
  2. 实体类为什么要实现Serializable接口,请参考文章:http://www.moonlightgate.com/archives/83

第二步:在applicationContext.xml文件下的<beans>标签下增加以下<bean>标签,内容如下:

<bean id="person" class="com.royotech.entity.Person">
    <property name="id" value="1"></property>
    <property name="name" value="Leon"></property>
    <property name="birthday" value="1990-01-01"></property>
    <property name="telephone" value="13811811118"></property>
    <property name="address" value="北京市西城区"></property>
</bean>   

添加<bean>标签的意思就是希望项目中的某一个类交由Spring框架去管理,由Spring工厂创建对象。
<bean>标签的id属性:对象创建好后,通过这个id取出来使用。
<bean>标签的class属性:交给Spring工厂创建对象的全类名。
<bean>标签的下的<property>标签:类的属性。

**第三步:在view包下创建PersonSpringIOC类

package com.royotech.view;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.royotech.entity.Person;

public class PersonSpringIOC {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); 
        Person p = (Person)ac.getBean("person");  
        System.out.println(p);
    }
}

运行,输出结果如下:
file

理解为什么使用SpringIOC工厂机制创建对象

不得不说,从这个案例来看,创建一个类变得如此复杂,纯属吃饱了撑的,但是我们换个角度去想:

  • 使用SpringIOC创建对象类似于用乐高建房子,房子建好后拆卸仍然很容易。
  • 而使用传统方法创建对象类似用积木和胶水建房子,房子建好了,想拆开可是非常困难的。

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