一、前言:
本程序为学习springboot、mybatis时的练手项目,前端代码(nginx部分)来自黑马程序员,后端代码学习自黑马程序员视频,由本人编写。
二、项目实现功能:
部门、员工的插、删、改、查功能,登录功能
三、项目演示:
四、项目亮点:
本项目虽为练手项目代码并不复杂、业务功能比较简单,但其功能较为丰富,实现了登录校验、文件存储(使用aliyun云存储)、分层结构实现、前后端分离设计模式、对于数据库的插、删、改、查基本操作,分页查询等功能。
五、代码展示:
com/example/test01/config
WebConfig.java(拦截器配置)
@Configuration public class WebConfig implements WebMvcConfigurer { @Autowired private LoginCheckInterceptor loginCheckInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(loginCheckInterceptor). addPathPatterns("/**").excludePathPatterns("/login"); } }
com/example/test01/controller
DeptController.java
@Slf4j @RestController @RequestMapping("/depts") public class DeptController { //获取日志 固定代码 // public static Logger log = LoggerFactory.getLogger(DeptController.class);可以简化为注解@Slf4j @Autowired private DeptService deptService; //@RequestMapping(value = "/depts",method = RequestMethod.GET)可以简化为@GetMapping... @GetMapping public Result list(){ List<Dept> deptList = deptService.list(); log.info("查询全部部门数据"); return Result.success(deptList); } //删除部门数据 @DeleteMapping("/{id}") public Result delete(@PathVariable Integer id){ log.info("根据id删除部门{}",id); deptService.delete(id); return Result.success(); } //新增部门 @PostMapping public Result add(@RequestBody Dept dept){ log.info("新增部门{}",dept); deptService.add(dept); return Result.success(); } @GetMapping("/{id}") public Result listById(@PathVariable Integer id){ log.info("查询部门{}",id); Dept dept = deptService.listById(id); return Result.success(dept); } @PutMapping public Result update(@RequestBody Dept dept){ log.info("修改部门{}",dept.getId()); deptService.update(dept); return Result.success(); } }
EmpController.java
@Slf4j @RestController public class EmpController { @Autowired private EmpService empService; @GetMapping("/emps") 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); PageBean pageBean = empService.page(page,pageSize,name,gender,begin,end); return Result.success(pageBean); } @DeleteMapping("/emps/{ids}") public Result delete(@PathVariable List<Integer> ids){ log.info("批量删除",ids); empService.delete(ids); return Result.success(); } @PostMapping("/emps") public Result sava(@RequestBody Emp emp){ log.info("新增员工",emp); empService.save(emp); return Result.success(); } @GetMapping("/emps/{id}") public Result getById(@PathVariable Integer id){ log.info("根据id查询信息{}",id); Emp emp = empService.getById(id); return Result.success(emp); } @PutMapping("/emps") public Result update(@RequestBody Emp emp){ log.info("更新员工{}",emp); empService.update(emp); return Result.success(); } }
LoginController.java
@Slf4j @RestController public class LoginController { @Autowired private EmpService empService; @PostMapping("/login") public Result login(@RequestBody Emp emp){ log.info("员工登录{}",emp); Emp e = empService.login(emp); if (e != null){ HashMap<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); return Result.success(jwt); } return Result.error("登陆失败"); } }
UploadController.java
@Slf4j @RestController public class UploadController { @Autowired private AliOSSUtils aliOSSUtils; // @PostMapping("/upload") // public Result upload(String username, Integer age, MultipartFile image) throws Exception { // log.info("文件上传{},{},{}", username, age, image); // //获取文件名字 // String originalFilename = image.getOriginalFilename(); // //构造唯一名字uuid // int i = originalFilename.lastIndexOf("."); // String s = originalFilename.substring(i); // String newFileName = UUID.randomUUID().toString() + s; // image.transferTo(new File("F:\\images\\" + newFileName)); // return Result.success(); // } @PostMapping("/upload") public Result upload(MultipartFile image) throws IOException { log.info("文件上传{}", image.getOriginalFilename()); String url = aliOSSUtils.upload(image); log.info("文件上传成功{}",url); return Result.success(url); } }
com/example/test01/exception
GlobalExcepionHandler.java(全局异常处理)
@RestControllerAdvice public class GlobalExcepionHandler { @ExceptionHandler(Exception.class) public Result ex(Exception ex){ ex.printStackTrace(); return Result.error("处理失败,请联系管理员"); } }
com/example/test01/interceptor
LoginCheckInterceptor.java(拦截器)
@Slf4j @Component public class LoginCheckInterceptor implements HandlerInterceptor { //目标资源前运行 true放行 @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String url = request.getRequestURL().toString(); log.info("url{}", url); if (url.contains("login")) { log.info("放行"); return true; } String jwt = request.getHeader("token"); if (!StringUtils.hasLength(jwt)) { log.info("请求头为空"); Result error = Result.error("NOT_LOGIN"); String notLogin = JSONObject.toJSONString(error); response.getWriter().write(notLogin); return false; } try { JwtUtils.parseJWT(jwt); } catch (Exception e) { e.printStackTrace(); log.info("解析令牌失败"); Result error = Result.error("NOT_LOGIN"); String notLogin = JSONObject.toJSONString(error); response.getWriter().write(notLogin); return false; } 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运行"); } }
com/example/test01/mapper
DeptMapper.java
@Mapper public interface DeptMapper { @Select("select * from dept") List<Dept> list(); @Delete("delete from dept where id = #{id}") void deleteById(Integer id); @Insert("insert into dept(name, create_time, update_time) values (#{name},#{createTime},#{updateTime})") void insert(Dept dept); @Select("select id,name,create_time,update_time from dept where id = #{id}") Dept selectById(Integer id); @Update("update dept set name = #{name},update_time = #{updateTime} where id = #{id}") void update(Dept dept); }
EmpMapper.java
@Mapper public interface EmpMapper { // @Select("select count(*) from emp") // Long count(); // // @Select("select * from emp limit #{start},#{pageSize}") // List<Emp> Page(Integer start, Integer pageSize); public List<Emp> list(String name, Short gender, LocalDate begin, LocalDate end); void delete(List<Integer> ids); @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); @Select("select * from emp where id = #{id}") Emp getById(Integer id); void update(Emp emp); @Select("select * from emp where username = #{username} and password = #{password}") Emp getByUserAndPassword(Emp emp); @Delete("delete from emp where dept_id = #{EmpId}") void deleteByEmpId(Integer EmpId); }
com/example/test01/pojo
Dept.java
@Data //使用lombok依赖 @NoArgsConstructor @AllArgsConstructor public class Dept { private Integer id; //ID private String name; //部门名称 private LocalDateTime createTime; //创建时间 private LocalDateTime updateTime; //修改时间 }
DeptLog.java
@Data @NoArgsConstructor @AllArgsConstructor public class DeptLog { private Integer id; private LocalDateTime createTime; private String description; }
Emp.java
@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
@Data @NoArgsConstructor @AllArgsConstructor public class PageBean { private Long total; private List rows; }
Result.java
@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); } }
com/example/test01/service
DeptService.java
public interface DeptService { List<Dept> list(); void delete(Integer id); void add(Dept dept); Dept listById(Integer id); void update(Dept dept); }
EmpService.java
public interface EmpService { PageBean page(Integer page, Integer pageSize, String name, Short gender, LocalDate begin, LocalDate end); void delete(List<Integer> ids); void save(Emp emp); Emp getById(Integer id); void update(Emp emp); Emp login(Emp emp); }
com/example/test01/service/impl
DeptServiceImpl.java
@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,propagation = Propagation.REQUIRED) @Override public void delete(Integer id) { deptMapper.deleteById(id); empMapper.deleteByEmpId(id); } @Override public void add(Dept dept) { dept.setCreateTime(LocalDateTime.now()); dept.setUpdateTime(LocalDateTime.now()); deptMapper.insert(dept); } @Override public Dept listById(Integer id) { Dept dept = deptMapper.selectById(id); return dept; } @Override public void update(Dept dept) { dept.setUpdateTime(LocalDateTime.now()); deptMapper.update(dept); } }
EmpServiceImpl.java
@Service public class EmpServiceImpl implements EmpService { @Autowired private EmpMapper empMapper; @Override public PageBean page(Integer page, Integer pageSize, String name, Short gender, LocalDate begin, LocalDate end) { PageHelper.startPage(page, pageSize); List<Emp> list = empMapper.list(name, gender, begin, end); Page<Emp> p = (Page<Emp>) list; PageBean pageBean = new PageBean(p.getTotal(), p.getResult()); return pageBean; } @Override public void delete(List<Integer> ids) { empMapper.delete(ids); } @Override public void save(Emp emp) { emp.setCreateTime(LocalDateTime.now()); emp.setUpdateTime(LocalDateTime.now()); empMapper.insert(emp); } @Override public Emp getById(Integer id) { Emp emp = empMapper.getById(id); return emp; } @Override public void update(Emp emp) { emp.setUpdateTime(LocalDateTime.now()); empMapper.update(emp); } @Override public Emp login(Emp emp) { return empMapper.getByUserAndPassword(emp); } }
com/example/test01/utils
AliOSSProperties.java
@Data @Component @ConfigurationProperties(prefix = "aliyun.oss") public class AliOSSProperties { private String endpoint; private String accessKeyId; private String accessKeySecret; private String bucketName; }
AliOSSUtils.java
@Component public class AliOSSUtils { @Autowired private AliOSSProperties aliOSSProperties; /** * 实现上传图片到OSS */ public String upload(MultipartFile file) throws IOException { 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.java
public class JwtUtils { private static String signKey = "itlsj01"; 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.HS384, 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; } }
Test01Application.java
@ServletComponentScan @SpringBootApplication public class Test01Application { public static void main(String[] args) { SpringApplication.run(Test01Application.class, args); } }
resourses/com/example/test01/mapper
EmpMapper.xml //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.example.test01.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.example.test01.pojo.Emp"> select * from emp <where> <if test="name != null and name != ''"> 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>
application.yml
#数据库连接信息 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/db01 username: root password: hsp servlet: multipart: max-file-size: 10MB max-request-size: 100MB ##配置mybatis的日志, 指定输出到控制台 # mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl # #开启mybatis的驼峰命名自动映射开关 a_column ------> aCloumn # mybatis.configuration.map-underscore-to-camel-case=true mybatis: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl map-underscore-to-camel-case: true ##单个文件上传最大大小 默认1m # spring.servlet.multipart.max-file-size=10MB # #单个请求上传最大大小 10m # spring.servlet.multipart.max-request-size=100MB aliyun: oss: endpoint: https:://oss-cn-beijing:aliyuncs:com accessKeyId: LTAI5tQsT3w445uDxVZWLxtb accessKeySecret: EwzzEVKyfo8BpQpUDp72c3MgpYtABe bucketName: web-tlias0111 # #阿里云配置文件 # aliyun.oss.endpoint=https://oss-cn-beijing.aliyuncs.com # aliyun.oss.accessKeyId=LTAI5tQsT3w445uDxVZWLxtb # aliyun.oss.accessKeySecret=EwzzEVKyfo8BpQpUDp72c3MgpYtABe # aliyun.oss.bucketName=web-tlias0111 #spring事务管理日志 logging: level: org.springframework.jdbc.support.JdbcTransactionManager: debug
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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <!-- 父程序--> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.12</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>Test01</artifactId> <version>0.0.1-SNAPSHOT</version> <name>Test01</name> <description>Demo project for Spring Boot</description> <properties> <java.version>11</java.version> </properties> <dependencies> <!-- springboot依赖--> <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.3.1</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.6</version> </dependency> <!-- 阿里云依赖--> <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> <!-- gwt令牌--> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.83</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <excludes> <exclude> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </exclude> </excludes> </configuration> </plugin> </plugins> </build> </project>
前端文件:链接:https://pan.baidu.com/s/1eFRPvd5I9MPTKlwgJkuu4Q
提取码:gxcs
后端代码:链接:https://pan.baidu.com/s/1jC4nkkqEACclyn5sGo4xfQ
提取码:esih
六、项目心得:
本项目提升了笔者对于springboot、mybatis开发流程的理解和认识,通过本项目笔者学习了关于springboot、mybatis的许多知识,了解了各种依赖和注解的使用,提高了本人的编程和理解能力。