综合案例

综合案例

# 修改web综合案例
要求如下:
1. 后端项目要求
	1). 基于springboot框架
	2). Restful风格
	3). 对异常进行统一的处理
	4). 使用AOP统计查询功能的执行时长
	5). 对增删改方法进行事务管理
2. 前端项目要求
	1). Restful风格

之前完成的web综合案例功能: 【前后端分离】

  • 用户

    • 添加用户

      • 前端:

        • POST请求方式
        • 请求参数:json
      • 后端:

        • 允许跨域
        • @RequestBody 接收前端发送的json数据
      • 解决的问题:

        1、需要获取所有的角色 (查询功能)
        
        
    • 修改用户

      • 前端

        • 请求方式:PUT

        • 请求参数:要修改用户数据(json)

          axios.put("http://localhost:8080/user", 请求参数)
          修改成功: 重新获取用户列表数据、 隐藏修改用户的窗口
          
      • 后端

        • RESTful风格

        • 修改用户: 用户的基本数据、用户的角色数据
          第1步:修改用户的基本数据(用户表)
          第2步:删除用户的所有角色数据, 添加用户的角色数据 (用户角色表)    
          
    • 删除用户

      • 前端:

        • 请求方式:DELETE

          axios.delete("http://localhost:8080/user/用户id")
          删除成功: 重新获取用户列表数据
          
      • 后端:

        • RESTful风格

        • 删除用户时: (用户表和用户角色表有主外键关系,不能直接删除主键表中的用户数据)
          第1步:删除用户角色表中的数据 (外键表)
          第2步:删除用户表中的数据(主键表)
          
    • 查询用户

      • 分页查询
      • 搜索查询(模糊查询)
  • 角色

  • 权限

# 思路 : 需求分析 -> 业务逻辑 -> 实现阶段(技术选型,搭建架构,具体代码) -> 测试 
0. 技术选型 (基于springboot框架)
	1). web场景
	2). mybatis场景 ,druid场景
	3). test场景
	
1. 入手点的逻辑链: 数据库 -> dao -> service -> controller
	1). 先修改数据库的参数(application.yml)
		I. url : 修改仓库名
			webdemo
		II. type
			需要导入druid场景
		III. pojo  (直接复制)
			a. po(persistence object) : 持久化对象(数据库映射pojo)
			b. vo(values object) : 值对象(前端映射pojo)	
            注意要修改type-aliases-package(pojo包扫描)
	2). dao层
		I. dao包下的接口直接复制
			注意在启动类中加上@MapperScan
		II. resources中的映射文件
			需要要修改application.yml中的mapper-locations位置
    3). service层
    	I. 接口
    	II. 实现类 
    		由于spring的IOC思想,使用dao层无需再用工具类创建,只要从ioc容器中获取即可
    		然后实现类对象也注意放到IOC容器中
	4). controller层	
		I. restful风格
		II. 查询传递参数不要用json格式(有无搜索条件,注意重载!!!)
3. 对异常进行统一的处理
	1). 异常统一处理器
		1). 作用: 整个工程中出现的异常无需catch,在异常处理器可以进行统一的处理
		2). 思想: AOP[切面 = 切入点(controlle层方法) + 通知(手动编写)]
	2). 实现方案:
		I. ProjectExceptionAdvice (注解配置)
		II. 此bean需要被扫描到,不然不会生效 (在springboot中只需要启动类所在包之下)
 
4.  使用AOP统计查询功能的执行时长
	1). 实现思路: 切面=切入点+通知
		I. 切入点 : find开头方法(查询方法)
		II. 通知 : 环绕通知,切入点执行之前记录时间,之后也记录时间,然后计算得到执行时间
	2). 实现方案:
		I. TimeAdvice (切面类)
			1). 注意通知方法异常需要抛出, 给异常统一处理器处理
			2). 要导入aop场景启动器
				<dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-aop</artifactId>
                </dependency>
			3). 此bean需要被扫描到            
5. 对增删改方法进行事务管理(声明式事务)
	1). @EnableTransactionManagement // 开启事务支持
		加在启动类上
	2).@Transactional (接口方法上添加)
		
# 单元测试
0. dao层findUserByPage方法为例 (查询: 分页,动态搜索)
1. 上策 : 搞清楚是什么东西
	1). 查询: 分页,动态搜索
	2). 动态搜索的sql: 
		I. 没有搜索
			 SELECT * FROM
                      (SELECT * FROM t_user
                            LIMIT #{offset},#{pageSize}) tu,
                       t_user_role tur,t_role tr
                WHERE tu.id=tur.user_id AND tr.id = tur.role_id;
        II. 有搜索
        	 SELECT * FROM
                      (SELECT * FROM t_user
             where username like concat('%',#{queryParams.username},'%')
                            LIMIT #{offset},#{pageSize}) tu,
                       t_user_role tur,t_role tr
                WHERE tu.id=tur.user_id AND tr.id = tur.role_id;
    3). 判定条件
    	QueryPageBean.queryParams里的key(username)是否有对应的value值
    	    // queryParams.put("username","h") // 有搜索条件
    		// queryParams.put("username","") // 没有搜索条件
2. 中策: 看不懂的删掉    	

扩展知识:SpringBoot解决跨域请求问题

  • 前端和后端一旦分离开发,就存在:ajax跨域

  • 解决跨问题的方案:

    1. 前端解决

      在vue脚手架工程: config/index.jsp , 配置请求代理:
      
      //配置代理(解决前端ajax跨域)
      proxyTable: {
         "/": {
              target: "http://localhost:8080",
              changeOrigin: true
          }, 
      //当浏览器发起的请求是:"/user"时,就会由vue代理转换为:"http://localhost:8080/user"
         "/user": {    
              target: "http://localhost:8080/user",
              changeOrigin: true //允许跨域
          }
      }
      
    2. 后端解决

      //在springboot中,存在一个注解: @CrossOrigin
      
      
      @RestController
      @RequestMapping("/user")
      @CrossOrigin  //该Controller中的所有方法,都允许跨域
      public class UserController{
          
      }
      
      
      
      @RestController
      @RequestMapping("/user")
      public class UserController{
          
          @GetMapping
          @CrossOrigin  //允许当前方法跨域
          public List<User> findUser(){
              .../
          }
      }
      

扩展知识:PageHelper的短板

PageHelper:mybatis的分页助手

  • 可以实现mybatis的分页查询功能

PageHelper底层机制:

  • 利用AOP思想来完成分页操作

    //PageHelper不会破坏原有方法的执行
    
    在查询方法执行之前,设置分页:
    PageHelper.startPage( 页码 , 每页条数);
    执行dao层的查询功能
    把查询的结果,封装到PageInfo对象中
    
    • 在执行dao层的查询之前,进行设置:分页

    • 在执行dao层的查询时,会对原有的sql查询语句,进行修改:

      • 在原sql语句后面,追加:LIMIT 起始位置,每页条数

示例:

原sql语句:
     select * from t_book 
设置PageHelper分页后,会对执行的sql语句进行修改(在sql语句的末尾,追加limit):
     select * from t_book limit 起始位置,每页条数
  • 结论:PageHelper通常是在SQL语句的末尾追加LIMIT

PageHelper短板:

  • 如果不是在原SQL的末尾添加LIMIT(例:在sql语句的中间位置要添加limit,PageHelper就变得不好用了)

  •  select u.id as userid,
                   u.username,
                   u.password,
                   u.email,
                   u.remark,
                   u.createTime,
                   u.updateTime,
    
                   r.id as roleid,
                   r.name,
                   r.description,
                   r.keyword
    
     from (select * from t_user LIMIT 起始位置,每页条数) AS u,
                 t_role AS r,
                 t_user_role AS ur
     where u.id = ur.user_id
           and r.id = ur.role_id
    
posted @ 2023-03-11 17:15  忘了鱼尾纱的猫  阅读(98)  评论(0)    收藏  举报