SSM01搭建SSM项目
1.创建maven的web工程
1.1pom.xml配置
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.aaa.ssm</groupId>
<artifactId>SSMDemo1</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>SSMDemo1 Maven Webapp</name>
<url>http://maven.apache.org</url>
<properties>
<!-- Spring版本号 -->
<spring.version>5.3.29</spring.version>
</properties>
<dependencies>
<!-- jackson依赖包 springmvc中 转json数据 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.14.2</version>
</dependency>
<!-- springmvc依赖包 -->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- spring面向切面编程依赖包 aop -->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- spring数据库依赖包 -->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.29</version>
</dependency>
<!-- mybatis依赖包 -->
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.13</version>
</dependency>
<!-- mybatis 与 spring整合的jar包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
<!-- mysql数据库驱动依赖包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<!-- druid连接池依赖包 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.4</version>
</dependency>
<!-- servlet-api依赖包 -->
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.14</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.4.13</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
</dependencies>
</project>
1.2web.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
2.SSM配置文件
创建resources文件夹
2.1spring.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"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
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
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- spring注解扫描 @Controller @Service @autowired -->
<context:annotation-config/>
<context:component-scan base-package="com.aaa.ssm"/>
<!-- spring mvc 注解驱动 @ResquestMapping -->
<mvc:annotation-driven/>
<!-- 静态文件加载配置 -->
<mvc:default-servlet-handler/>
<!-- 属性文件加载 我们现在要使用 druid的数据库连接池
druid的数据库连接池有一个配置文件 druid.properties 里面都是druid的配置信息
此时在spring的配置文件中 需要去读druid.properties中的信息
在spring 中可以配置PropertyPlaceholderConfigurer 这样的bean
这个bean 就会根据location 配置的地址classpath:druid.properties
去读取配置信息
-->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:druid.properties"></property>
</bean>
<!-- 我们当前项目 使用的数据库连接池是 阿里巴巴的 druid
数据库连接池的使用 创建数据库连接池对象 ,需要连接对象conn的时候 从连接池对象中
获取
此时我们使用spring 创建连接池对象的工作就交给spring
配置当前bean class 是com.alibaba.druid.pool.DruidDataSource
此时spring就会管理数据库连接池对象的创建
-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- spring整合 mybatis SqlSessionFactoryBean -->
<bean id="sqlFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 使用哪个数据库连接池 此时使用 ref引用 dataSource 代表使用的是 上面的
druid数据库连接池 -->
<property name="dataSource" ref="dataSource"/>
<!-- 配置 mybatis的 配置文件位置-->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<!-- 扫描 所有的 mapper.xml文件的位置 注意 此处容易出问题 -->
<property name="mapperLocations" value="classpath:mapper/*Mapper.xml"/>
<!--别名扫描-->
<property name="typeAliasesPackage" value="com.aaa.ssm.pojo"></property>
</bean>
<!-- mapper 扫描接口 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- mapper对应的接口的包名 -->
<property name="basePackage" value="com.aaa.ssm.mapper"/>
<!-- 扫描接口的时候 要知道为谁扫描的-->
<property name="sqlSessionFactoryBeanName" value="sqlFactory"/>
</bean>
</beans>
2.2mybatis-config.xml
<?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>
</configuration>
2.3log4j.properties
log4j.rootLogger=ERROR, stdout
log4j.logger.com.aaa.ssm=TRACE
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
2.4druid.properties
jdbc.driverClassName=com.mysql.jdbc.Driver
#注意要操作的数据库名称 此处用的是 myproject
jdbc.url=jdbc:mysql://127.0.0.1:3306/myproject?characterEncoding=utf-8&useSSL=false
#数据库连接用户名
jdbc.username=root
#数据库密码
jdbc.password=123456
到这里前期的准备工作就完成了
接下来创建一下项目的基本结构如图:
3.登录模块
数据库
登录模块中只需要用户的账号密码,这是我的一个数据库内容
流程分析
登录的话,当我们配置好tomcat后,启动项目应该先进入一个默认的登录页面,然后在页面中输入账号密码后,后台访问数据库进行业务处理
我们现在webapp文件夹下,创建一个默认页面
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
<script src="js/jquery.min.js"></script>
<!-- 引入样式 -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<!-- 引入组件库 -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<style>
#app {
width: 600px;
margin: 150px auto;
padding: 40px;
}
</style>
</head>
<body>
<div id="app">
<h1>欢迎登录XXX管理系统</h1>
<el-form :model="loginInfo" :rules="rules" status-icon ref="loginInfo" label-width="100px" class="demo-ruleForm">
<el-form-item label="账号" prop="username">
<el-input type="text" autocomplete="off" v-model="loginInfo.username"></el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input type="password" autocomplete="off" v-model="loginInfo.password"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="login()">登录</el-button>
<el-button @click="reset()">重置</el-button>
</el-form-item>
</el-form>
</div>
<script>
var app = new Vue({
el: "#app",
data: {
loginInfo: {},
rules: {
username: [
{required: true, message: '请输入账号', trigger: 'blur'},
{min: 2, max: 10, message: '请输入2到10个字符', trigger: 'blur'}
],
password: [
{required: true, message: '请输入密码', trigger: 'blur'},
{min: 2, max: 10, message: '请输入2到10个字符', trigger: 'blur'}
]
}
},
methods: {
login() {
this.$refs["loginInfo"].validate((valid) => {
if (valid) {
//发送ajax请求到后台
$.post("/ssm/emp/login",app.loginInfo,function (backData) {
})
}
});
},
reset: function () {
this.$refs["loginInfo"].resetFields();
},
}
})
</script>
</body>
</html>
3.1页面引入文件
在这个页面中,用到了jquery和vue的文件,我是下载到本地了,如果需要可以直接去官网下载,或者直接使用官网提供的CDN如下:
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<!-- 引入样式 -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<!-- 引入组件库 -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
我还使用了ElementUI,在引入时要放在vue的下边
在登录中,我们需要输入账号密码。页面中有两个按钮,一个登录一个重置
我们在这里主要写一下登录的业务流程
当我们点击登录时我们会执行login函数,这里有一个对表单进行验证是ElementUI自带的
login() {
this.$refs["loginInfo"].validate((valid) => {
if (valid) {
//发送ajax请求到后台
$.post("/ssm/emp/login",app.loginInfo,function (backData) {
})
}
});
},
3.2controller
我们使用ajax对后台发送请求
这时候我们会去controller层
在controller文件夹下创建EmpController类,进行参数的接收。这里会根据路径不同自动的进行分发操作
package com.aaa.ssm.controller;
import com.aaa.ssm.result.AjaxResult;
import com.aaa.ssm.service.EmpService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Author Grg
* @Date 2023/9/17 14:49
* @PackageName:com.aaa.ssm.controller
* @ClassName: EmpController
* @Description: 又是码代码的一天
* @Version plus max 宇宙无敌终极版本
*/
@RestController
@RequestMapping("emp")
public class EmpController {
@Autowired
private EmpService empService;
@RequestMapping("login")
public AjaxResult login(String username, String password) {
return empService.login(username, password);
}
}
3.3service
登录时,我们发送的请求路径是"/ssm/emp/login"
所以就会执行login方法
在此之前,我们需要用EmpService接口并通过注解@Autowired进行自动注入
我们去service文件夹下创建一个impl文件夹(存放的是Service的实现类)和一个EmpService接口
3.3.1EmpService
package com.aaa.ssm.service;
import com.aaa.ssm.result.AjaxResult;
/**
* @Author Grg
* @Date 2023/9/17 14:58
* @PackageName:com.aaa.ssm.service
* @ClassName: EmpService
* @Description: 又是码代码的一天
* @Version plus max 宇宙无敌终极版本
*/
public interface EmpService {
AjaxResult login(String username, String password);
}
3.3.2EmpServiceImpl
编写实现类EmpServiceImpl
package com.aaa.ssm.service.impl;
import com.aaa.ssm.mapper.EmpMapper;
import com.aaa.ssm.pojo.dto.EmpDTO;
import com.aaa.ssm.pojo.dto.LoginDTO;
import com.aaa.ssm.result.AjaxResult;
import com.aaa.ssm.service.EmpService;
import com.aaa.ssm.sysconst.DeptState;
import com.aaa.ssm.sysconst.EmpState;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpSession;
/**
* @Author Grg
* @Date 2023/9/17 15:00
* @PackageName:com.aaa.ssm.service.impl
* @ClassName: EmpServiceImpl
* @Description: 又是码代码的一天
* @Version plus max 宇宙无敌终极版本
*/
@Service
public class EmpServiceImpl implements EmpService {
@Autowired
private EmpMapper empMapper;
@Autowired
private HttpSession session;
@Override
public AjaxResult login(String username, String password) {
//1.验证账号密码是否正确
LoginDTO login = empMapper.login(username, password);
//1.5账号的状态是什么 state 0在职 1冻结 2离职
if (login == null) {
return AjaxResult.error("账号或者密码错误");
}
if (login.getState() == EmpState.EMP_DONGJIE) {
return AjaxResult.error("账号被冻结");
}
if (login.getState() == EmpState.EMP_LIZHI) {
return AjaxResult.error("员工已经离职 联系管理员");
}
//2.如果正确 获取员工编号 查询员工信息
Integer eid = login.getEid();
EmpDTO empInfo = empMapper.getEmpInfoByEid(eid);
if (empInfo.getDept().getState() == DeptState.DEPT_STATE_BILE) {
return AjaxResult.error("部门已倒闭 请联系主管");
}
//登录成功
//将当前用户信息存储近Session中
session.setAttribute("emp", empInfo);
return AjaxResult.success();
}
}
3.4mapper
这里我们需要用到mapper通过mybatis进行数据库的操作
在mapper文件夹中新建EmpMapper
3.4.1EmpMapper
package com.aaa.ssm.mapper;
import com.aaa.ssm.pojo.dto.EmpDTO;
import com.aaa.ssm.pojo.dto.LoginDTO;
import org.apache.ibatis.annotations.Param;
/**
* @Author Grg
* @Date 2023/9/17 15:02
* @PackageName:com.aaa.ssm.mapper
* @ClassName: EmpMapper
* @Description: 又是码代码的一天
* @Version plus max 宇宙无敌终极版本
*/
public interface EmpMapper {
LoginDTO login(@Param("username")String username,@Param("password") String password);
EmpDTO getEmpInfoByEid(Integer eid);
}
在resources配置文件夹下新建一个mapper文件夹
创建EmpMapper.xml文件
3.4.2EmpMapper.xml
<?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.aaa.ssm.mapper.EmpMapper">
<select id="login" resultType="com.aaa.ssm.pojo.dto.LoginDTO">
select * from t_emp_login where username = #{username} and password = #{password};
</select>
<resultMap id="empInfo" type="empDTO">
<id column="id" property="id"></id>
<result column="ename" property="ename"></result>
<result column="hiredate" property="hiredate"></result>
<result column="telephone" property="telephone"></result>
<association property="dept" javaType="deptDTO">
<id column="did" property="id"></id>
<result column="dname" property="dname"></result>
<result column="dstate" property="state"></result>
</association>
<association property="role" javaType="roleDTO">
<id column="rid" property="id"></id>
<result column="rname" property="rname"></result>
<result column="rstate" property="state"></result>
</association>
</resultMap>
<select id="getEmpInfoByEid" resultMap="empInfo">
SELECT e.id,
e.ename,
e.hiredate,
e.telephone,
d.id did,
d.dname,
d.other,
d.state dstate,
r.id rid,
r.rname,
r.state rstate
from t_emp_info e
LEFT JOIN t_dept d on e.did = d.id
LEFT JOIN t_role r on e.rid = r.id
where e.id = #{eid};
</select>
</mapper>
3.5result
我们在实现类中需要用到一个结果集,在业务处理完成后响应信息
在result文件夹下创建AjaxResult
package com.aaa.ssm.result;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @Author Grg
* @Date 2023/8/28 15:58
* @PackageName:com.grg.Result
* @ClassName: AjaxResult
* @Description: 又是码代码的一天
* @Version plus max 宇宙无敌终极版本
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class AjaxResult {
private Integer code;
private String msg;
private Object data;
public static AjaxResult success() {
return new AjaxResult(1,"操作成功",null);
}
public static AjaxResult success(Object data) {
return new AjaxResult(1,"操作成功",data);
}
public static AjaxResult error() {
return new AjaxResult(2,"操作失败",null);
}
public static AjaxResult error(String msg) {
return new AjaxResult(2,msg,null);
}
}
3.6pojo
我们在pojo中创建几个实体类用于结果的接收
在pojo文件夹下新建dto文件夹
3.6.1DeptDTO
package com.aaa.ssm.pojo.dto;
import lombok.Data;
import java.io.Serializable;
/**
* @Author Grg
* @Date 2023/9/17 15:22
* @PackageName:com.aaa.ssm.pojo.dto
* @ClassName: DeptDTO
* @Description: 又是码代码的一天
* @Version plus max 宇宙无敌终极版本
*/
@Data
public class DeptDTO implements Serializable {
private Integer id;
private String dname;
private String other;
private Integer state;
}
3.6.2EmpDTO
package com.aaa.ssm.pojo.dto;
import lombok.Data;
import java.io.Serializable;
/**
* @Author Grg
* @Date 2023/9/17 15:20
* @PackageName:com.aaa.ssm.pojo.dto
* @ClassName: EmpDTO
* @Description: 又是码代码的一天
* @Version plus max 宇宙无敌终极版本
*/
@Data
public class EmpDTO implements Serializable {
private Integer id;
private String ename;
private String hiredate;
private String telephone;
//数据库中存在外键,我们通过 成员对象来对应
private DeptDTO dept;
private RoleDTO role;
}
3.6.3LoginDTO
package com.aaa.ssm.pojo.dto;
import lombok.Data;
import java.io.Serializable;
/**
* @Author Grg
* @Date 2023/9/17 15:03
* @PackageName:com.aaa.ssm.pojo
* @ClassName: LoginDTO
* @Description: 又是码代码的一天
* @Version plus max 宇宙无敌终极版本
*/
@Data
public class LoginDTO implements Serializable {
private Integer id;
private String username;
private String password;
private Integer eid;
private Integer state;
}
3.6.4RoleDTO
package com.aaa.ssm.pojo.dto;
import lombok.Data;
import java.io.Serializable;
/**
* @Author Grg
* @Date 2023/9/17 15:25
* @PackageName:com.aaa.ssm.pojo.dto
* @ClassName: RoleDTO
* @Description: 又是码代码的一天
* @Version plus max 宇宙无敌终极版本
*/
@Data
public class RoleDTO implements Serializable {
private Integer id;
private String rname;
private String other;
private Integer state;
}
3.7sysconst
这个文件夹中我们主要用来创建接口,接口中存放一些常量,用来消除魔法值
3.7.1DeptState
package com.aaa.ssm.sysconst;
/**
* @Author Grg
* @Date 2023/9/17 15:42
* @PackageName:com.aaa.ssm.sysconst
* @ClassName: DeptState
* @Description: 又是码代码的一天
* @Version plus max 宇宙无敌终极版本
*/
public interface DeptState {
int DEPT_STATE_BILE = 1;
}
3.7.2EmpState
package com.aaa.ssm.sysconst;
/**
* @Author Grg
* @Date 2023/9/17 15:16
* @PackageName:com.aaa.ssm.sysconst
* @ClassName: EmpState
* @Description: 又是码代码的一天
* @Version plus max 宇宙无敌终极版本
*/
public interface EmpState {
int EMP_DONGJIE = 1;
int EMP_LIZHI = 2;
}
4.项目启动
4.1测试
到这里我们就完成了登录模块
启动tomcat首先进入到登录页面
按下F12进入页面网络检查
首先进行错误检查,输入一个错误的账号或密码,查看响应信息
在输入正确的账号密码,我的数据库中是123,123
可以看到响应的数据正确
此时做一个登录成功后的页面跳转就可以了
4.2页面优化跳转
我们做一个当登录失败时给用户的提示,此时也是用的ElementUI中的
在index.html页面中
this.$refs["loginInfo"].validate((valid) => {
if (valid) {
//发送ajax请求到后台
$.post("/ssm/emp/login", app.loginInfo, function (backData) {
if (backData.code == 1) {
window.location.href = "main.html"
} else {
app.$notify.error({
title: '温馨提示',
message: '账号或者密码错误'
});
}
})
}
});
这里做一个更改加入提示信息 效果如下
当登录成功时我们就跳转到新页面main.html
此时登录模块就基本做好了,可以自行在页面中进行美化等