介绍SSM框架---原理
一、什么是SSM框架?
SSM框架是指由Spring、Spring MVC和MyBatis三个开源框架整合而成的Java Web应用开发框架组合。标准的SSM框架有四层,分别是dao层(mapper),service层,controller层和view层。使用spring实现业务对象管理,使用spring MVC负责请求的转发和视图管理,mybatis作为数据对象的持久化引擎。
1)持久层:mapper/dao层
定义:持久层是专门处理数据存储和检索的软件层次,负责将内存中的对象数据持久化到数据库或其他存储介质中。
作用:主要是做数据持久层的工作,负责与数据库进行联络的一些任务都封装在此。
- dao层首先设计的是接口,然后Spring的配置文件中定义接口的实现类。
- 然后可以在模块中进行接口的调用来进行数据业务的处理(不在关心接口的实现类是哪个类)
- 数据源的配置以及有关数据库连接的参数都在Spring的配置文件中进行配置。
2)业务层:service层
定义:业务层(也称为服务层)是SSM框架中承上启下的核心层次,位于表现层(Controller)和持久层(Mapper/Dao)之间,负责实现系统的业务逻辑。
作用:Service层主要负责业务模块的逻辑应用设计。
- 先设计接口然后在设计实类,然后再在Spring的配置文件中配置其实现的关联。(业务逻辑层的实现具体要调用到自己已经定义好的Dao的接口上)这样就可以在应用中调用Service接口来进行业务处理。
- 建立好Dao之后再建立service层,service层又要在controller层之下,因为既要调用Dao层的接口又要提供接口给controller层。每个模型都有一个service接口,每个接口分别封装各自的业务处理的方法。
3)表现层:Controller层
定义:表现层是SSM框架中直接与用户交互的层次,在Web应用中通常由Spring MVC框架实现,负责处理HTTP请求和响应。
作用:负责具体的业务模块流程的控制。
- 配置也同样是在Spring的配置文件里面进行。
- 调用Service层提供的接口来控制业务流程。
- 业务流程的不同会不同的控制器,在具体的开发中可以将我们的流程进行抽象的归纳,设计出可以重复利用的子单元流程模块。
关键注解说明
4)View层
定义:在SSM框架中,View层(视图层) 负责数据的展示,通常与Controller层配合,将后端数据渲染成HTML、JSON、XML等格式返回给前端。
作用:主要和控制层紧密结合,主要负责前台jsp页面的表示。
联系:
DAO层,Service层这两个层次都可以单独开发,互相的耦合度很低,完全可以独立进行,这样的一种模式在开发大项目的过程中尤其有优势,Controller,View层因为耦合度比较高,因而要结合在一起开发,但是也可以看作一个整体独立于前两个层进行开发。这样,在层与层之前我们只需要知道接口的定义,调用接口即可完成所需要的逻辑单元应用,一切显得非常清晰简单。
1、Spring
spring里面的IOC容器和AOP是我们平时使用最多的。
1)IOC(控制反转)
它可以装载bean,也是一种降低对象之间耦合关系的设计思想。(比如,传统方式(高耦合,自己管理依赖)类比:我(作为租客)需要自己找房东,然后谈合同(直接找房东解决),最后付房租(直接与房东交互),但是有个问题,如果换了个房东,就必须修改代码,导致的是租客和房东耦合性太强,灵活性太差了。IOC方式(低耦合,中介管理依赖):这时候我作为租客,我只需要找房屋中介(Spring IOC容器),他负责管理房东资源,然后匹配租客需求(自动注入合适的房东),然后提供统一标准化服务(统一的合同和付款接口),给我(作为租客)提供的便利就是只需要提供需求,换房东也罢,调用的接口是统一的,总结就是IoC就像房屋中介,帮你管理复杂的依赖关系。Bean就是中介管理的资源(房东、合同、付款方式等)。你的代码(租客)只需关注业务逻辑,不用操心对象创建和组装。)
2)AOP(面向切面)
是面向对象开发的一种补充,它允许开发人员在不改变原来模型的基础上动态的修改模型以满足新的需求,如:动态的增加日志,安全或异常处理等。AOP使业务逻辑各部分间的耦合度降低,提高程序课重用性,提高开发效率。
2、Spring MVC
工作流程
发起请求到前端控制器(DispatcherServlet)
前端控制器请求HandlerMapping查找Handler
处理器映射器HandlerMapping向前端控制器返回Handler
前端控制器调用处理器适配器去执行Handler
处理器适配器去执行Handler
Handler执行完成给适配器返回ModelAndView
处理器适配器向前端控制器返回ModelAndView(SpringMVC框架的一个底层对象,包括Model和View)
前端控制器请求视图解析器去进行视图解析,根据逻辑视图名解析成真正的视图(jsp)
视图解析器向前端控制器返回view
前端控制器进行视图渲染:视图渲染将模型数据(在ModelAndView对象中)填充到request域
前端控制器向用户响应结果
注:Model中的数据存储在request作用域中,SpringMVC默认采用转发的方式跳到视图,本次请求结束,模型中的数据被销毁
3、Mybatis(核心是sqlSession)
mybatis是对jdbc的封装,它让数据库底层操作变的透明。mybatis的操作都是围绕一个sqlSessionFactory实例展开的。mybatis通过配置文件关联到实体类的Mapper文件,Mapper文件中配置了每个类对数据库所需进行的sql语句映射。在每次与数据库交互时,通过sqlSessionFactory拿到一个sqlSession,再执行sql命令。
二、代码实战(TLIAS教学管理系统)
1、创建配置工程
1)创建maven工程
2)创建目录
- src--main下创建两个文件夹(Java和resources)。
- 和main同级创建一个test,test里面创建一个Java。
3)配置工程
-
file -- project structure -- modules
4)创建包
- src--Java下创建文件夹(XXX),
- (XXX)下创建entity,mapper,service和util包。
5)配置依赖
pom.xml加入依赖
代码如下:
<dependencies>
<!-- web起步依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- mybatis起步依赖 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<!-- mysql驱动 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- springboot单元测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--PageHelper分页插件-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.7</version>
</dependency>
<!-- 阿里云OSS -->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.15.1</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
<!-- no more than 2.3.3 -->
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<!-- JWT令牌 -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<!-- fastJSON -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.76</version>
</dependency>
</dependencies>
2、代码实战
1)设计数据库
-- 部门管理
create table dept(
id int unsigned primary key auto_increment comment '主键ID',
name varchar(10) not null unique comment '部门名称',
create_time datetime not null comment '创建时间',
update_time datetime not null comment '修改时间'
) comment '部门表';
insert into dept (id, name, create_time, update_time) values(1,'学工部',now(),now()),(2,'教研部',now(),now()),(3,'咨询部',now(),now()), (4,'就业部',now(),now()),(5,'人事部',now(),now());
-- 员工管理(带约束)
create table emp (
id int unsigned primary key auto_increment comment 'ID',
username varchar(20) not null unique comment '用户名',
password varchar(32) default '123456' comment '密码',
name varchar(10) not null comment '姓名',
gender tinyint unsigned not null comment '性别, 说明: 1 男, 2 女',
image varchar(300) comment '图像',
job tinyint unsigned comment '职位, 说明: 1 班主任,2 讲师, 3 学工主管, 4 教研主管, 5 咨询师',
entrydate date comment '入职时间',
dept_id int unsigned comment '部门ID',
create_time datetime not null comment '创建时间',
update_time datetime not null comment '修改时间'
) comment '员工表';
INSERT INTO emp
(id, username, password, name, gender, image, job, entrydate,dept_id, create_time, update_time) VALUES
(1,'jinyong','123456','金庸',1,'1.jpg',4,'2000-01-01',2,now(),now()),
(2,'zhangwuji','123456','张无忌',1,'2.jpg',2,'2015-01-01',2,now(),now()),
(3,'yangxiao','123456','杨逍',1,'3.jpg',2,'2008-05-01',2,now(),now()),
(4,'weiyixiao','123456','韦一笑',1,'4.jpg',2,'2007-01-01',2,now(),now()),
(5,'changyuchun','123456','常遇春',1,'5.jpg',2,'2012-12-05',2,now(),now()),
(6,'xiaozhao','123456','小昭',2,'6.jpg',3,'2013-09-05',1,now(),now()),
(7,'jixiaofu','123456','纪晓芙',2,'7.jpg',1,'2005-08-01',1,now(),now()),
(8,'zhouzhiruo','123456','周芷若',2,'8.jpg',1,'2014-11-09',1,now(),now()),
(9,'dingminjun','123456','丁敏君',2,'9.jpg',1,'2011-03-11',1,now(),now()),
(10,'zhaomin','123456','赵敏',2,'10.jpg',1,'2013-09-05',1,now(),now()),
(11,'luzhangke','123456','鹿杖客',1,'11.jpg',5,'2007-02-01',3,now(),now()),
(12,'hebiweng','123456','鹤笔翁',1,'12.jpg',5,'2008-08-18',3,now(),now()),
(13,'fangdongbai','123456','方东白',1,'13.jpg',5,'2012-11-01',3,now(),now()),
(14,'zhangsanfeng','123456','张三丰',1,'14.jpg',2,'2002-08-01',2,now(),now()),
(15,'yulianzhou','123456','俞莲舟',1,'15.jpg',2,'2011-05-01',2,now(),now()),
(16,'songyuanqiao','123456','宋远桥',1,'16.jpg',2,'2007-01-01',2,now(),now()),
(17,'chenyouliang','123456','陈友谅',1,'17.jpg',NULL,'2015-03-21',NULL,now(),now());
2)配置文件application.yml
spring:
#数据库连接信息
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/tlias
username: root
password: root
#文件上传的配置
servlet:
multipart:
max-file-size: 10MB
max-request-size: 100MB
#Mybatis配置
mybatis:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
map-underscore-to-camel-case: true
#阿里云OSS
aliyun:
oss:
endpoint: https://oss-cn-hangzhou.aliyuncs.com
accessKeyId: LTAI4GCH1vX6DKqJWxd6nEuW
accessKeySecret: yBshYweHOpqDuhCArrVHwIiBKpyqSL
bucketName: web-tlias2901
#spring事务管理日志
logging:
level:
org.springframework.jdbc.support.JdbcTransactionManager: debug
3)实体类pojo
Dept.java
package com.itheima.tlias.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
/**
* 部门实体类
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Dept {
private Integer id; //ID
private String name; //部门名称
private LocalDateTime createTime; //创建时间
private LocalDateTime updateTime; //修改时间
}
Emp.java
package com.itheima.tlias.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDate;
import java.time.LocalDateTime;
/**
* 员工实体类
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Emp {
private Integer id; //ID
private String username; //用户名
private String password; //密码
private String name; //姓名
private Short gender; //性别 , 1 男, 2 女
private String image; //图像url
private Short job; //职位 , 1 班主任 , 2 讲师 , 3 学工主管 , 4 教研主管 , 5 咨询师
private LocalDate entrydate; //入职日期
private Integer deptId; //部门ID
private LocalDateTime createTime; //创建时间
private LocalDateTime updateTime; //修改时间
}
PageBean.java
package com.itheima.tlias.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* 分页查询结果封装类
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PageBean {
private Long total; //总记录数
private List rows; //当前数据列表
}
Result.java
package com.itheima.tlias.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result {
private Integer code;//响应码,1 代表成功; 0 代表失败
private String msg; //响应信息 描述字符串
private Object data; //返回的数据
//增删改 成功响应
public static Result success() {
return new Result(1, "success", null);
}
//查询 成功响应
public static Result success(Object data) {
return new Result(1, "success", data);
}
//失败响应
public static Result error(String msg) {
return new Result(0, msg, null);
}
}
4)控制类controller
DeptController.java
package com.itheima.tlias.controller;
import com.itheima.tlias.pojo.Dept;
import com.itheima.tlias.pojo.Result;
import com.itheima.tlias.service.DeptService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 部门管理Controller
*/
@Slf4j
@RestController
@RequestMapping("/depts")
public class DeptController {
// private static Logger log = (Logger) LoggerFactory.getLogger(DeptController.class); ===>@Slf4j
//@RequestMapping(value = "/depts",method = RequestMethod.GET)//指定请求方式为GET ===> @GetMapping("/depts")
@Autowired
private DeptService deptService;
/**
* 查询部门数据
*
* @return
*/
@GetMapping
public Result list() {
log.info("查询全部部门数据");
List<Dept> deptList = deptService.list();
return Result.success(deptList);
}
/**
* 删除部门
*
* @param id
* @return
*/
@DeleteMapping("/{id}")
public Result delete(@PathVariable Integer id) {
log.info("根据id删除部门:{}", id);
deptService.delete(id);
return Result.success();
}
/**
* 新增部门
*
* @param dept
* @return
*/
@PostMapping
public Result add(@RequestBody Dept dept) {
log.info("新增部门:{}", dept);
deptService.add(dept);
return Result.success();
}
/**
* 根据id查询部门
*
* @param id
* @return
*/
@GetMapping("/{id}")
public Result findById(@PathVariable Integer id) {
log.info("根据id查询部门:{}", id);
Dept dept = deptService.findById(id);
if (dept == null) {
return Result.error("Department not found");
}
return Result.success(dept);
}
/**
* 修改部门
* @param dept
* @return
*/
@PutMapping
public Result update(@RequestBody Dept dept){
log.info("新增部门:{}", dept);
boolean isUpdated = deptService.updateDept(dept);
if (isUpdated) {
return Result.success();
} else {
return Result.error("部门不存在,更新失败");
}
}
}
EmpController.java
package com.itheima.tlias.controller;
import com.itheima.tlias.pojo.Emp;
import com.itheima.tlias.pojo.PageBean;
import com.itheima.tlias.pojo.Result;
import com.itheima.tlias.service.EmpService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDate;
import java.util.List;
/**
* 员工管理Controller
*/
@Slf4j
@RestController
@RequestMapping("/emps")
public class EmpController {
@Autowired
private EmpService empService;
/**
*
* @param page
* @param pageSize
* @param name
* @param gender
* @param begin
* @param end
* @return
*/
@GetMapping
public Result page(@RequestParam(defaultValue = "1") Integer page,
@RequestParam(defaultValue = "10") Integer pageSize,
String name, Short gender,
@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,
@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end) {
log.info("条件分页查询,参数:{},{},{},{},{},{}", page, pageSize, name, gender, begin, end);
//
PageBean pageBean = empService.page(page, pageSize, name, gender, begin, end);
return Result.success(pageBean);
}
/**
*
* @param ids
* @return
*/
@DeleteMapping("/{ids}")
public Result delete(@PathVariable List<Integer> ids) {
log.info("批量删除操作,id:{}",ids);
empService.delete(ids);
return Result.success();
}
/**
*
* @param emp
* @return
*/
@PostMapping
public Result add(@RequestBody Emp emp){
log.info("新增员工,emp:{}",emp);
empService.add(emp);
return Result.success(emp);
}
/**
*
* @param id
* @return
*/
@GetMapping("/{id}")
public Result getById(@PathVariable Integer id){
log.info("根据ID查询员工信息, id: {}",id);
Emp emp = empService.getById(id);
return Result.success(emp);
}
/**
*
* @param emp
* @return
*/
@PutMapping
public Result update(@RequestBody Emp emp){
log.info("更新员工信息 : {}", emp);
empService.update(emp);
return Result.success();
}
}
LoginController.java
package com.itheima.tlias.controller;
import com.itheima.tlias.pojo.Emp;
import com.itheima.tlias.pojo.Result;
import com.itheima.tlias.service.EmpService;
import com.itheima.tlias.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@Slf4j
@RestController
public class LoginController {
@Autowired
private EmpService empService;
/**
*
* @param emp
* @return
*/
@PostMapping("/login")
public Result login(@RequestBody Emp emp) {
log.info("员工登录:{}", emp);
Emp e = empService.login(emp);
//登录成功,生成令牌,下发令牌
if (e!=null){
Map<String,Object> claims=new HashMap<>();
claims.put("id",e.getId());
claims.put("name", e.getName());
claims.put("username", e.getUsername());
String jwt= JwtUtils.generateJwt(claims);//jwt包含了当前登录的员工信息
return Result.success(jwt);
}
//登录失败,返回错误信息
return Result.error("用户名或密码错误");
}
}
SessionController.java
package com.itheima.tlias.controller;
import com.itheima.tlias.pojo.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* Cookie、HttpSession演示
*/
@Slf4j
@RestController
public class SessionController {
/**
*
* @param response
* @return
*/
//设置Cookie
@GetMapping("/c1")
public Result cookie1(HttpServletResponse response) {
response.addCookie(new Cookie("login_username", "itheima")); //设置Cookie/响应Cookie
return Result.success();
}
/**
*
* @param request
* @return
*/
//获取Cookie
@GetMapping("/c2")
public Result cookie2(HttpServletRequest request) {
Cookie[] cookies = request.getCookies();
for (Cookie cookie : cookies) {
if (cookie.getName().equals("login_username")) {
System.out.println("login_username: " + cookie.getValue()); //输出name为login_username的cookie
}
}
return Result.success();
}
/**
*
* @param session
* @return
*/
@GetMapping("/s1")
public Result session1(HttpSession session) {
log.info("HttpSession-s1: {}", session.hashCode());
session.setAttribute("loginUser", "tom"); //往session中存储数据
return Result.success();
}
/**
*
* @param request
* @return
*/
@GetMapping("/s2")
public Result session2(HttpServletRequest request) {
HttpSession session = request.getSession();
log.info("HttpSession-s2: {}", session.hashCode());
Object loginUser = session.getAttribute("loginUser"); //从session中获取数据
log.info("loginUser: {}", loginUser);
return Result.success(loginUser);
}
}
UploadController.java
package com.itheima.tlias.controller;
import com.itheima.tlias.pojo.Result;
import com.itheima.tlias.utils.AliOSSUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.util.UUID;
@Slf4j
@RestController
public class UploadController {
@Autowired
private AliOSSUtils aliOSSUtils;
/**
*
* @param image
* @return
* @throws IOException
*/
@PostMapping("/upload")
public Result upload(MultipartFile image) throws IOException {
log.info("文件上传, 文件名: {}", image.getOriginalFilename());
//调用阿里云OSS工具类进行文件上传
String url = aliOSSUtils.upload(image);
log.info("文件上传完成,文件访问的url: {}", url);
return Result.success(url);
}
}
4)接口类:service
DeptService.java
package com.itheima.tlias.service;
import com.itheima.tlias.pojo.Dept;
import java.util.List;
/**
* 部门管理
* */
public interface DeptService {
/**
* 查询全部部门数据
* @Return
* */
List<Dept> list();
/**
* 删除部门
* @param id
*/
void delete(Integer id);
/**
* 新增数据
* @param dept
*/
void add(Dept dept);
/**
* 根据ID查询部门
*
* @param id
* @return
*/
Dept findById(Integer id);
/**
* 修改部门
* @param dept
*/
boolean updateDept(Dept dept);
}
EmpService.java
package com.itheima.tlias.service;
import com.itheima.tlias.pojo.Emp;
import com.itheima.tlias.pojo.PageBean;
import java.time.LocalDate;
import java.util.List;
/**
* 员工管理
* */
public interface EmpService {
/**
* 分页查询
* @param page
* @param pageSize
* @return
*/
// PageBean page(Integer page, Integer pageSize);
/**
*条件查询
* @param page
* @param pageSize
* @param name
* @param gender
* @param begin
* @param end
* @return
*/
PageBean page(Integer page, Integer pageSize, String name, Short gender, LocalDate begin,LocalDate end);
/**
* 批量删除操作
* @param ids
*/
void delete(List<Integer> ids);
/**
* 新增员工
* @param emp
*/
void add(Emp emp);
/**
* 根据ID查询员工
* @param id
* @return
*/
Emp getById(Integer id);
/**
* 更新员工
* @param emp
*/
void update(Emp emp);
/**
*
* @param emp
* @return
*/
public Emp login(Emp emp);
}
DeptServiceImpl.java
package com.itheima.tlias.service.impl;
import com.itheima.tlias.mapper.DeptMapper;
import com.itheima.tlias.mapper.EmpMapper;
import com.itheima.tlias.pojo.Dept;
import com.itheima.tlias.service.DeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.List;
@Service
public class DeptServiceImpl implements DeptService {
@Autowired
private DeptMapper deptMapper;
@Autowired
private EmpMapper empMapper;
@Override
public List<Dept> list() {
return deptMapper.list();
}
@Transactional(rollbackFor = Exception.class)
@Override
public void delete(Integer id) {
deptMapper.deleteById(id);//根据id删除部门数据
empMapper.deleteByDeptId(id);//根据部门id删除该部门下的员工
}
@Override
public void add(Dept dept) {
dept.setCreateTime(LocalDateTime.now());
dept.setUpdateTime(LocalDateTime.now());
deptMapper.insert(dept);
}
@Override
public Dept findById(Integer id) {
Dept deptId = deptMapper.findById(id);
return deptId;
}
@Override
public boolean updateDept(Dept dept) {
dept.setUpdateTime(LocalDateTime.now());
Dept existingDept = deptMapper.findById(dept.getId());
if (existingDept == null) {
return false;
}
int result = deptMapper.update(dept);
return result > 0;
}
}
EmpServiceImpl.java
package com.itheima.tlias.service.impl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.itheima.tlias.mapper.EmpMapper;
import com.itheima.tlias.pojo.Emp;
import com.itheima.tlias.pojo.PageBean;
import com.itheima.tlias.service.EmpService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
@Service
public class EmpServiceImpl implements EmpService {
@Autowired
private EmpMapper empMapper;
/**
* 员工分页查询
* @param page
* @param pageSize
* @return
*/
@Override
public PageBean page(Integer page, Integer pageSize, String name, Short gender, LocalDate begin, LocalDate end) {
//1.设置分页参数
PageHelper.startPage(page, pageSize);
//2.执行查询
List<Emp> empList = empMapper.list(name, gender, begin, end);
Page<Emp> p = (Page<Emp>) empList;
//3.封装PageBean对象
PageBean pageBean = new PageBean(p.getTotal(), p.getResult());
return pageBean;
}
@Override
public void delete(List<Integer> ids) {
empMapper.delete(ids);
}
@Override
public void add(Emp emp) {
emp.setCreateTime(LocalDateTime.now());
emp.setUpdateTime(LocalDateTime.now());
empMapper.insert(emp);
}
@Override
public Emp getById(Integer id) {
return empMapper.getById(id);
}
@Override
public void update(Emp emp) {
emp.setUpdateTime(LocalDateTime.now());
empMapper.update(emp);
}
@Override
public Emp login(Emp emp) {
Emp e = empMapper.getByUsernameAndPassword(emp);
return e;
}
}
5)持久层:mapper
DeptMapper.java
package com.itheima.tlias.mapper;
import com.itheima.tlias.pojo.Dept;
import org.apache.ibatis.annotations.*;
import java.util.List;
/**
* 部门管理
*/
@Mapper
public interface DeptMapper {
/**
* 查询全部部门
* @Return
* */
@Select("select * from dept")
List<Dept> list();
/**
* 根据ID删除部门
* @param id
*/
@Delete("delete from dept where id=#{id}")
void deleteById(Integer id);
/**
* 新增部门
* @param dept
*/
@Insert("insert into dept(name,create_time,update_time) values (#{name},#{createTime},#{updateTime}) ")
void insert(Dept dept);
/**
* 根据id查询部门
*
* @param id
* @return
*/
@Select("select id from dept where id=#{id}")
Dept findById(Integer id);
/**
* 修改部门
* @param dept
*/
@Update("update dept set name=#{name} ,update_time = #{updateTime} where id=#{id} ")
int update(Dept dept);
}
EmpMapper.java
package com.itheima.tlias.mapper;
import com.itheima.tlias.pojo.Emp;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.time.LocalDate;
import java.util.List;
/**
* 员工管理
*/
@Mapper
public interface EmpMapper {
// /**
// * 查询记录数
// * @return
// */
// @Select("select count(*) from emp")
// Long count();
//
// /**
// * 分页查询,获取列表数
// * @param start
// * @param pagesize
// * @return
// */
// @Select("select * from emp limit #{start},#{pagesize}")
// List<Emp> page(Integer start,Integer pagesize);
// ================================================
/**
* 分页查询
* @return
*/
// @Select("select * from emp")
// public List<Emp> list();
/**
* 条件分页查询
*
* @param name
* @param gender
* @param begin
* @param end
* @return
*/
public List<Emp> list(String name, Short gender, LocalDate begin, LocalDate end);
/**
* 批量删除
*
* @param ids
*/
void delete(List<Integer> ids);
/**
* 新增员工
*
* @param emp
*/
@Insert("insert into emp(username, name, gender, image, job, entrydate, dept_id, create_time, update_time) " +
"values (#{username},#{name},#{gender},#{image},#{job},#{entrydate},#{deptId},#{createTime},#{updateTime})")
void insert(Emp emp);
/**
* 根据ID查询员工
*
* @param id
* @return
*/
@Select("select * from emp where id = #{id}")
Emp getById(Integer id);
/**
* 更新员工
*
* @param emp
*/
void update(Emp emp);
/**
* 登录操作
* @param emp
* @return
*/
@Select("select * from emp where username=#{username} and password=#{password}")
Emp getByUsernameAndPassword(Emp emp);
/**
* 根据部门id来删除部门下的员工数据
* @param deptId
*/
@Delete("delete from emp where dept_id=#{deptId}")
void deleteByDeptId(Integer deptId);
}
EmpMapper.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.itheima.tlias.mapper.EmpMapper">
<!-- 更新员工 -->
<update id="update">
update emp
<set>
<if test="username != null and username != ''"> username = #{username}, </if>
<if test="password != null and password != ''"> password = #{password}, </if>
<if test="name != null and name != ''"> name = #{name}, </if>
<if test="gender != null"> gender = #{gender}, </if>
<if test="image != null and image != ''"> image = #{image}, </if>
<if test="job != null"> job = #{job}, </if>
<if test="entrydate != null"> entrydate = #{entrydate}, </if>
<if test="deptId != null"> dept_id = #{deptId}, </if>
<if test="updateTime != null"> update_time = #{updateTime} </if>
</set>
where id = #{id}
</update>
<!-- 批量删除语句-->
<delete id="delete">
delete
from emp
where id in
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</delete>
<!--条件查询-->
<select id="list" resultType="com.itheima.tlias.pojo.Emp">
select *
from emp
<where>
<if test="name!=null">
name like concat('%', #{name}, '%')
</if>
<if test="gender!=null">
and gender = #{gender}
</if>
<if test="begin!=null and end!=null">
and entrydate between #{begin} and #{end}
</if>
</where>
order by update_time desc
</select>
</mapper>
6)文件处理
package com.itheima.tlias.Filter;
import com.alibaba.fastjson.JSONObject;
import com.itheima.tlias.pojo.Result;
import com.itheima.tlias.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Slf4j
@WebFilter(urlPatterns = "/*")
public class LoginCheckFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
//1.获取请求url。
String url = req.getRequestURL().toString();
log.info("请求的url: {}",url);
//2.判断请求url中是否包含login,如果包含,说明是登录操作,放行。
if(url.contains("login")){
log.info("登录操作, 放行...");
chain.doFilter(request,response);
return;
}
//3.获取请求头中的令牌(token)。
String jwt = req.getHeader("token");
//4.判断令牌是否存在,如果不存在,返回错误结果(未登录)。
if(!StringUtils.hasLength(jwt)){
log.info("请求头token为空,返回未登录的信息");
Result error = Result.error("NOT_LOGIN");
//手动转换 对象--json --------> 阿里巴巴fastJSON
String notLogin = JSONObject.toJSONString(error);
resp.getWriter().write(notLogin);
return;
}
//5.解析token,如果解析失败,返回错误结果(未登录)。
try {
JwtUtils.parseJWT(jwt);
} catch (Exception e) {//jwt解析失败
e.printStackTrace();
log.info("解析令牌失败, 返回未登录错误信息");
Result error = Result.error("NOT_LOGIN");
//手动转换 对象--json --------> 阿里巴巴fastJSON
String notLogin = JSONObject.toJSONString(error);
resp.getWriter().write(notLogin);
return;
}
//6.放行。
log.info("令牌合法, 放行");
chain.doFilter(request, response);
}
}
7)异常处理
package com.itheima.tlias.exception;
import com.itheima.tlias.pojo.Result;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* 全局异常处理器
*/
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)//捕获所有异常
public Result ex(Exception ex){
ex.printStackTrace();
return Result.error("对不起,操作失败,请联系管理员");
}
}
8)interceptor
package com.itheima.tlias.interceptor;
import com.alibaba.fastjson.JSONObject;
import com.itheima.tlias.pojo.Result;
import com.itheima.tlias.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Slf4j
@Component
public class LoginCheckInterceptor implements HandlerInterceptor {
@Override //目标资源方法运行前运行, 返回true: 放行, 放回false, 不放行
public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) throws Exception {
//1.获取请求url。
String url = req.getRequestURL().toString();
log.info("请求的url: {}",url);
//2.判断请求url中是否包含login,如果包含,说明是登录操作,放行。
if(url.contains("login")){
log.info("登录操作, 放行...");
return true;
}
//3.获取请求头中的令牌(token)。
String jwt = req.getHeader("token");
//4.判断令牌是否存在,如果不存在,返回错误结果(未登录)。
if(!StringUtils.hasLength(jwt)){
log.info("请求头token为空,返回未登录的信息");
Result error = Result.error("NOT_LOGIN");
//手动转换 对象--json --------> 阿里巴巴fastJSON
String notLogin = JSONObject.toJSONString(error);
resp.getWriter().write(notLogin);
return false;
}
//5.解析token,如果解析失败,返回错误结果(未登录)。
try {
JwtUtils.parseJWT(jwt);
} catch (Exception e) {//jwt解析失败
e.printStackTrace();
log.info("解析令牌失败, 返回未登录错误信息");
Result error = Result.error("NOT_LOGIN");
//手动转换 对象--json --------> 阿里巴巴fastJSON
String notLogin = JSONObject.toJSONString(error);
resp.getWriter().write(notLogin);
return false;
}
//6.放行。
log.info("令牌合法, 放行");
return true;
}
@Override //目标资源方法运行后运行
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle ...");
}
@Override //视图渲染完毕后运行, 最后运行
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion...");
}
}
9)util类
AliOSSProperties
package com.itheima.tlias.utils;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Data
@Component
@ConfigurationProperties(prefix = "aliyun.oss")
public class AliOSSProperties {
private String endpoint;
private String accessKeyId;
private String accessKeySecret;
private String bucketName;
}
AliOSSUtils
package com.itheima.tlias.utils;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;
/**
* 阿里云 OSS 工具类
*/
@Component
public class AliOSSUtils {
// @Value("${aliyun.oss.endpoint}")
// private String endpoint ;
// @Value("${aliyun.oss.accessKeyId}")
// private String accessKeyId ;
// @Value("${aliyun.oss.accessKeySecret}")
// private String accessKeySecret ;
// @Value("${aliyun.oss.bucketName}")
// private String bucketName ;
@Autowired
private AliOSSProperties aliOSSProperties;
/**
* 实现上传图片到OSS
*/
public String upload(MultipartFile file) throws IOException {
//获取阿里云OSS参数
String endpoint = aliOSSProperties.getEndpoint();
String accessKeyId = aliOSSProperties.getAccessKeyId();
String accessKeySecret = aliOSSProperties.getAccessKeySecret();
String bucketName = aliOSSProperties.getBucketName();
// 获取上传的文件的输入流
InputStream inputStream = file.getInputStream();
// 避免文件覆盖
String originalFilename = file.getOriginalFilename();
String fileName = UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."));
//上传文件到 OSS
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
ossClient.putObject(bucketName, fileName, inputStream);
//文件访问路径
String url = endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + fileName;
// 关闭ossClient
ossClient.shutdown();
return url;// 把上传到oss的路径返回
}
}
JwtUtils
package com.itheima.tlias.utils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
import java.util.Map;
public class JwtUtils {
private static String signKey = "itheima";
private static Long expire = 43200000L;
/**
* 生成JWT令牌
* @param claims JWT第二部分负载 payload 中存储的内容
* @return
*/
public static String generateJwt(Map<String, Object> claims){
String jwt = Jwts.builder()
.addClaims(claims)
.signWith(SignatureAlgorithm.HS256, signKey)
.setExpiration(new Date(System.currentTimeMillis() + expire))
.compact();
return jwt;
}
/**
* 解析JWT令牌
* @param jwt JWT令牌
* @return JWT第二部分负载 payload 中存储的内容
*/
public static Claims parseJWT(String jwt){
Claims claims = Jwts.parser()
.setSigningKey(signKey)
.parseClaimsJws(jwt)
.getBody();
return claims;
}
}
10)启动类
TliasApplication.java
package com.itheima.tlias;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
@ServletComponentScan//开启了对servlet组件的支持
@SpringBootApplication
public class TliasApplication {
public static void main(String[] args) {
SpringApplication.run(TliasApplication.class, args);
}
}
参考文献
1.SSM框架讲解(史上最详细的文章)_ssm架构-CSDN博客
2.黑马程序员JavaWeb开发教程,实现javaweb企业开发全流程(涵盖Spring+MyBatis+SpringMVC+SpringBoot等)-哔哩哔哩