1. Spring复习

Spring主要是创建对象和管理对象的框架。

Spring通过DI实现了IoC。

Spring能很大程度的实现解耦。

需要掌握SET方式注入属性的值。

需要理解自动装配。

需要掌握Spring表达式。

需要掌握AOP(暂时没学)。

2. Spring MVC复习

Spring MVC框架是解决了V-C交互的问题,即:服务器端如何接收客户端的请求,并如何给予响应。

需要掌握如何接收请求参数。

需要掌握如何转发数据。

需要掌握转发与重定向。

需要掌握响应JSON数据。

需要掌握统一处理异常的做法。

需要掌握拦截器的使用。

3. MyBatis复习

执行增删改的操作的方法应该返回Integer,表示受影响的行数;

执行查询方法的<select>节点必须配置resultTyperesultMap

执行查询时如果列名与字段名不一致,在查询时需要自定义别名,以保证名称统一;

掌握<resultMap>的配置。

--------------------------------------

1. 项目开发流程

关于项目的开发,首先应该确定需要处理的数据有哪些:商品,用户,收藏,订单,购物车,商品分类,收货地址……

然后,确定这些数据的开发、管理的先后顺序,因为某些数据是必须建立在其它数据基础之上的,例如必须先有用户数据,才可以有订单数据或收货地址数据,另外,不同的数据功能,开发的难度也有差异,应该尽可能的先开发简单的、熟悉的数据功能,然后再开发相对较难的数据功能,所以,以上数据的开发顺序大概可以是:用户 > 收货地址 > 商品分类 > 商品 > 收藏 > 购物车 > 订单……

每种类型的数据的处理,都应该遵循:增 > 查 > 删 > 改。

每个功能的处理,应该:持久层 > 业务层 > 控制器层 > 界面。

核心原则:一次只解决一个问题!

2. 用户-注册-持久层

关于持久层,应该先检查有没有对应的数据库/表,及对应的实体类。

关于数据库:

CREATE DATABASE tedu_store;

USE tedu_store;

关于数据表:

CREATE TABLE t_user (
uid INT AUTO_INCREMENT COMMENT '用户id',
username VARCHAR(20) UNIQUE NOT NULL COMMENT '用户名',
password CHAR(32) NOT NULL COMMENT '密码',
salt CHAR(36) COMMENT '盐',
gender INT COMMENT '性别,0-女,1-男',
avatar VARCHAR(50) COMMENT '头像',
phone VARCHAR(20) COMMENT '手机号码',
email VARCHAR(30) COMMENT '电子邮箱',
is_delete INT COMMENT '是否已删除,0-未删除,1-已删除',
created_user VARCHAR(20) COMMENT '创建者',
created_time DATETIME COMMENT '创建时间',
modified_user VARCHAR(20) COMMENT '修改者',
modified_time DATETIME COMMENT '修改时间',
PRIMARY KEY(uid)
) DEFAULT CHARSET=UTF8;

然后,下载本次项目store.zip,解压到Workspace中,通过Import > Existing Maven Projects导入项目。(可以在spring boot 官网自己生成)

由于以上数据表中关于日志的4个字段是后续每张表都应该有的,则后续的每张表对应的实体类中也应该有4个对应的属性,所以,应该创建实体类的基类来封装这4个字段对应的属性,且,当前项目中的所有实体类都应该继承自该基类:

/**
* 实体类的基类
*/
public abstract class BaseEntity implements Serializable { private static final long serialVersionUID = -6185124879935579311L; private String createdUser;
private Date createdTime;
private String modifiedUser;
private Date modifiedTime; // SET/GET ... }

创建与数据表对应的实体类cn.tedu.store.entity.User

/**
* 用户数据的实体类
*/
public class User extends BaseEntity { private static final long serialVersionUID = 8777086855777796877L; private Integer uid;
private String username;
private String password;
private String salt;
private Integer gender;
private String avatar;
private String phone;
private String email;
private Integer isDelete; // SET/GET ...
}

持久层的开发重点应该分为3个步骤:

1. 分析当前功能所需要执行的SQL语句

当前执行“注册”功能,必然需要执行插入数据操作:

INSERT INTO t_user (
username, password ... modified_time
) VALUES (
?, ?, ... ?
)

为了保证“用户名唯一”,还应该有“根据用户名查询数据”的操作:

SELECT
uid
FROM
t_user
WHERE
username=?

2. 创建接口(如果必要的话),并设计抽象方法

创建cn.tedu.store.mapper.UserMapper接口文件,并在其中添加抽象方法:

/**
* 处理用户数据的持久层接口
*/
public interface UserMapper { /**
* 插入用户数据
* @param user 用户数据
* @return 受影响的行数
*/
Integer addnew(User user); /**
* 根据用户名查询用户信息
* @param username 用户名
* @return 匹配的用户数据,如果没有匹配的数据,则返回null
*/
User findByUsername(String username);
}

3. 在XML中配置抽象方法的映射

src/main/resources下创建mappers文件夹,然后复制此前的项目得到UserMapper.xml,配置好该文件中根节点的namespace对应的接口,然后,再配置以上2个抽象方法对应的映射:

<mapper namespace="cn.tedu.store.mapper.UserMapper">

    <!-- 插入用户数据 -->
<!-- Integer addnew(User user) -->
<insert id="addnew">
INSERT INTO t_user (
username, password,
salt, gender,
phone, email,
avatar, is_delete,
created_user, created_time,
modified_user, modified_time
) VALUES (
#{username}, #{password},
#{salt}, #{gender},
#{phone}, #{email},
#{avatar}, #{isDelete},
#{createdUser}, #{createdTime},
#{modifiedUser}, #{modifiedTime}
)
</insert> <!-- 根据用户名查询用户信息 -->
<!-- User findByUsername(String username) -->
<select id="findByUsername"
resultType="cn.tedu.store.entity.User">
SELECT
uid
FROM
t_user
WHERE
username=#{username}
</select> </mapper>

注意:此次并没有在接口文件之前添加@Mapper注解,由于这个注解是添加在接口之前的,则项目中可能出现的多个持久层接口都需要添加该注解,管理起来比较麻烦,所以,改为在执行程序StoreApplication之前添加@MapperScan("cn.tedu.store.mapper")注解,以指定持久层接口所在的包,则后续每个持久层接口都不必再添加@Mapper注解。

最后,在src/test/java下,创建cn.tedu.store.mapper.UserMapperTestCase测试类:

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserMapperTestCase { @Autowired
private UserMapper mapper; @Test
public void addnew() {
User user = new User();
user.setUsername("root");
user.setPassword("1234");
Integer rows = mapper.addnew(user);
System.err.println("rows=" + rows);
} @Test
public void findByUsername() {
String username = "root";
User user = mapper.findByUsername(username);
System.err.println(user);
} }

3. 用户-注册-业务层

业务层的开发通常也是3个步骤来完成!

1. 规划异常

业务层中的方法的返回值,仅以操作成功为标准,判断是否需要返回某种数据。

由于返回值并不体现操作成功与否,则还需要考虑失败的情况,并抛出对应的异常,通常,建议自定义异常,针对不同的操作错误(操作失败的原因)抛出不同的异常,并且,这些异常都应该继承自RuntimeException(原因后续再讲)。实际做法是自定义ServiceException,是继承自RuntimeException的,而其它自定义的异常都继承自ServiceException

/**
* 业务异常,当前项目中自定义异常类的基类
*/
public class ServiceException extends RuntimeException { private static final long serialVersionUID = 980104530291206274L; public ServiceException() {
super();
} public ServiceException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
} public ServiceException(String message, Throwable cause) {
super(message, cause);
} public ServiceException(String message) {
super(message);
} public ServiceException(Throwable cause) {
super(cause);
} }

然后,本次的“注册”功能可能抛出“用户名被占用”和“插入数据失败”错误,则需要创建对应的异常UserConflictExceptionInsertException以备抛出。

2. 在业务层接口中声明抽象方法

在业务层中声明的方法是被控制器层(Controller)调用的,且在实现业务层功能时,需要调用持久层对象中的方法,所以,在参数方面,应该是承上启下的,即:能满足调用和被调用的需求。

创建业务层接口cn.tedu.store.service.IUserService接口,并添加抽象方法:

void reg(User user)
throws UserConflictException, InsertException;

3. 实现接口中的抽象方法

创建cn.tedu.store.service.impl.UserServiceImpl类,实现IUserService接口,在类中声明持久层对象@Autowired private UserMapper userMapper;,在类之前添加@Service注解:

@Service
public class UserServiceImpl
implements IUserService { @Autowired
private UserMapper userMapper; @Override
public void reg(User user) throws UserConflictException, InsertException {
// TODO Auto-generated method stub } }

通常,应该把持久层中声明的抽象方法复制到业务层的实现类中,并且通过持久层对象直接调用来实现方法的功能,这些方法应该是私有的,如果是查询类的方法,应该直接返回调用持久层方法的返回结果,如果是增删改的方法,应该将方法的返回值修改为void,并且,在方法体中,判断调用时的返回结果,如果结果不符合预期,则抛出异常。

基于以上原则,应该在业务层的实现类中添加:

/**
* 插入用户数据
* @param user 用户数据
* @return 受影响的行数
*/
private void addnew(User user) {
Integer rows = userMapper.addnew(user);
if (rows != 1) {
throw new InsertException("增加用户数据时出现未知错误!请联系系统管理员!");
}
} /**
* 根据用户名查询用户信息
* @param username 用户名
* @return 匹配的用户数据,如果没有匹配的数据,则返回null
*/
private User findByUsername(String username) {
return userMapper.findByUsername(username);
}

然后,重写接口中定义的抽象方法,在编写时,应该先分析过程,然后再编写代码:

@Override
public void reg(User user) throws UserConflictException, InsertException {
// 根据user.getUsername()获取用户名匹配的数据
// 检查数据是否为null
// 是:为null,用户名未被占用,则应该补全参数中的属性值
// - 1. 密码加密,并封装
// - 2. 封装salt
// - 3. 封装isDelete,固定为0
// - 4. 封装4项日志数据
// - 执行注册:addnew(user)
// 否:非null,用户名被占用,则抛出UserConflictException
}

分析完成,编写可以完成的部分的代码(暂不包括密码加密与salt的处理):

@Override
public void reg(User user) throws UserConflictException, InsertException {
// 根据user.getUsername()获取用户名匹配的数据
String username = user.getUsername();
User data = findByUsername(username);
// 检查数据是否为null
if (data == null) {
// 是:为null,用户名未被占用,则应该补全参数中的属性值
// TODO - 1. 密码加密,并封装
// TODO - 2. 封装salt
// - 3. 封装isDelete,固定为0
user.setIsDelete(0);
// - 4. 封装4项日志数据
Date now = new Date();
user.setCreatedTime(now);
user.setModifiedTime(now);
user.setCreatedUser(username);
user.setModifiedUser(username);
// - 执行注册:addnew(user)
addnew(user);
} else {
// 否:非null,用户名被占用,则抛出UserConflictException
throw new UserConflictException(
"注册失败!您尝试注册的用户名(" + username + ")已经被占用!");
}
}

完成后,仍编写对应的单元测试:

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserServiceTestCase { @Autowired
private IUserService service; @Test
public void reg() {
try {
User user = new User();
user.setUsername("admin");
user.setPassword("8888");
user.setPhone("13800138001");
user.setEmail("admin@tedu.cn");
user.setGender(1);
user.setAvatar("http://www.tedu.cn/logo.png");
service.reg(user);
System.err.println("OK.");
} catch (ServiceException e) {
System.err.println(e.getMessage());
}
} }

4. 用户-注册-控制器层

5. 用户-注册-界面

spring boot 搭建基本套路《1》的更多相关文章

  1. Set up HTTP/2 server with Spring Boot 【基于Spring boot搭建http2.0服务器】

    1. Server side With spring boot, we can set up a http server easily. Restcontroller make it easier t ...

  2. maven 聚合工程 用spring boot 搭建 spring cloud 微服务 模块式开发项目

    项目的简单介绍: 项目采用maven聚合工程 用spring boot 搭建 spring cloud的微服务 模块式开发 项目的截图: 搭建开始: 能上图 我少打字 1.首先搭建maven的聚合工程 ...

  3. 自我救赎 → 利用 IDEA 和 Spring Boot 搭建 SSM

    前言 开心一刻 儿子读高中放学回来了,一向不管他学习的我突然来了兴趣,想看看他的学习他的状况,抄起他的数学习题看了起来,当看到 1 x 2 x 3 x 4 x 5 x 6 x 7 x 8 x 9 x ...

  4. 记录一次Spring boot 搭建框架连接Mysql数据库注解事务不回滚的故障

    搭建了一个新框架,使用了spring boot 替换以简化原来繁杂的spring配置,使用Spring注解管理事务,持久层使用mybatis. 连接mysql数据库完成项目的过程中发现不支持事务,因为 ...

  5. 使用Spring Boot搭建应用开发框架(一) —— 基础架构

    Spring的简史 第一阶段:XML配置,在Spring1.x时代,使用Spring开发满眼都是xml配置的Bean,随着项目的扩大,我们需要把xml配置文件分放到不同的配置文件里,那时候需要频繁的在 ...

  6. Spring Boot搭建Web项目常用功能

    搭建WEB项目过程中,哪些点需要注意: 1.技术选型: 前端:freemarker.vue 后端:spring boot.spring mvc 2.如何包装返回统一结构结果数据? 首先要弄清楚为什么要 ...

  7. 如何基于Spring Boot搭建一个完整的项目

    前言 使用Spring Boot做后台项目开发也快半年了,由于之前有过基于Spring开发的项目经验,相比之下觉得Spring Boot就是天堂,开箱即用来形容是绝不为过的.在没有接触Spring B ...

  8. Spring Boot 搭建TCP Server

    本示例首选介绍Java原生API实现BIO通信,然后进阶实现NIO通信,最后利用Netty实现NIO通信及Netty主要模块组件介绍. Netty 是一个异步事件驱动的网络应用程序框架,用于快速开发可 ...

  9. (子文章)Spring Boot搭建两个微服务模块

    目录 1. 创建工程和user-service模块 1.1 创建空工程 1.2 在空工程里新建Module 2. 配置文件 2.1 pom.xml 2.2 application.yml 3. 代码 ...

随机推荐

  1. Csharp: FreeTextbox 编辑器控件运行时错误: 'FTB_ResizeGalleryArea' 未定义

    ftb.imagegallery.aspx 改一下代码: <form id="Form1" runat="server" enctype="mu ...

  2. 用C#实现工资计算公式动态编写

    1,工资计算公式 每一个企业都一定会用到工资计算,发工资是一件非常神圣的事情,而计算工资就是一项非常重要的工作.Excel有非常强大的公式功能,帮助了很多财务人员计算工资,但如果企业的人数比较多,而且 ...

  3. 学习JVM虚拟机原理总结

    0x00:JAVA虚拟机的前世今生 1991年,在Sun公司工作期间,詹姆斯·高斯林和一群技术人员创建了一个名为Oak的项目,旨在开发运行于虚拟机的编程语言,允许程序多平台上运行.后来,这项工作就演变 ...

  4. django-1-应用开发基本套路

    Django 开发基本流程 创建项目 创建应用 修改配置文件 设计数据模型 后台管理注册 编写业务视图 编写模板文件 设置URL 访问测试/调试 部署上线 创建项目 django-admin star ...

  5. 域名和DNS服务器

    概念性的东西: 域名:     ①.百度:域名(Domain Name),是由一串用点分隔的名字组成的Internet上某一台计算机或计算机组的名称,用于在数据传输时标识计算机的电子方位(有时也指地理 ...

  6. Informatica 9.1.0 Domain地址变化修改

    由于公司机房的变动,infa所连数据库的IP地址变化,致使INFA不能启动.经过查找资料终于解决,现分享给大家,解决方法如下: 1.查看日志路径: Informatica/9.1.0/tomcat/l ...

  7. solidity语言10

    pragma solidity ^0.4.16; contract OwnedToken { // TokenCreator是个合约类型,由后面部分定义.只要不用于创建新合约,引用它就好 TokenC ...

  8. Web系统常见安全漏洞及解决方案-SQL盲注

    关于web安全测试,目前主要有以下几种攻击方法: 1.XSS 2.SQL注入 3.跨目录访问 4.缓冲区溢出 5.cookies修改 6.Htth方法篡改(包括隐藏字段修改和参数修改) 7.CSRF ...

  9. 【Leetcode】【Medium】Single Number II

    Given an array of integers, every element appears three times except for one. Find that single one. ...

  10. 深入理解linux源码安装三板斧

    概述: 根据源码包中 Makefile.in 文件的指示,configure 脚本检查当前的系统环境和配置选项,在当前目录中生成 Makefile 文件(还有其它本文无需关心的文件),然后 make ...