ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

用户&角色&权限demo_case 梳理总结

2022-05-09 00:00:41  阅读:141  来源: 互联网

标签:case 实体类 demo request response session static 权限 public


用户&角色&权限demo_case小结

实现过程问题记录

Q1:
	1- UserMapper中sql语句查询结果和实体类不一致
	TODO:目前查询筛选数据和实体类不一致??? 
	2- 多表查询配置Role中的column无查询的id
		
	验证结果,查询效果一致,分析:对于sql语句未查询到的字段,实体类中未默认值

Q2:
	角色前端界面不显示数据,后端能反馈数据
	前端界面显示问题,已修改
		
		
Q3:  数据查询存在问题???    页面显示数据为t_user和t_role的交集
	页面显示的用户信息和后台数据信息不一致;如admin1不显示在界面上
	有设置角色的用户信息不显示
		
		
Q4:delete
	删除表的信息时需要先删除表的关联外键,再删除
		

前端总结梳理

前端
	1-先加载App.vue点击userList跳转到(router)跳转到
		userList.vue界面
	2-Template书写基本页面布局样式,按钮绑定等
	3-script data() 中书写过程页面及交互所需要的数据和后端实体类有一定关联,一些state属性内容、数据校验规则
	4-created()页面加载时运行 
	5-mthods增删查改方法
		查询:
            获取url:发送给后端的地址 config中配置三要素
            param:发送给后端的数据参数,后端的数据输入
            axios.post(url,param)
            .then(response.data)对于后端反馈的数据进行处理
            进行一些逻辑判断等
            .catch()
            .finally() 关闭窗口、更新数据等
	
技术点:AJAX,element-ui,Vue  

后端梳理

后端
	1-文件目录结构:三层架构:web层 service层 dao层
		web层:
			接受前端的数据并将其封装为实体类
			创建业务层对象,调用业务层方法
			将业务层返回对象转换为JSON返回给前端
		service层(可使用接口配合BeanFactory使用)
			实现业务层的CRUD方法,接受web层传递的数据
			获取工厂类会话,运用动态代理实现接口方法
			将数据库查询结果(实体类)返回给Web层
		dao层
			定义接口方法
				单表CRUD使用注解开发
				多表CRUD使用xml进行开发
		pojo:
			数据封装的实体类和数据库表、前端JSOPN强相关
			po:存放数据库对应的实体类
			vo:对应前后端交互Result、CRUD设计的实体类,方便数据流动
		utils:
			工具类:
				BaseController:
					接受前端的JSOPN数据并并解析为实体类
					将Service层传递的实体类转换为前端可识别的JSON
				EncodingFilter:解决前后端交互的request和response乱码问题
				BeanFactory:获取业务层对象的工厂类(反射+读取配置文件+单例设计模式)
				SqlSessionUtil:获取工厂会话类
		XML开发:xml文件名需要和接口文件名一致+在统一文件路径下
		配置文件类型:
			beans.properties: BeanFactory实现对应的key和value(Service实现类的地址)
			jdbc.properties:数据库参数的配置
			mybatisConfig.xml:mybatis环境配置、相关的依赖包、Mapper映射
			logback.xml:日志配置
	2-针对不同角色进行CRUD开发
		web层BaseServlet:使用反射进行所有CRUD方法的调用
		集合pojo实体类搞清接受的类型和传入的参数
	3-关于pojo中vo类的设计思路需要锻炼,一个好的设计,开发会非常顺畅
		AddUser:数据库字段+角色List(一个用户对应多个角色)——根据数据库表之间的对应关系来实现
		PageResult:作为返回给前端的数据 总记录数+List
		QueryPageBean:前端查询数据封装的实体类
		Result:返回给前端的实体类,所有类都可封装进该类进行数据传递
		UpdateUser:前端需求字段(表字段)+List(一个User对应多个Role)
		数据库表的实体类:表对应的字段+表之间的关系,如Role实体类中包含了
							Set<User>和Set<Permission>两个集合
	4-sql的CRUD实现 —— 单一表功能的CRUD需要考虑到对其他表的影响(外键约束)
		单表的CRUD实现使用注解开发
		多表CRUD中涉及中间表的修改,需要先将中间表进行修改(考虑外键约束)
			如update User表时需修改User和Role表的中间表(先删除中间表信息再添加)
		多表查询: 
			ResltMap	
				Type(接口方法的返回值类型) 
				配置user表和User实体类的主键映射关系
				一个用户对应多个角色,使用标签collection  
				OfType为集合中保存的实体类型
				propert表示User实体类集合中期对象名是roles					

技术点:mybatis、mysql、反射、动态代理

部分Code

多表查询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.case2.dao.UserMapper">

    <!--
      主键字段映射不可省略,原因在于mybatis是根据主键映射知道哪个字段是主键的.
          这样的话, 多条主键值相同的记录被合并成一个JavaBean
    -->
    <!--
       1.id="findAllUsersByPageMap" : 表示唯一标识,通过属性值关联下面的select标签
       2.type="user":接口中关联方法的返回值类型,是容器中的泛型类型
       3.autoMapping="true":如果实体类和数据表的字段名一致那么会自动映射
   -->
    <resultMap id="findAllUsersByPageMap" type="user" autoMapping="true">
        <!--配置t_user表和User实体类中的主键映射关系、
            4.<id column="id" property="id"/> :column表示数据表的字段名 property 表示实体类中的成员变量名
        -->
        <id column="id" property="id"/>
        <!--
            在mybatis中没有多对多,配置一对多,一个用户对应多个角色,使用的标签是collection
                5.ofType="role"表示List集合中保存的实体类类型
                6.autoMapping="true":如果实体类和数据表的字段名一致那么会自动映射
                7.property="roles":表示在User实体类集合容器对象名是roles
        -->
        <collection property="roles" autoMapping="true" ofType="role">
            <!--
                9.配置t_role表和实体类Role之间主键的映射关系:
                    1)column="rid" 表示数据表的字段名
                    2)property="id" 表示Role实体类的成员变量名
            -->
            <id column="rid" property="id"/>
        </collection>
    </resultMap>
    <!--
        1. 分页查询用户和角色
            List<User> findUserByPage(QueryPageBean bean);
        2.#{offset} 底层调用QueryPageBean的getOffset方法:
    -->
    <select id="findUserByPage" resultMap="findAllUsersByPageMap">
        select u.*,r.id rid,r.name from
                (select * from t_user limit #{offset},#{pageSize}) u
                    inner join t_user_role ur
                    inner join t_role r
                               on u.id = ur.user_id and
                                  ur.role_id = r.id
    </select>


    <!--
         insert into t_user_role values(5,1),(5,2),(5,3)
    -->
    <insert id="addRoleByUid" >
        insert into t_user_role values
                <foreach collection="ids" item="rid" separator=",">
                   (#{uid},#{rid})
                </foreach>
    </insert>

</mapper>

updateUser表中的多表实现

 public void updateUser(UpdateUser uu) {

        SqlSession session = SqlSessionUtil.getSession();
        UserMapper mapper = session.getMapper(UserMapper.class);

        //1). 修改t_user表
        mapper.updateUser(uu);
        //2). 修改t_user_role表 : 先删除再添加
        mapper.deleteRoleByUid(uu.getId());

        //3). 向t_user_role表中添加用户和新角色的id

        mapper.addRoleByUid(uu.getId(), uu.getRoleIds());

        session.close();
   }

工具类

会话工厂SqlSessionUtil

public class SqlSessionUtil {

    private static SqlSessionFactory factory;
    static {
        //实例化工厂建造类
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        //读取核心配置文件
        try (InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml")) {
            //创建工厂对象
            factory = builder.build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     得到会话对象
     @return 会话对象 : 自动提交事务
     */
    public static SqlSession getSession() {
        return factory.openSession(true);
    }

    /**
     得到会话对象
     @param isAutoCommit 是否自动提交事务
     */
    public static SqlSession getSession(boolean isAutoCommit) {
        return factory.openSession(isAutoCommit);
    }

    /*
    *   提交事务并关闭session
    * */
    public static void commitAndClose(SqlSession session) {
        if(session != null){
            session.commit();
            session.close();
        }
    }

    /*
     *   回滚事务并关闭session
     * */
    public static void rollbackAndClose(SqlSession session) {
        if(session != null){
            session.rollback();
            session.close();
        }
    }

}


前后端数据交互请求响应

public class BaseController {

    public static void printResult(HttpServletResponse response, Object obj) throws IOException {
        response.setContentType("application/json;charset=utf8");// 设置返回类型
        JSON.writeJSONString(response.getWriter(),obj);
    }

    public static  <T> T parseJSON2Object(HttpServletRequest request, Class<T> tClass) throws IOException{
        // 把json格式的表单数据直接转成T类型的对象
        return JSON.parseObject(request.getInputStream(),tClass);
    }
}


反射动态代理实现方法

public class BaseServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取url路径携带的方法
        String url = request.getRequestURI();
        int index = url.lastIndexOf('/');
        String methodName = url.substring(index+1);
        //使用反射执行方法
        //获取要执行的类的对象
        Class<?> aClass = this.getClass();
        try {
            //使用class类调用要执行的方法
            Method method = aClass.getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
            //执行方法
            method.invoke(this,request,response);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);

    }
}



处理请求响应乱码问题

@WebFilter("/*")
public class EncodingFilter implements Filter {
    public void init(FilterConfig config) throws ServletException {
    }

    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        //解决请求乱码问题
        request.setCharacterEncoding("utf-8");
        //解决响应乱码问题
        response.setContentType("text/html;charset=utf-8");
        chain.doFilter(request, response);
    }
}


生成业务层单例对象

public class BeansFactory {
    //定义静态方法生成单例对象
    private static HashMap<String,Object> map = new HashMap<String,Object>();
    //创建静态方法生成单例对象
    public  static synchronized Object getSingleInstance(String beanName) throws Exception{
        Object obj = map.get(beanName);
        if(obj == null){
            //读取保存实现类的配置文件
            ResourceBundle bundle = ResourceBundle.getBundle("beans");
            String userServiceStr = bundle.getString(beanName);
            //使用反射根据上述读取的实现类全路径创建对象
            Class clazz = Class.forName(userServiceStr);
            //使用clazz实现UserServiceImp的无参构造
            obj=clazz.newInstance();
            //将创建的对象和key存储到map集合中
            map.put(beanName,obj);
        }
        return obj;
    }
}

小结

    设计好代码的实现逻辑(UML)非常重要,想好再动手
    出现bug时debug调试很关键、结合控制台输出信息+日志信息+google大法(stackoverflow)
    学会查官方文档(element-ui)
    学会使用浏览器抓包查看数据
    浏览器查看源码及调试
    从数据库表之间的关系入手,理清项目时自上而下,最后到具体业务
    项目的文件结构很重要,清晰的结构可以使代码实现思路简单,且高内聚低耦合
    数据表之间的多表查询需要考虑外键约束
    完成一个功能就进行测试,避免后期代码bug过多
    
人生是不断遇到问题并解决问题的过程,程序工作中遇到的问题可能会更明显一点,你遇到的所有问题都有解决方案,不要急躁,一个个解决即可    

标签:case,实体类,demo,request,response,session,static,权限,public
来源: https://www.cnblogs.com/albert-liu/p/16247611.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有