1、Maven是什么?
Maven是一个项目管理工具,将项目开发和管理过程抽象成一个项目对象模型(POM)
POM(Project Object Model):项目对象模型
Maven是一个项目管理工具,它包含了一个项目对象模型(Project Object Model),一组标准集合,一个项目生命周期(Project Lifecycle),一个依赖管理系统(Dependency Management System),和用来运行定义在生命周期阶段的(phase)中插件(plugin)目标(goal)的逻辑。当你使用Maven的时候,你用一个明确定义的项目对象模型来描述你的项目,然后Maven可以应用横切的逻辑,这些逻辑来自一组共享的(或者自定义的)插件。
曾经的架构风格—现在:
1.1、Maven能解决什么问题
通俗易懂来说,项目开发在写代码的同时,会伴随着许多必不可少的事情要做,下面我们举几个例子感受一下:
-
我们需要引用各种 jar 包,尤其是比较大的工程,引用的 jar 包往往有几十个乃至上百个, 每用到一种 jar 包,都需要手动引入工程目录,这样会使项目体积过大,不利于传送和管理,而且经常遇到各种让人抓狂的 jar 包冲突,版本冲突。
-
世界上没有不存在bug的代码,为了减少bug,写完代码之后,我们还要写一些单元测试,然后一个个的运行来检查代码质量。
-
再优雅的代码也是要出来卖的。我们后面还需要把代码与各种配置文件、资源整合到一起,定型打包,如果是 web 项目,还需要将之发布到服务器,供人蹂躏。
试想,如果现在有一种工具,可以把你从上面的繁琐工作中解放出来,能帮你构建工程,管理 jar包,编译代码,还能帮你自动运行单元测试,打包,生成报表,甚至能帮你部署项目,生成 Web 站点,你会心动吗?Maven 就可以解决上面所提到的这些问题。
1.2、Maven作用
-
项目搭建:提供标准的、跨平台的自动化项目构建方式
-
依赖管理:方便快捷的管理项目依赖的资源(jar包),避免资源间的版本冲突问题
-
统一开发结构
1.3、Maven的认识
-
Maven可以做到整体的编译和测试
-
快速的打包和部署
好处:自动化,不需要人工再去挨个进行处理和打包,全自动化的过程!
这个全自动化的过程,前提是需要一个文件和对应的生命周期
-
pom.xml
-
生命周期
2、Maven生命周期
2.1、生命周期
Maven有一个声明周期,当你运行 mvn install的时候被调用,这条命令告诉 Maven 执行一系列的有序的步骤,知道到达你指定的生命周期。遍历生命周期旅途中的一个影响就是,Maven运行了很多默认的插件目标,这些目标完成了像编译和创建一个 JAR 文件这样的工作。
-
mvn clean:清理编译的项目
-
mvn compile:编译项目
-
mvn test:测试项目(运行测试类)
-
mvn package:负责将我们的项目打包
-
mvn install:将这个项目安装到本地仓库中
2.2、Clean声明周期(Clean Lifecycle)
当我们执行 mvn post-clean 命令时,Maven 调用 clean 生命周期,它包含以下阶段:
-
pre-clean:执行一些需要在clean之前完成的工作
-
clean:移除所有上一次构建生成的文件
-
post-clean:执行一些需要在clean之后立刻完成的工作
注意:
mvn clean 这个是独立的和它们没有任何关系
mvn clean compile
mvn clean package - - - clean compile test package
2.3、Default 生命周期(Default Lifecycle)
Default Lifecycle是构建的核心部分、编译、测试、打包、部署等,Default生命周期是Maven生命周期中最重要的一个,绝大部分工作发生在这里声明周期中。
一些比较重要和常用的阶段:
-
compile:编译项目的源代码
-
install:将包安装到本地仓库,以让其他开发人员共享
-
deploy:将最终的包复制到远程仓库,以让其他开发人员与项目共享
-
process-test-sources:复制并处理资源文件至测试目录
-
process-resources:处理并复制资源文件,至目标目录,准备打包
-
test-compile:编译测试源代码
-
test:使用合适的单元测试框架进行测试,这些测试代码不会被打包和部署
-
package:接收编译好的代码,打包成可发布的格式,例:jar
所有介绍
生命周期阶段 | 描述 |
---|---|
validate(校验) | 校验项目是否正确并且所有必要的信息可以完成项目的构建过程。 |
initialize(初始化) | 初始化构建状态,比如设置属性值。 |
generate-sources(生成源代码) | 生成包含在编译阶段中的任何源代码。 |
process-sources(处理源代码) | 处理源代码,比如说,过滤任意值。 |
generate-resources(生成资源文件) | 生成将会包含在项目包中的资源文件。 |
process-resources (处理资源文件) | 复制和处理资源到目标目录,为打包阶段最好准备。 |
compile(编译) | 编译项目的源代码。 |
process-classes(处理类文件) | 处理编译生成的文件,比如说对Java class文件做字节码改善优化。 |
generate-test-sources(生成测试源代码) | 生成包含在编译阶段中的任何测试源代码。 |
process-test-sources(处理测试源代码) | 处理测试源代码,比如说,过滤任意值。 |
generate-test-resources(生成测试资源文件) | 为测试创建资源文件。 |
process-test-resources(处理测试资源文件) | 复制和处理测试资源到目标目录。 |
test-compile(编译测试源码) | 编译测试源代码到测试目标目录. |
process-test-classes(处理测试类文件) | 处理测试源码编译生成的文件。 |
test(测试) | 使用合适的单元测试框架运行测试(Juint是其中之一)。 |
prepare-package(准备打包) | 在实际打包之前,执行任何的必要的操作为打包做准备。 |
package(打包) | 将编译后的代码打包成可分发格式的文件,比如JAR、WAR或者EAR文件。 |
pre-integration-test(集成测试前) | 在执行集成测试前进行必要的动作。比如说,搭建需要的环境。 |
integration-test(集成测试) | 处理和部署项目到可以运行集成测试环境中。 |
post-integration-test(集成测试后) | 在执行集成测试完成后进行必要的动作。比如说,清理集成测试环境。 |
verify (验证) | 运行任意的检查来验证项目包有效且达到质量标准。 |
install(安装) | 安装项目包到本地仓库,这样项目包可以用作其他本地项目的依赖。 |
deploy(部署) | 将最终的项目包复制到远程仓库中与其他开发者和项目共享。 |
2.4、Site 生命周期(Site Lifecycle)
Site Lifecycle 生成项目报告,站点,发布站点,站点的文章(站点信息,依赖),Site生命周期,生成站点信息四个阶段:
-
pre-site:执行一些需要在生成站点文档之前完成的工作
-
site:生成项目的站点文档
-
post-site: 执行一些需要在生成站点文档之后完成的工作,并且为部署做准备
-
site-deploy:将生成的站点文档部署到特定的服务器上
如果你要进行配置插件,参考菜鸟官网:https://www.runoob.com/maven/maven-build-life-cycle.html
3、Maven下载与安装
统一使用版本:maven 3.6.3
3.1、下载和官网
-
官网:https://maven.apache.org/
-
下载地址:https://maven.apache.org/download.cgi
如果你要下载旧版本,请参考如下进行寻找:
1、打开Download页面之后进入这里
2、选择自己需要的版本!
3、选择二进制或者源码下载方式!
4、下载!
3.3、Maven安装
Maven属于绿色出版软件,解压即安装
3.2、Maven环境变量配置
为什么要配置环境变量?
-
使用Java,需要配置JAVA_HOME
-
设置MAVEN自身的运行环境,需要配置MAVEN_HOME
-
测试环境配置结果 MVN
-
不论是配置什么环境变量,他们都有一个好处就是:可以在任意,目录下执行和编译对应的文件。
mac 配置MAVEN_HOME
1、首先打开terminal
2、输入:vim ~/.bash_profile
3、按 i 或 a 进入编辑模式
4、输入你的配置
export MAVEN_HOME=/usr/local/apache-maven-3.6.3
export PATH=$PATH:$MAVEN_HOME/bin
5、保存,按ESC,输入英文 : ,输入wq,按下回车
6、输入source ~/.bash_profile使配置文件生效
7、输入mvn -v查看是否配置成功,显示版本号等相关信息说明配置成功,如果没有改变那就重新打开终端!
为什么要配置JAVA_HOME?
原因是:未来在你的电脑上运行java产品比如:你自己开发的SSM、springboot、微服务的。也可以运行tomcat、zk、kafka、es、maven,因为他们都是java产品,只要是java开发的产品,就一定要读取 jdk 的目录调用目录中的java 和javac目录,才能把项目部署和运行到内存中。
为什么要配置MAVEN_HOME?
与git一样,您未来在idea中或者eclipse中执行的界面命令都在执行底层maven命令,也就是 mvn 指令。比如idea你在执行其实是通过在idea设置的maven进行编译和打包的,那么idea中配置的maven与环境变量中配置的maven有没有关系?没有,那么为什么要配置环境变量呢?让你有一个新的选择,可以通过命令行,从而达到和idea图形化界面一样的效果。
配置MAVEN_HOME:其实就是告诉你,你可以通过命令去打包和编译你的项目,可以不用idea的maven设置。但是在开发中我们建议就是配置上,还是图像界面会方便一点。
macdeMacBook-Pro:~ mac$ mvn -version
Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f)
Maven home: /usr/local/apache-maven-3.6.3
Java version: 1.8.0_331, vendor: Oracle Corporation, runtime: /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home
Default locale: zh_CN, platform encoding: UTF-8
OS name: "mac os x", version: "11.6.7", arch: "x86_64", family: "mac"
System.getProperties("JAVA_HOME");
4、Maven仓库和坐标
4.1、仓库
仓库:就和我们家里的房间或者谷仓一样的概念,用于存储粮食或者物品。那么maven的仓库用来存储什么呢?答案是:存储我们项目依赖的各种jar包。
推荐的远程仓库地址:https://mvnrepository.com/
4.2、仓库分类
仓库分为两种:本地仓库和远程仓库,而远程仓库分为私服和中央仓库。
-
远程仓库:顾名思义,是一个云端的仓库,本地仓库的所有资源都需要从远程仓库中下载。远程仓库又可以细分为私服与中央仓库。
-
私服:作用相当于缓存,若所有的开发者都直接从中央仓库获取资源,必定造成网络阻塞,而私服就相当于缓存。私服先从中央仓库中获取所需资源,提供给本地仓库下载,一些不开源的资源也存于私服中,目的在于实现小范围的共享(内部使用)。
-
中央仓库:收录了几乎世界上所有的jar包,本地仓库下载资源。
4.3、私服的作用
-
保存具有版权的资源,包含购买或自主研发的jar
-
中央仓库中的jar都是开源的,不能存储具有版权的资源
-
一定范围内共享资源,仅对内部开放,不对外共享
4.4、配置远程仓库及阿里云镜像
在maven的安装目录下的conf/setting.xml进行如下配置:
-
把localRepository配置打开,指定你自己的本地仓库的位置
/usr/local/repository
-
配置阿里云的镜像仓库地址
alimaven
aliyun maven
http://maven.aliyun.com/nexus/content/groups/public/
central
nexus-aliyun
*,!jeecg,!jeecg-snapshots
Nexus aliyun
http://maven.aliyun.com/nexus/content/groups/public
配置JDK环境
jdk-1.8
true
1.8
1.8
1.8
1.8
5、Maven 坐标
Maven 坐标为各种构件引入了秩序,任何一个构件都必须明确定义自己的坐标,而一组Maven坐标是通过一些元素定义的,他们是groupId、artifactId、version、packaging、classifier。先看一组坐标定义,如下:
org.sonatype.nexus
nexus-indexer
2.0.0
jar
这是nexus-indexer的坐标定义,nexus-indexer是一个对Maven仓库编篡索引并提供搜索的类库,他是Nexus项目的一个子模块。上述代码片段中,其坐标分别为groupId:org.sonatype.nexus、artifactId:nexus-indexer、version:2.0.0.、packaging:jar,没有classifier。下面详细解释一下各个坐标元素。
groupId
定义当前Maven项目隶属的实际项目。首先,Maven项目和实际项目不一定是一对一的关系。比如SpringFramework这一实际项目,其对应的Maven项目会有很多,如spring-core、spring-context等。这是由于Maven中模块的概念,因此,一个实际项目往往会被划分成很多模块。其次,groupId不应该对应项目隶属的组织或公司。原因很简单,一个组织下会有很多实际项目,如果groupId只定义到组织级别,而后面我们会看到,artifactId只能定义Maven项目(模块),那么实际项目这个层将难以定义。最后,groupId的表示方式与Java包名的表示方法类似,通常与域名反向一一对应。上例中,groupId为org.sonatype.nexus,org.sonatype表示Sonatype公司建立的一个非营利性组织,nexus表示Nexus这一实际项目,该groupId与域名nexus.sonatype.org对应。
artifactId
该元素定义实际项目中的一个Maven项目(模块),推荐的做法是使用实际项目名称作为artifactId的前缀。比如上例中的artifactId是nexus-indexer,使用了实际项目名nexus作为前缀,这样做的好处是方便寻找实际构件。在默认情况下,Maven生成的构件,其文件名会以artifactId作为开头,如nexus-indexer-2.0.0.jar,使用实际项目名称作为前缀之后,就能方便从一个lib文件夹中找到某个项目的一组构件。考虑有5个项目,每个项目都有一个core模块,如果没有前缀,我们会看到很多core-1.2.jar这样的文件,加上实际项目名前缀之后,便能很容易区分foo-core-1.2.jar、bar-core-1.2.jar......
version
该元素定义Maven项目当前所处的版本,如上例中nexus-indexer的版本是2.0.0。需要注意的是,Maven定义了一套完成的版本规范,以及快照(SNAPSHOT)的概念。
packaging
该元素定义Maven项目的打包方式。首先,打包方式通常与所生成构件的文件扩展名对应,如上例中packaging为jar,最终的文件名为nexus-indexer-2.0.0.jar,而使用war打包方式的Maven项目,最终生成的构件会有一个.war文件,不过这不是绝对的。其次,打包方式会影响到构建的生命周期,比如jar打包和war打包会使用不同的命令。最后,当不定义packaging的时候,Maven会使用默认值jar。
classifier
该元素用来帮助定义构建输出的一些附属构建。附属构件与主构件对应,如上例中的主构件是nexus-indexer-2.0.0.jar,该项目可能还会通过使用一些插件生成如nexus-indexer-2.0.0-javadoc.jar、nexus-indexer-2.0.0-sources.jar这样一些附属构建,其包含了Java文档和源代码。这时候,javadoc和sources就是这两个附属构建的classifier。这样,附属构建也就拥有了自己唯一的坐标。还有一个关于classifier的典型例子是TestNG,TestNG的主构件是基于Java1.4平台的,而他又提供了一个classifier为jdk5的附属构件。注意,不能直接定义项目的classifier,因为附属构建不是项目直接默认生成地,而是由附加的插件帮助生成。
上述5个元素中,groupId、artifactId、version是必须定义的,packaging是可选的(默认为jar),而classifier是不能直接定义的。
同时,项目构建的文件名和坐标相对应的,一般的规则为artifactId-version [-classifier] .packaging,[-classifier]表示可选。比如上例nexus-indexer的主构件为nexus-indexer-2.0.0.jar,附属构建有nexus-indexer-2.0.0-javaodc.jar。这里还要强调一点是,packaging 并非一定与构件扩展名对应,比如packaging为maven-plugin的构件扩展名为jar。
此外,Maven仓库的布局也是基于Maven坐标。
6、Maven在idea中的创建和整合
-
安装依赖插件
安装成功如下所示:
后续就可以在这里进行jar包相关的依赖和搜索,非常的方便
-
配置本地 maven
-
在idea中手动创建maven项目
-
原始创建Maven项目
-
Tomcat7 插件
org.apache.tomcat.maven
tomcat7-maven-plugin
2.2
80
/
true
UTF-8
Maven中使用tomcat8 插件,参考:https://blog.csdn.net/qq_39230153/article/details/122286262
Maven插件,官网地址:https://maven.apache.org/plugins/index.html
7、idea搭建一个SSM项目
1、先构建一个maven的webapp项目
2、导入相关依赖
-
spring依赖
-
mybatis依赖
-
MYSQL依赖
-
Druid依赖
-
Jackjson依赖
-
pagehelper依赖
-
junit依赖
-
…..
3、在resources下新建springmvc.xml文件
4、在web.xml中配置springmvc的servlet
5、在resources目录下新建applicationContent.xml整合mybatis项目的service
6、在resources目录下新建jdbc.properties管理数据连接信息
7、在src目录下新建对应的domain,service,controller,dao,完成用户相关业务的查询和工作
8、定义Mapper.xml文件在resources下,对用户表进行管理
9、发布和部署项目
整体架构如下:
1、创建一个maven项目
pom.xml如下所示:
4.0.0
com.yykk
maven-web
1.0-SNAPSHOT
war
maven-web Maven Webapp
UTF-8
1.8
1.8
junit
junit
4.11
test
org.springframework
spring-webmvc
5.3.20
org.mybatis
mybatis-spring
2.0.7
com.alibaba
druid
1.2.11
mysql
mysql-connector-java
8.0.27
com.fasterxml.jackson.core
jackson-databind
2.13.3
org.mybatis
mybatis
3.2.1
com.github.pagehelper
pagehelper
5.3.0
org.springframework
spring-test
5.3.20
javax.servlet
javax.servlet-api
4.0.1
org.springframework
spring-jdbc
5.3.20
maven-web
maven-clean-plugin
3.1.0
maven-resources-plugin
3.0.2
maven-compiler-plugin
3.8.0
maven-surefire-plugin
2.22.1
maven-war-plugin
3.2.2
maven-install-plugin
2.5.2
maven-deploy-plugin
2.8.2
org.apache.tomcat.maven
tomcat7-maven-plugin
2.2
80
/
true
UTF-8
2、新建jdbc.properties
新建一个数据库:ssm_db,新建一个表
kss_user.sql
CREATE TABLE `kss_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) DEFAULT NULL,
`password` varchar(255) DEFAULT NULL,
`realName` varchar(255) DEFAULT NULL,
`gender` int DEFAULT NULL,
`birthday` date DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4
新建jdbc.properties
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm_db?serverTimezone-GMT%2b8&useUnicode=true&characterEncoding=UTF-8&useSSL=false
jdbc.username=root
jdbc.password=123456
3、spring整合mybatis
新建applicationContext.xml
mysql
true
4、整合springmvc
在resources目录下新建一个spring-mvc.xml文件即可!
5、在web.xml配置springmvc的核心servlet
web.xml
contextConfigLocation
classpath*:applicationContext.xml
org.springframework.web.context.ContextLoaderListener
encodingFilter
org.springframework.web.filter.CharacterEncodingFilter
encoding
utf-8
encodingFilter
/*
15
DispatcherServlet
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath*:spring-mvc.xml
1
DispatcherServlet
/
6、建立用户相关的业务!SSM整合
User.java
package com.yykk.domain;
import java.io.Serializable;
import java.util.Date;
public class User implements Serializable {
private Integer id;
private String username;
private String password;
private String realName;
private Integer gender;
private Date birthday;
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", realName='" + realName + '\'' +
", gender=" + gender +
", birthday=" + birthday +
'}';
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getRealName() {
return realName;
}
public void setRealName(String realName) {
this.realName = realName;
}
public Integer getGender() {
return gender;
}
public void setGender(Integer gender) {
this.gender = gender;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public User(Integer id, String username, String password, String realName, Integer gender, Date birthday) {
this.id = id;
this.username = username;
this.password = password;
this.realName = realName;
this.gender = gender;
this.birthday = birthday;
}
public User() {
}
}
UserDao
package com.yykk.dao;
import com.yykk.domain.User;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface UserDao {
/**
* 添加用户
* @param user
* @return
*/
public boolean save(User user);
/**
* 修改用户
* @param user
* @return
*/
public boolean update(User user);
/**
* 删除用户
* @param id
* @return
*/
public boolean delete(Integer id);
/**
* 查询单个用户信息
* @param id
* @return
*/
public User get(Integer id);
/**
* 查询全部用户信息
* @return
*/
public List getAll();
/**
* 根据用户名或者密码查询个人信息
* @param userName 用户名
* @param password 密码信息
* @return
*/
// 注意:数据层操作不要和业务层操作的名称混淆,通常数据层只反映与数据库的信息交换,不体现业务逻辑!
public User getByUserNameAndPassword(@Param("userName")String userName,@Param("password")String password);
}
UserDao.xml
在resources目录下新建一个com.yykk.dao的目录新建UserDao.xml文件,如下:
insert into ssmbuild.books(bookName,bookCounts,detail)
values (#{bookName}, #{bookCounts}, #{detail})
delete from ssmbuild.books where bookID=#{bookID}
update ssmbuild.books
set bookName = #{bookName},bookCounts = #{bookCounts},detail = #{detail}
where bookID = #{bookID}
UserService
package com.yykk.service;
import com.github.pagehelper.PageInfo;
import com.yykk.domain.User;
import org.apache.ibatis.annotations.Param;
import org.springframework.transaction.annotation.Transactional;
@Transactional(readOnly = true)
public interface UserService {
/**
* 添加用户
* @param user
* @return
*/
@Transactional(readOnly = false)
public boolean save(User user);
/**
* 修改用户
* @param user
* @return
*/
@Transactional(readOnly = false)
public boolean update(User user);
/**
* 删除用户
* @param id
* @return
*/
@Transactional(readOnly = false)
public boolean delete(Integer id);
/**
* 查询单个用户信息
* @param id
* @return
*/
public User get(Integer id);
/**
* 查询全部用户信息
* @return
*/
public PageInfo getAll(int page,int size);
/**
* 根据用户名或者密码查询个人信息
* @param userName 用户名
* @param password 密码信息
* @return
*/
public User login(@Param("userName")String userName, @Param("password")String password);
}
UserServiceImpl
package com.yykk.service.impl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.yykk.dao.UserDao;
import com.yykk.domain.User;
import com.yykk.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
public boolean save(User user) {
return userDao.save(user);
}
@Override
public boolean update(User user) {
return userDao.update(user);
}
@Override
public boolean delete(Integer id) {
return userDao.delete(id);
}
@Override
public User get(Integer id) {
return userDao.get(id);
}
@Override
public PageInfo getAll(int page, int size) {
PageHelper.startPage(page,size);
List all = userDao.getAll();
return new PageInfo(all);
}
@Override
public User login(String userName, String password) {
return userDao.getByUserNameAndPassword(userName,password);
}
}
UserController
package com.yykk.controller;
import com.github.pagehelper.PageInfo;
import com.yykk.config.exception.BusinessException;
import com.yykk.config.results.Code;
import com.yykk.config.results.Result;
import com.yykk.domain.User;
import com.yykk.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@PostMapping
public Result save(User user){
boolean flag = userService.save(user);
return new Result(flag ? Code.SAVE_OK:Code.SAVE_ERROR);
}
@PutMapping
public Result update(User user){
boolean flag = userService.update(user);
return new Result(flag ? Code.UPDATE_OK:Code.UPDATE_ERROR);
}
@DeleteMapping("/{id}")
public Result delete(Integer id){
boolean flag = userService.delete(id);
return new Result(flag ? Code.DELETE_OK:Code.DELETE_ERROR);
}
@GetMapping("/{id}")
public Result get(@PathVariable("id")Integer id) throws BusinessException {
User user = userService.get(id);
// 模拟出现异常,使用条件控制,便于测试结果
if (id == 10) {
throw new BusinessException("查询出错了,请重试!",Code.GET_ERROR);
}
return new Result(null != user ? Code.GET_OK :Code.GET_ERROR,user);
}
@GetMapping("/{page}/{size}")
public Result getAll(@PathVariable Integer page,@PathVariable Integer size){
PageInfo all = userService.getAll(page, size);
return new Result(null != all ? Code.GET_OK :Code.GET_ERROR,all);
}
@PostMapping("/login")
public Result login(String username,String password){
User user = userService.login(username,password);
return new Result(null != user ? Code.GET_OK :Code.GET_ERROR,user);
}
}
Config配置类
config/exception/BusinessException.java
统一异常的处理
package com.yykk.config.exception;
public class BusinessException extends RuntimeException {
// 自定义异常中封装对应的错误编码,用于处理异常时获取对应的操作编码
private Integer code;
public BusinessException(Integer code) {
this.code = code;
}
public BusinessException(String message, Integer code) {
super(message);
this.code = code;
}
public BusinessException(String message, Throwable cause, Integer code) {
super(message, cause);
this.code = code;
}
public BusinessException(Throwable cause, Integer code) {
super(cause);
this.code = code;
}
public BusinessException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Integer code) {
super(message, cause, enableSuppression, writableStackTrace);
this.code = code;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
}
config/interceptor/ProjectExceptionAdvice
package com.yykk.config.interceptor;
import com.yykk.config.exception.BusinessException;
import com.yykk.config.results.Result;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
@Component
@ControllerAdvice
public class ProjectExceptionAdvice {
@ExceptionHandler(BusinessException.class)
@ResponseBody
// 对出现异常的情况进行拦截,并将其处理成统一的页面数据结果格式
public Result doBusinessException(BusinessException e) {
return new Result(e.getCode(),e.getMessage());
}
}
config/Code
package com.yykk.config.results;
public class Code {
// 操作结果编码
public static final Integer SAVE_OK = 20011;
public static final Integer UPDATE_OK = 20021;
public static final Integer DELETE_OK = 20031;
public static final Integer GET_OK = 20041;
public static final Integer SAVE_ERROR = 20010;
public static final Integer UPDATE_ERROR = 20020;
public static final Integer DELETE_ERROR = 20030;
public static final Integer GET_ERROR = 20040;
}
config/Result
package com.yykk.config.results;
public class Result {
// 操作结果编码
private Integer code;
// 操作数据结果
private Object data;
// 消息
private String message;
public Result(Integer code, Object data) {
this.code = code;
this.data = data;
}
public Result(Integer code) {
this.code = code;
}
@Override
public String toString() {
return "Result{" +
"code=" + code +
", data=" + data +
", message='" + message + '\'' +
'}';
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
对于dependencyManagement 与 depencies区别就是如果你选择了前者他不会为你下载依赖,按需导入,后者会为你全部子模块添加一遍!前者可以做版本控制管理!在pom.xml中这两者可以同时存在,然后第一个做版本管理,第二个导入每个模块会用到的依赖!
7、SSM模块化开发:
因为在我们的开发中有很多问题,例如我们很多的模块都是一样的代码,但是我们开发不同的东西都要重新编写或者复制,对于这种重复的事情相信你们也会也厌烦,所以进行了模块化开发,如下图所示!
1、搭建父项目工程
在这里要注意一定要建立一个maven空项目!
-
pug-ssm-parent
src目录要删掉,因为这里只是用来管理以下子模块的开发,配置pom.xml!
4.0.0
com.yykk
pug-ssm-parent
1.0-SNAPSHOT
pug-ssm-pojo
pug-ssm-dao
pug-ssm-service
pug-ssm-config
pug-ssm-webpc
pom
8
8
org.springframework
spring-webmvc
5.3.20
com.alibaba
druid
1.2.11
mysql
mysql-connector-java
8.0.27
com.fasterxml.jackson.core
jackson-databind
2.13.3
org.mybatis
mybatis
3.5.4
org.mybatis
mybatis-spring
2.0.2
com.github.pagehelper
pagehelper
5.3.0
org.springframework
spring-test
5.3.20
javax.servlet
javax.servlet-api
4.0.1
org.springframework
spring-jdbc
5.3.20
junit
junit
4.11
test
org.apache.tomcat.maven
tomcat7-maven-plugin
2.2
80
/
true
UTF-8
2、搭建子项目!(对于子模块中所有的依赖不要导入版本,因为父项目进行了整体的依赖聚合!)
-
pug-ssm-pojo
pom.xml
pug-ssm-parent
com.yykk
1.0-SNAPSHOT
4.0.0
pug-ssm-pojo
8
8
domain/User
package com.yykk.domain;
import java.io.Serializable;
import java.util.Date;
public class User implements Serializable {
private Integer id;
private String username;
private String password;
private String realName;
private Integer gender;
private Date birthday;
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", realName='" + realName + '\'' +
", gender=" + gender +
", birthday=" + birthday +
'}';
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getRealName() {
return realName;
}
public void setRealName(String realName) {
this.realName = realName;
}
public Integer getGender() {
return gender;
}
public void setGender(Integer gender) {
this.gender = gender;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public User(Integer id, String username, String password, String realName, Integer gender, Date birthday) {
this.id = id;
this.username = username;
this.password = password;
this.realName = realName;
this.gender = gender;
this.birthday = birthday;
}
public User() {
}
}
-
pug-ssm-dao
pom.xml
pug-ssm-parent
com.yykk
1.0-SNAPSHOT
4.0.0
pug-ssm-dao
com.yykk
pug-ssm-pojo
1.0-SNAPSHOT
org.mybatis
mybatis
org.mybatis
mybatis-spring
com.github.pagehelper
pagehelper
8
8
dao/UserDao
package com.yykk.dao;
import com.yykk.domain.User;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface UserDao {
/**
* 添加用户
* @param user
* @return
*/
public boolean save(User user);
/**
* 修改用户
* @param user
* @return
*/
public boolean update(User user);
/**
* 删除用户
* @param id
* @return
*/
public boolean delete(Integer id);
/**
* 查询单个用户信息
* @param id
* @return
*/
public User get(Integer id);
/**
* 查询全部用户信息
* @return
*/
public List getAll();
/**
* 根据用户名或者密码查询个人信息
* @param userName 用户名
* @param password 密码信息
* @return
*/
// 注意:数据层操作不要和业务层操作的名称混淆,通常数据层只反映与数据库的信息交换,不体现业务逻辑!
public User getByUserNameAndPassword(@Param("userName")String userName,@Param("password")String password);
}
-
pug-ssm-service
pom.xml
pug-ssm-parent
com.yykk
1.0-SNAPSHOT
4.0.0
pug-ssm-service
8
8
com.yykk
pug-ssm-dao
1.0-SNAPSHOT
com.yykk
pug-ssm-config
1.0-SNAPSHOT
service/UserService 以及 UserServiceImpl
package com.yykk.service;
import com.github.pagehelper.PageInfo;
import com.yykk.domain.User;
import org.apache.ibatis.annotations.Param;
import org.springframework.transaction.annotation.Transactional;
@Transactional(readOnly = true)
public interface UserService {
/**
* 添加用户
* @param user
* @return
*/
@Transactional(readOnly = false)
public boolean save(User user);
/**
* 修改用户
* @param user
* @return
*/
@Transactional(readOnly = false)
public boolean update(User user);
/**
* 删除用户
* @param id
* @return
*/
@Transactional(readOnly = false)
public boolean delete(Integer id);
/**
* 查询单个用户信息
* @param id
* @return
*/
public User get(Integer id);
/**
* 查询全部用户信息
* @return
*/
public PageInfo getAll(int page,int size);
/**
* 根据用户名或者密码查询个人信息
* @param userName 用户名
* @param password 密码信息
* @return
*/
public User login(@Param("userName")String userName, @Param("password")String password);
}
package com.yykk.service.impl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.yykk.dao.UserDao;
import com.yykk.domain.User;
import com.yykk.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
public boolean save(User user) {
return userDao.save(user);
}
@Override
public boolean update(User user) {
return userDao.update(user);
}
@Override
public boolean delete(Integer id) {
return userDao.delete(id);
}
@Override
public User get(Integer id) {
return userDao.get(id);
}
@Override
public PageInfo getAll(int page, int size) {
PageHelper.startPage(page,size);
List all = userDao.getAll();
return new PageInfo(all);
}
@Override
public User login(String userName, String password) {
return userDao.getByUserNameAndPassword(userName,password);
}
}
-
pug-ssm-config
pom.xml
pug-ssm-parent
com.yykk
1.0-SNAPSHOT
4.0.0
pug-ssm-config
8
8
org.springframework
spring-webmvc
com.fasterxml.jackson.core
jackson-databind
org.springframework
spring-test
org.springframework
spring-jdbc
javax.servlet
javax.servlet-api
config/exception
package com.yykk.config.exception;
public class BusinessException extends RuntimeException {
// 自定义异常中封装对应的错误编码,用于处理异常时获取对应的操作编码
private Integer code;
public BusinessException(Integer code) {
this.code = code;
}
public BusinessException(String message, Integer code) {
super(message);
this.code = code;
}
public BusinessException(String message, Throwable cause, Integer code) {
super(message, cause);
this.code = code;
}
public BusinessException(Throwable cause, Integer code) {
super(cause);
this.code = code;
}
public BusinessException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, Integer code) {
super(message, cause, enableSuppression, writableStackTrace);
this.code = code;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
}
config/interceptor
package com.yykk.config.interceptor;
import com.yykk.config.exception.BusinessException;
import com.yykk.config.results.Result;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
@Component
@ControllerAdvice
public class ProjectExceptionAdvice {
@ExceptionHandler(BusinessException.class)
@ResponseBody
// 对出现异常的情况进行拦截,并将其处理成统一的页面数据结果格式
public Result doBusinessException(BusinessException e) {
return new Result(e.getCode(),e.getMessage());
}
}
config/results/Code
package com.yykk.config.results;
public class Code {
// 操作结果编码
public static final Integer SAVE_OK = 20011;
public static final Integer UPDATE_OK = 20021;
public static final Integer DELETE_OK = 20031;
public static final Integer GET_OK = 20041;
public static final Integer SAVE_ERROR = 20010;
public static final Integer UPDATE_ERROR = 20020;
public static final Integer DELETE_ERROR = 20030;
public static final Integer GET_ERROR = 20040;
}
config/results/Result
package com.yykk.config.results;
public class Result {
// 操作结果编码
private Integer code;
// 操作数据结果
private Object data;
// 消息
private String message;
public Result(Integer code, Object data) {
this.code = code;
this.data = data;
}
public Result(Integer code) {
this.code = code;
}
@Override
public String toString() {
return "Result{" +
"code=" + code +
", data=" + data +
", message='" + message + '\'' +
'}';
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
3、以上就对模块进行了拆分,对于我们具体的业务而言,我们需要建立一个webapp的模块进行开发!
-
pug-ssm-webpc
在这里进行数据库的依赖导入是为了后期开发其他可以随意切换数据源!
pug-ssm-parent
com.yykk
1.0-SNAPSHOT
4.0.0
pug-ssm-webpc
war
pug-ssm-webpc Maven Webapp
http://www.example.com
UTF-8
1.7
1.7
com.yykk
pug-ssm-service
1.0-SNAPSHOT
com.alibaba
druid
mysql
mysql-connector-java
pug-ssm-webpc
maven-clean-plugin
3.1.0
maven-resources-plugin
3.0.2
maven-compiler-plugin
3.8.0
maven-surefire-plugin
2.22.1
maven-war-plugin
3.2.2
maven-install-plugin
2.5.2
maven-deploy-plugin
2.8.2
controller/UserController
package com.yykk.controller;
import com.github.pagehelper.PageInfo;
import com.yykk.config.exception.BusinessException;
import com.yykk.config.results.Code;
import com.yykk.config.results.Result;
import com.yykk.domain.User;
import com.yykk.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@PostMapping
public Result save(User user){
boolean flag = userService.save(user);
return new Result(flag ? Code.SAVE_OK:Code.SAVE_ERROR);
}
@PutMapping
public Result update(User user){
boolean flag = userService.update(user);
return new Result(flag ? Code.UPDATE_OK:Code.UPDATE_ERROR);
}
@DeleteMapping("/{id}")
public Result delete(Integer id){
boolean flag = userService.delete(id);
return new Result(flag ? Code.DELETE_OK:Code.DELETE_ERROR);
}
@GetMapping("/{id}")
public Result get(@PathVariable("id")Integer id) throws BusinessException {
User user = userService.get(id);
// 模拟出现异常,使用条件控制,便于测试结果
if (id == 10) {
throw new BusinessException("查询出错了,请重试!",Code.GET_ERROR);
}
return new Result(null != user ? Code.GET_OK :Code.GET_ERROR,user);
}
@GetMapping("/{page}/{size}")
public Result getAll(@PathVariable Integer page,@PathVariable Integer size){
PageInfo all = userService.getAll(page, size);
return new Result(null != all ? Code.GET_OK :Code.GET_ERROR,all);
}
@PostMapping("/login")
public Result login(String username,String password){
User user = userService.login(username,password);
return new Result(null != user ? Code.GET_OK :Code.GET_ERROR,user);
}
}
web.xml
contextConfigLocation
classpath*:applicationContext.xml
org.springframework.web.context.ContextLoaderListener
encodingFilter
org.springframework.web.filter.CharacterEncodingFilter
encoding
utf-8
encodingFilter
/*
15
DispatcherServlet
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath*:spring-mvc.xml
1
DispatcherServlet
/
jdbc.properties
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm_db?serverTimezone-GMT%2b8&useUnicode=true&characterEncoding=UTF-8&useSSL=false
jdbc.username=root
jdbc.password=123456
applicationContext.xml
mysql
true
spring-mvc.xml
以及业务代码com.yykk.dao/UserDao.xml
insert into ssm_db.kss_user(username, password, realName, gender, birthday)
VALUES (#{userName},#{password},#{realName},#{gender},#{birthday})
delete
from ssm_db.kss_user where id = #{id};
update ssm_db.kss_user set
username = #{userName},password = #{password},realName = #{realName},gender = #{gender},birthday = #{birthday}
where id = #{id}
以上就是对模块化开发的全部整合内容,然后就可以尝试tomcat进行测试了,虽然配置了tomcat7 插件但是可能会因为部分原因不能进行使用,根据自己情况进行处理!
如果你勾选了这个小闪电,会让你打包的时候跳过test,提升速度!
对于打包,你的pom.xml中如果有filename你可以自定义名字,就是你打包成功后的war/jar,如果不写就是你的 artifactId+version !
8、Maven私服仓库的搭建
01、概述
在实际的开发和场景中,我们大部分情况都是协同开发,我们之前使用maven可以高效的管理我们的项目,可以把项目中的jar包,可以很快速的通过坐标然后通过网络从远程仓库或者阿里云仓库的中把对应的jar包下载到本地仓库中。就好比下载电影一样, 在线看太慢了,下载到本地电脑慢慢欣赏一样的道理。
而在企业中,我们所需的注解只能够通过第三方的maven仓库远程下载到本地,下载速度相对比较慢,耗时很长,不利于管理。其实最快的方式就是在一个 局域网或 者用U盘拷贝和文件传输即可。到时候U盘拷贝和文件传输还需要用户自己手动的去添加到本地仓库,就有点麻烦。所以大部分情况下:公司在建设项目之初就会在公司内部搭建一个maven的私服 仓库nexus。进行本地仓库和远程仓库的链接和下载工作。从而服务团队的协作以及高效的下载和管理组件jar包。
02、具体步骤
1、首先下载nexus
https://help.sonatype.com/repomanager3/product-information/download
在这里我们进行下载可能会遇到的一些问题:
-
页面下载可能打不开
-
可以试试复制链接在迅雷或者其他软件进行下载(因为可能会网络卡加载不出来)
-
最后就是针对mac用户的一些问题:如果你复制了链接但是打开无法下载,大小显示0kb,那么解决方案是可以试试将你的版本更改一下,亲测有效!
2、然后解压即可
3、配置环境变量
为什么在开发中我们都要把很多软件去配置环境变量,一个原因:
方便你在任何命令行可以找到你的应用程序,就不要你在进入到执行目录下找文件启动。
-
配置环境变量
-
首先编辑这个文件
vim ~/.bash_profile
-
然后增加下面一行配置
export PATH=${PATH}:/usr/local/nexus-3.38.1-01-mac/nexus-3.38.1-01/bin
如下所示:
-
然后保存并退出,输入命令
:wq
-
输入
source ~/.bash_profile
让文件立即生效!
-
启动nexus,如果不了解命令的话可以输入nexus查看提示!
-
启动后,nexus默认监听端口是8081
如果如上所示就启动成功了。默认监听端口是8081,如果你想要更改可以通过 /usr/local/nexus-3.38.1-01-mac/nexus-3.38.1-01/etc
目录下的 nexus-default.properties
配置文件进行修改如下:
切记不是本机的etc目录
4、运行nexus的方式(.exe 可以不加)
-
前台运行:nexus start | nexus.exe /run (前者是mac,后者是win)
-
后台运行:(推荐)
-
安装nexus服务:管理员身份运行:cms- ->运行nexus.exe /install
-
卸载nexus服务:管理员身份运行:cms- ->运行nexus.exe /uninstall
-
启动nexus服务:管理员身份运行:cms- ->运行nexus.exe /start
-
停止nexus服务:管理员身份运行:cms- ->运行nexus.exe /stop
-
查看nexus服务:管理员身份运行:cms- ->运行nexus.exe /status
-
-
注意:后台运行这种方式,nexus服务只需要启动一次,后续会随着系统的启动而启动,无须每次都运行启动命令。
5、访问
在浏览器输入
http://127.0.0.1:8081/nexus或者http://localhost:8081/nexus
出现下面这个界面,没关系,点击nexus repo..图标,跳转到下一个界面。
03、登录关于密码问题
在我们的安装完成之后会有两个文件打开我们的 sonatype-work
打开目录:
sonatype/nexus3/admin.password
默认密码文件,修改一次密码之后会自动删除,默认账号为admin,打开密码文件,然后登录即可!
进入以后会让你修改密码。建议改成简单一点的密码即可。一旦修改目录的密码文件会自动删除掉!
现在让所有用户可以访问,不需要账户密码访问,如下:
接下来就可以看到nexus的配置了。选择左侧的Browse如下:
就可以看到对应的远程仓库,接下来就是如何将nexus与阿里云远程仓库建立连接。
然后点击结束即可!
04、Nexus和阿里云仓库配合
点击上面的齿轮,开始进行远程仓库和nexus的关联。
Repository仓库界面罗列了多个默认仓库,也可以添加新的仓库。
-
maven-center :type为proxy表示代理仓库,用来代理远程仓库- - 下载组件是,如果代理仓库找不到,就会从远程仓库(默认是:https://repo1.maven.org/maven2/)后续我们会更改为阿里云的参合库地址,并从远程仓库下载,然后将改组件仓库到代理仓库,当再次请求组件时。则直接到代理仓库下载,不会再次请求远程仓库。
默认情况下是和国外的远程仓库关联的。如何进行修改呢?点击当前的maven-center如下:
修改如下:
将https://repo1.maven.org/maven2/修改为
http://maven.aliyun.com/nexus/content/groups/public - - ->然后向下滑动滚动条,点击save按钮进行保存。至此maven-center远程仓库地址就配置完成了。
-
maven-releases/maven-snapshosts。type是hosted。表示宿主仓库,主要用来部署团队内部的自己,其中maven-releases是用来部署团队内部的发布版本组件,maven-snapshosts用来部署团队内部的快照版本的组件
-
maven-public:type是group,表示分组仓库,默认将maven-center、maven-realeases、maven-sniphots三个仓库在一起对外提供服务,简化了:maven客户端在setting.xml或者pom.xml中进行配置
中央仓库地址:http://127.0.0.1:8081/repository/maven-central/
SNAPSHOT地址:http://127.0.0.1:8081/repository/maven-snapshots/
RELEASES地址:http://127.0.0.1:8081/repository/maven-releases/
自建的地址:http://127.0.0.1:8081/repository/maven-self/
聚合地址:http://127.0.0.1:8081/repository/maven-public/
05、最终使用的仓库地址- - -下载
http://127.0.0.1:8081/repository/maven-public/
具体应用
1、在本地的maven的setting.xml进行镜像的配置如下:
nexus
*
Nexus aliyun
http://127.0.0.1:8081/repository/maven-public/
2、创建maven项目,然后添加依赖即可
可以看到下载jar包的时候就是从自己的私服仓库进行下载到本地仓库中。
06、关于Maven手动配置jar到本地仓库?
-
阿飞丢了一个jar包
-
小k同学,下载执行下面的命令
mvn install:install-file -Dfile="/Users/mac/Documents/项目/phutools.jar" -DgroupId=com.pug.htools -DartifactId=phtools -Dversion=1.1.0 -Dpackaging=jar
-
小k同学在他的maven项目,依赖坐标即可
com.pug.htools
phtools
1.1.0
07、最终使用的仓库地址- - -上传
1、向客户端setting。xml文件的servers标签添加如下配置
nexus
admin
123456
2、修改您项目的pom.xml,向project根目录添加如下配置
nexus
Nexus Release Repository
http://127.0.0.1:8081/repository/maven-releases/
nexus
Nexus Snapshot Repository
http://127.0.0.1:8081/repository/maven-snapshots/
08、关于RELEASE版本不允许重复发布的问题
发布release版本只需要在项目的pom.xml修改对应的版本即可!
1.0-RELEASES
修改releases允许覆盖和发布旧的版本
默认情况下:releases版本是禁止重复上传和发布的,我们可以在下面打开允许重复发布和覆盖旧的版本,修改如下:
然后save即可!
运行项目的deploy命令,执行结果如下:
其实建议:不要打开,而是每次发布增加版本号。既然你都要更新和发布了,说明有新的变化。你为什么不加版本号呢?
9、SpringBoot搭建SSM项目的完整过程
01、新建一个springboot项目
选择依赖和版本
SpringBoot整合lombok
lombok是一个快速生成javabean的一个工具工程和生成日志的工具。未来给我们提供了很大的遍历。
需要在idea中安装插件和pom.xml中进行依赖才可以使用生效:
pom.xml依赖如下:
org.projectlombok
lombok
true
SpringBoot在依赖的过程,为什么有的要加版本号,有的不加?
org.springframework.boot
spring-boot-starter-web
mysql
mysql-connector-java
8.0.27
com.baomidou
mybatis-plus-boot-starter
3.5.2
org.projectlombok
lombok
true
-
mysql
-
mybatis-plus 都不属于springboot父工程管理,自然必须把自己的version加上去!
SpringBoot整合Mybatis-Plus和数据源
1、在pom.xml中依赖如下:
mysql
mysql-connector-java
8.0.27
com.baomidou
mybatis-plus-boot-starter
3.5.2
2、准备一个数据库表kss_user
CREATE TABLE `kss_user` (
`id` int NOT NULL AUTO_INCREMENT,
`user_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
`password` varchar(255) DEFAULT NULL,
`real_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
`gender` int DEFAULT NULL,
`birthday` date DEFAULT NULL,
`create_time` datetime DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
3、配置数据源和mybatis配置
在项目的resource目录下的application.yaml配置如下:
server:
port: 8080
# 数据源配置
spring:
application:
name: pug-springboot-ssm
datasource:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/ssm_db?serverTimezone=GMT%2b8&useUnicode=true&useSSL=false&characterEncoding=UTF-8
username: root
password: 123456
hikari:
connection-timeout: 60000
validation-timeout: 3000
idle-timeout: 60000
login-timeout: 5
max-lifetime: 60000
maximum-pool-size: 30
minimum-idle: 10
read-only: false
# mybatis-plus配置
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
mapper-locations:
- classpath*:/mapper/*.xml
4、在resource新建一个mapper文件用来存放mybatis的xml文件
5、springboot整合mybatis-plus
package com.ksd.pug;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("com.ksd.pug.mapper")
public class PugSpringbootSsmApplication {
public static void main(String[] args) {
SpringApplication.run(PugSpringbootSsmApplication.class, args);
}
}
SpringBoot实现对用户表的CRUD操作
01、pojo
package com.ksd.pug.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.io.Serializable;
import java.util.Date;
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@TableName("kss_user")
public class User implements Serializable {
@TableId(type = IdType.AUTO)
private Integer id;
private String username;
private String password;
private String realName;
private Integer gender;
private Date birthday;
}
02、mapper
package com.ksd.pug.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ksd.pug.pojo.User;
public interface UserMapper extends BaseMapper {
}
03、service和serviceImpl
package com.ksd.pug.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ksd.pug.pojo.User;
public interface IUserService extends IService {
}
package com.ksd.pug.service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ksd.pug.mapper.UserMapper;
import com.ksd.pug.pojo.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Slf4j
@Service
public class IUserServiceImpl extends ServiceImpl implements IUserService {
}
04、controller
package com.ksd.pug.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ksd.pug.config.exception.BusinessException;
import com.ksd.pug.config.results.Code;
import com.ksd.pug.config.results.Result;
import com.ksd.pug.pojo.User;
import com.ksd.pug.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private IUserService userService;
@PostMapping
public Result save(User user){
boolean flag = userService.saveOrUpdate(user);
return new Result(flag ? Code.SAVE_OK:Code.SAVE_ERROR);
}
@PutMapping
public Result update(User user){
boolean flag = userService.updateById(user);
return new Result(flag ? Code.UPDATE_OK:Code.UPDATE_ERROR);
}
@DeleteMapping("/{id}")
public Result delete(Integer id){
boolean flag = userService.removeById(id);
return new Result(flag ? Code.DELETE_OK:Code.DELETE_ERROR);
}
@GetMapping("/{id}")
public Result get(@PathVariable("id")Integer id) throws BusinessException {
User user = userService.getById(id);
// 模拟出现异常,使用条件控制,便于测试结果
if (id == 10) {
throw new BusinessException("查询出错了,请重试!",Code.GET_ERROR);
}
return new Result(null != user ? Code.GET_OK :Code.GET_ERROR,user);
}
@GetMapping("/{pageNo}/{pageSize}")
public Result getAll(@PathVariable Integer pageNo,@PathVariable Integer pageSize){
// 1、设置分页
Page page = new Page<>(pageNo,pageSize);
// 2、设置条件
LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>();
// 3、查询分页返回
IPage page1 = userService.page(page, lambdaQueryWrapper);
return new Result(null != page1 ? Code.GET_OK :Code.GET_ERROR,page1);
}
}
这里剩余的一些配置类可以参考上面的!这里就不进行写入了!
在这里扩展一个小技巧:(测试数据可以使用)
这个跟你在浏览器或者postman、apipost...是一样的作用
1、首先你要在你的idea创建一个resource/http/xxx.http
2、然后可以点击Add Request创建你要测试的数据接口
3、根据自己情况进行测试!
GET http://localhost:8080/user/1/1
Accept: application/json
###
GET http://localhost:8080/user/1
Accept: application/json
###
Mybatis-Plus的分页失效问题
@Configuration
public class MybatisPlusConfig {
/**
* 新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题(该属性会在旧插件移除后一同移除)
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
Mybatis-Plus的创建时间和更新时间回填问题
-
定义个回填配置类
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
log.info("start insert fill...");
//default MetaObjectHandler setFieldValByName(String fieldName, Object fieldVal, MetaObject metaObject)
this.setFieldValByName("createTime",new Date(),metaObject);
this.setFieldValByName("updateTime",new Date(),metaObject);
}
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updateTime",new Date(),metaObject);
}
}
-
在pojo中使用@TableFiled(fill=xxx)指定回填触发方法
package com.ksd.pug.pojo;
import com.baomidou.mybatisplus.annotation.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.io.Serializable;
import java.util.Date;
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@TableName("kss_user")
public class User implements Serializable {
@TableId(type = IdType.AUTO)
private Integer id;
private String userName;
private String password;
private String realName;
private Integer gender;
private Date birthday;
@TableField(fill = FieldFill.INSERT)
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
}
数据库级别的解决方案
首先将字段设置为timestamp,然后设置不是null,根据当前时间戳更新,在这里注意我们的create_time是不根据当前时间戳更新的!这种方式虽然可以但是不建议!
在mysql低版本的时候可能会出现一个问题,你的sql语句无法导入,而导致这个的原因是有的他只可以设置一个timestamp(在这里提示:mysql5.7 、mysql8.0是可以的!)
Mybatis-Plus是怎么做到不写sql但是可以实现CRUD操作
-
背后绝对是拼接SQL语句,然后调用mybatis底层执行sql。
具体需要学习mp!