一、建立环境
1、使用到的框架及数据库版本
2、新建NEW Project:Maven--->quickstart
3、工程目录结构
(到这一步如有缺少的包不用慌很正常,自己把缺少的包补起来然后继续下面的步骤)
4、在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.msb</groupId>
<artifactId>mycrm</artifactId>
<version>1.0-SNAPSHOT</version>
<name>mycrm</name>
<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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--
mybatis 集成
-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.1</version>
</dependency>
<!-- 分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.13</version>
</dependency>
<!--mysql 驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.5</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.5</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
<!-- DevTools 的坐标 热部署 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.2</version>
<configuration>
<configurationFile>src/main/resources/generatorConfig.xml</configurationFile>
<verbose>true</verbose>
<overwrite>true</overwrite>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<!-- 如果没有该配置,热部署的devtools不生效 -->
<fork>true</fork>
</configuration>
</plugin>
</plugins>
</build>
</project>
3、 在application.yml文件中进行本地化配置
## 端口号 上下文路径
server:
port: 8089
servlet:
context-path: /mycrm
## 数据源配置(url后的crm_sql_data是我本地数据库名称,读者根据自己的数据库名进行修改)
## username、password是数据库的账号与密码
spring:
datasource:
type: com.mchange.v2.c3p0.ComboPooledDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/crm_sql_data?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8
username: root
password: ******
## freemarker
freemarker:
suffix: .ftl
content-type: text/html
charset: UTF-8
template-loader-path: classpath:/views/
## 启用热部署
devtools:
restart:
enabled: true
additional-paths: src/main/java
## port: 35729
## mybatis 配置
mybatis:
mapper-locations: classpath:/mappers/*.xml
type-aliases-package: com.msb.crm.vo;com.msb.crm.query;com.msb.crm.dto
configuration:
map-underscore-to-camel-case: true
## pageHelper
pagehelper:
helper-dialect: mysql
## 设置 dao 日志打印级别
logging:
level:
com:
msb:
crm:
dao: debug
二、逆向工程
1、利用mybatis逆向工程自动生成vo类,mapper接口和mapper映射文件
1.1首先在resources目录下添加generatorConfig.xml文件,进行如下配置
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!--数据库驱动:这里的路径要改成自己的jar包路径-->
<classPathEntry location="D:/java_tool/repository/mysql/mysql-connector-java/8.0.18/mysql-connector-java-8.0.18.jar"/>
<context id="DB2Tables" targetRuntime="MyBatis3">
<commentGenerator>
<property name="suppressDate" value="true"/>
<property name="suppressAllComments" value="true"/>
</commentGenerator>
<!--数据库链接地址账号密码:这里也要修改成自己的数据-->
<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver" connectionURL="jdbc:mysql://127.0.0.1:3306/crm_sql_data?serverTimezone=GMT%2B8"
userId="root" password="123456">
<!--!!!!!!!!!!!!!一句话影响整个工程启动 !!!!!!!!!!!!!!!!!-->
<property name="nullCatalogMeansCurrent" value="true"/>
</jdbcConnection>
<!--java类型处理器:用于处理DB中的类型到Java中的数据类型-->
<javaTypeResolver>
<property name="forceBigDecimals" value="false"/>
</javaTypeResolver>
<!--生成Model类存放位置:vo层的存在就是方便前端获取响应数据(后端将响应的数据做一个整合,打包成一个类)-->
<javaModelGenerator targetPackage="com.msb.crm.vo" targetProject="src/main/java">
<!--在targetPackage基础上,根据数据库的schema再生成一层package,最终生成的类放在这个package里,默认为false-->
<property name="enableSubPackages" value="true"/>
<!--设置是否在getter方法中对String类型字段调用trim方法-->
<property name="trimStrings" value="true"/>
</javaModelGenerator>
<!--生成映射文件存放位置-->
<sqlMapGenerator targetPackage="mappers" targetProject="src/main/resources">
<property name="enableSubPackages" value="true"/>
</sqlMapGenerator>
<!--生成Dao类存放位置(数据访问层,也叫mapper层,持久层,与mapper.xml匹配使用)-->
<javaClientGenerator type="XMLMAPPER" targetPackage="com.msb.crm.dao" targetProject="src/main/java">
<property name="enableSubPackages" value="true"/>
</javaClientGenerator>
<table tableName="t_user" domainObjectName="User"
enableCountByExample="false" enableUpdateByExample="false"
enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>
</context>
</generatorConfiguration>
1.2、将下列执行命令语句按操作顺序图粘贴在圈4的位置:
mybatis-generator:generate -e
3、点击apply---->🆗,然后点击绿色三角运行按钮。
4、观察运行前后文件目录对比:
三、错误及解决 (如果没有错误忽略此步骤)
1、接口报错
1.1、接口中的方法不要出现方法体标志{},否则报错
1.2、改正:
2、逆向工程自动生成的实体类与表中的字段不一致
2.1、报错信息
2.2、改正:在generatorConfig.xml这个文件里找到数据库的连接标签,加上下面这行即可
//返回指定库涉及表
<property name="nullCatalogMeansCurrent" value="true"/>
如图所示:
2.3、修改之后先将之前逆向工程自动生成的 vo包中类文件,mapper接口类文件和mapper.xml映射文件都删除,然后按照本篇文章标题“二”的步骤重新执行逆向工程命令,然后将项目中其他报错的地方的依赖重新导入一下,基本上问题就解决了。
3、出现LiveReload(热部署)警告
3.1、复刻项目代码时报了一个警告:
WARN 13504 --- [ restartedMain] o.s.b.d.a.OptionalLiveReloadServer : Unable to start LiveReload server
3.2、问题背景
首先查询资料得知该警告出现原因是多个项目/模块都进行了热启动部署,导致热部署默认的端口冲突,我百思不得其解,我的工程里就一个模块怎么还冲突了???结果我突然发现我复刻的那个工程也在运行,顿时恍然大悟,原来问题出在这里,我同时运行了两个工程(我打开了2个idea,每个idea都有工程在运行),这两个工程里的热部署都是默认的端口,所以冲突了,后来我把其中一个工程结束运行就没有警告了。
3.3、解决
我们要运行多个进行热启动部署工程/模块时,可以在部署时把每个工程/模块的热部署端口号修改的不一致,如此就完美解决了冲突警告。
四、添加resources目录下静态资源
base包:阿里云盘资源分享
utils包:阿里云盘资料
views包:阿里云盘资料分享
Exception包:阿里云盘资源分享
public包下资源<css包资源,images资源包,js资源包,,lib资源包之font-awesome-4.7.0,lib资源包之jq&LayUI>
五、编写代码
(一)用户登录 后端整体思路:
1、参数判断
用户姓名: 非空判断 用户密码: 非空判断
2、通过用户名查询用户记录,返回用户对象
3、判断用户对象是否为空
3.1若用户对象不为空,则将前台传递的用户密码与数据库中的做比较
3.1.1若密码正确,登陆成功,返回登录页面后的首页结果
3.1.2否则返回密码错误的提示信息 3.2若用户对象为空,则返回登录页面并提示用户先进行注册后登录使用。
(二)分层实现思路
1、controller层 (控制层:接受请求并提供实参入口,响应结果)
(1)通过形参接收客户端传递的实参
(2)调用业务逻辑层的登录方法
(3)响应数据给客户端
2、service层 (业务逻辑层:非空判断层,条件判断等业务逻辑处理) 是上述整体思路的具体细节执行者
(1)参数判断,判断用户姓名,密码是否非空
(1.1)用户名参数为空:抛出异常(异常被控制层捕获并处理)
(1.2)用户名参数不空:调用持久层方法查询用户记录,根据持久层返回的用户对象数据作进一步判断(对象数据的密码与实参密码比较
(1.2.1)密码不正确,抛出异常(异常被控制层捕获并处理)
( 1.2.2)密码正确,登陆成功
3、dao层 (数据访问层:数据库中增删改查) 通过用户名查询用户记录,返回用户对象
三、具体代码
1、dao层UserMapper类
package com.msb.crm.dao;
import com.msb.crm.base.BaseMapper;
import com.msb.crm.vo.User;
public interface UserMapper extends BaseMapper<User,Integer> {
public User queryUserByName(String userName);
}
2、service层UserService类
package com.msb.crm.service;
import com.msb.crm.base.BaseService;
import com.msb.crm.dao.UserMapper;
import com.msb.crm.model.UserModel;
import com.msb.crm.utils.AssertUtil;
import com.msb.crm.utils.Md5Util;
import com.msb.crm.vo.User;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/**
* 业务逻辑层会调用dao层:将dao层对象注入
* 然后调用各种具体的方法
*/
//@Service注解:告诉Spring要将这个类纳入管理并创建其实例
@Service
public class UserService extends BaseService<User,Integer> {
@Resource
private UserMapper userMapper;
/**
* 用户登录:
* service层 (业务逻辑层:非空判断层,条件判断等业务逻辑处理)
* 是整体思路的具体细节执行者
* 1、参数判断,判断用户姓名,密码是否非空
* 1.1、用户名,密码为空:抛出异常(异常被控制层捕获并处理)
* 1.2、用户名参数不空:调用持久层方法查询用户记录,根据持久层返回的用户对象数据作进一步判断(对象数据的密码与实参密码比较)
* 1.2.1、密码不正确,抛出异常(异常被控制层捕获并处理)
* 1.2.2、密码正确,登陆成功
* @param userName 用户姓名
* @param userPwd 用户密码
*/
public UserModel userLogin(String userName, String userPwd){
//1.1、调用方法:进行参数非空判断,判断用户姓名,密码是否为空
cheakLoginparams(userName,userPwd);
//1.2用户名不空:调用持久层方法查询数据库中是否有该用户记录,也就是判断与该用户名匹配的用户是否存在于数据库
User user = userMapper.queryUserByName(userName);
//1.2.1用户不存在:
AssertUtil.isTrue(user==null,"用户不存在");
//1.2.2用户存在:判断密码输入是否正确
cheakUserPwd(userPwd,user.getUserPwd());
//1.2.3针对登陆成功的用户调用buildUserInfo方法:把所需要的用户信息封装为对象后返回
return buildUserInfo(user);
}
/**
* 1.2.3定义方法:根据传入的用户返回需求字段的信息
* @param user
* @return
*/
private UserModel buildUserInfo(User user) {
UserModel userModel = new UserModel();
userModel.getUserId();
userModel.getUserName();
userModel.getTrueName();
return userModel;
}
/**
* 1.2.2方法定义:密码是否正确
* 先对前台传来的密码进行加密,然后与数据库中的密码进行比较
* 加密工具:Md5Util
* @param userPwd
* @param pwd
*/
private void cheakUserPwd(String userPwd, String pwd) {
//将客户端传递的密码加密
userPwd = Md5Util.encode(userPwd);
//判断密码是否相等
AssertUtil.isTrue(!userPwd.equals(pwd),"用户密码不正确");
}
/**
* 1.1方法定义、用户名,密码为空:抛出异常(异常被控制层捕获并处理)
* @param userName 用户姓名
* @param userPwd 用户密码
*/
private void cheakLoginparams(String userName, String userPwd) {
//判断用户姓名
AssertUtil.isTrue(StringUtils.isBlank(userName),"用户姓名不能为空");
//判断用户密码
AssertUtil.isTrue(StringUtils.isBlank(userPwd),"用户密码不能为空");
}
}
3、controller层
3.1、 IndexController类
package com.msb.crm.controller;
import com.msb.crm.base.BaseController;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
@Controller
public class IndexController extends BaseController {
/**
* 系统登录页
* @return
*/
@RequestMapping("index")
public String index(){
return "index";
}
// 系统界面欢迎页
@RequestMapping("welcome")
public String welcome(){
return "welcome";
}
/**
* 后端管理主页面
* @return
*/
@RequestMapping("main")
public String main(HttpServletRequest request){
return "main";
}
}
3.2、UserController类
package com.msb.crm.controller;
import com.msb.crm.base.BaseController;
import com.msb.crm.base.ResultInfo;
import com.msb.crm.exceptions.ParamsException;
import com.msb.crm.model.UserModel;
import com.msb.crm.service.UserService;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.Resource;
/**
* 这里是用户登录页面后台,对接前台index页面里发送的Ajax登录请求
*/
//@Controller标记该类是一个控制器(控制器负责接收请求、处理请求,并返回响应)
@Controller
@RequestMapping("user")
public class UserController extends BaseController {
//本层会调用service层对象里的方法,在该类里注入service层对象
@Resource
private UserService userService;
//该注解作用:给客户端提供访问路径
@PostMapping("login")
//以jason格式返回对象类型数据要加这个注解@ResponseBody(如果返回页面不需要加该注解)
@ResponseBody
//调用登录方法,用ResultInfo类型变量接收传回来的数据
public ResultInfo userLogin(String userName, String userPwd) {
ResultInfo resultInfo = new ResultInfo();
try {
//没有异常时执行try里的代码块,否则执行catch里的代码段
//controller层对service层的数据进行接收(不建议直接用User类对象接收,因为其中有很多我们不需要的属性值)
//所以我们新建一个model层,里面定义UserModel类,用于把我们需要返回的数据信息封装到该类里
UserModel userModel = userService.userLogin(userName, userPwd);
//将接收到的数据给客户端响应
//设置登陆成功后resultInfo的response值
resultInfo.setResult(userModel);
} catch (ParamsException p) {
resultInfo.setCode(p.getCode());
resultInfo.setMsg(p.getMsg());
p.printStackTrace();
} catch (Exception e) {
resultInfo.setCode(500);
resultInfo.setMsg("登陆失败");
}
return resultInfo;
}
;
}
4、启动器(在我本地的crm包下)
运行启动器,
package com.msb.crm;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("com.msb.crm.dao")
public class Starter {
public static void main(String[] args) {
SpringApplication.run(Starter.class);
}
}