考试管理系统-刷题系统登录注册权限校验

1. 用户与角色

在这里插入图片描述

思路:
根据用户去找角色的信息,然后需要用到两个表的查询,在前端页面显示信息的时候用for:each通过遍历去动态生成,而不是静态的生成
需要进行更新用户与角色关系时,先从前端拿到数据,后端调用删除和添加方法来进行更新,这样运行的时候相对比较容易些,不需要分三种情况(没动,有删除,有添加)来操作

1.1 绑定用户与角色关系数据准备

在这里插入图片描述

(1)在用户模块下的\WEB-INF\pages\system\user\list.jsp页面中找到角色按钮,对应的点击事件和函数的绑定都已完成,roleList方法中向后台UserServelt发送请求,执行userRoleList方法,传递参数用户id

(2)找到UserServlet,添加方法

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String operation = request.getParameter("operation");
    if("list".equals(operation)){
        this.list(request,response);
    }
    //中间的省略
    else if("userRoleList".equals(operation)){
        this.userRoleList(request,response);
    }
}
private void userRoleList(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String userId = request.getParameter("id");
    User user = userService.findById(userId);
    //将数据加载到指定区域,供页面获取
    request.setAttribute("user,user);
    //获取所有的角色列表
    List<Role> all = roleService.findAllRoleByUserId(userId);
    request.setAttribute("roleList",all);
    //跳转页面
    request.getRequestDispatcher("/WEB-INF/pages/system/user/role.jsp").forward(request,response);
}

同时从day03的课程资料中找到:模块页面\user\role.jsp,拷贝到工程/WEB-INF/pages/system/user/目录下

(3)在RoleService接口中添加查询方法,根据用户id查询角色列表

List<Role> findAllRoleByUserId(String userId);
1

(4)在对应的实现类中去实现该方法

@Override
public List<Role> findAllRoleByUserId(String userId) {
    SqlSession sqlSession = null;
    try{
        //1.获取SqlSession
        sqlSession = MapperFactory.getSqlSession();
        //2.获取Dao
        RoleDao roleDao = MapperFactory.getMapper(sqlSession,RoleDao.class);
        //3.调用Dao层操作
        return roleDao.findAllRoleByUserId(userId);
    }catch (Exception e){
        throw new RuntimeException(e);
        //记录日志
    }finally {
        try {
            TransactionUtil.close(sqlSession);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

(5)在dao接口RoleDao中添加查询方法findAllRoleByUserId

List<Role> findAllRoleByUserId(String userId);
1

(6)在映射配置文件RoleDao.xml中添加对应的查询

    <!--配置根据ID查询-->
<select id="findAllRoleByUserId" parameterType="java.lang.String" resultMap="BaseResultMap">
	SELECT
		role_id,
		NAME,
		CASE
			WHEN role_id IN (SELECT role_id FROM ss_role_user WHERE user_id = #{'userId'})
			THEN 'checked'
			ELSE ''
		END
		AS remark
	FROM
		ss_role
</select>

(7)修改页面/WEB-INF/pages/system/user/role.jsp,添加checked

<form id="urform" action="${ctx}/system/user?operation=updateRole" method="post">
    <input type="hidden" name="userId" value="${user.id}"/>
    <div class="textbox" id="centerTextbox">
        <div style="text-align:left">
            <c:forEach items="${roleList}" var="role" varStatus="vs">
                <span style="padding:3px;margin-right:30px;width: 160px;display: inline-block">
        <input type="checkbox" name="roleIds" value="${role.id}" ${role.remark}/>${role.name}
                </span>
            </c:forEach>
        </div>
    </div>
</form>

(8)启动项目测试!

1.2 绑定用户与角色关系

现在要真正去绑定用户与角色的关系,前台页面提交表单后会将用户的id和选择的角色的id传递到后台servlet

(1)在UserServlet中添加新的方法

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String operation = request.getParameter("operation");
    if("list".equals(operation)){
        this.list(request,response);
    }
    //中间的省略
    else if("userRoleList".equals(operation)){
        this.userRoleList(request,response);
    }else if("updateRole".equals(operation)){
        this.updateRole(request,response);
    }
}
private void updateRole(HttpServletRequest request, HttpServletResponse response) throws IOException {
    String userId = request.getParameter("userId");
    String[] roleIds = request.getParameterValues("roleIds");
    userService.updateRole(userId,roleIds);
    //跳转回到页面list
    response.sendRedirect(request.getContextPath()+"/system/user?operation=list");
}

(2)在UserService接口中添加一个新的方法updateRole

void updateRole(String userId, String[] roleIds);

(3)在对应的实现类中去实现

@Override
public void updateRole(String userId, String[] roleIds) {
    SqlSession sqlSession = null;
    try{
        //1.获取SqlSession
        sqlSession = MapperFactory.getSqlSession();
        //2.获取Dao
        UserDao userDao = MapperFactory.getMapper(sqlSession,UserDao.class);
        userDao.deleteRole(userId);
        for(String roleId : roleIds){
            userDao.updateRole(userId,roleId);
        }
        //4.提交事务
        TransactionUtil.commit(sqlSession);
    }catch (Exception e){
        TransactionUtil.rollback(sqlSession);
        throw new RuntimeException(e);
        //记录日志
    }finally {
        try {
            TransactionUtil.close(sqlSession);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

(4)在dao接口UserDao中添加两个方法

void deleteRole(String userId);

void updateRole(@Param("userId") String userId, @Param("roleId")String roleId);

(5)在该接口对应的映射配置文件中添加两个操作

<!--配置根据roleId删除关系表数据-->
<delete id="deleteRole" parameterType="java.lang.String">
    delete from ss_role_user
    where user_id = #{userId,jdbcType=VARCHAR}
</delete>

<!--配置全字段插入,当某个字段没有值时,插入null-->
<insert id="updateRole" parameterType="map">
    insert into ss_role_user (role_id, user_id)
    values (#{roleId,jdbcType=VARCHAR}, #{userId,jdbcType=VARCHAR})
</insert>

(6)启动项目进行测试!

2. 登陆

在这里插入图片描述

登录功能其实一样,前端传数据三层传递,去数据库找,返回一个user对象,判断user有没有,有就存会话域中,跳转到主页面,没有就弹回登录页面。
值得一提的是因为用户的密码是加密的,所以在去调用找方法之前,在service层需要对前端传入的密码也进行同一种加密方式,然后传到后端,来实现统一

2.1 登陆功能快速开发

(1)找到项目webapp/login.jsp登陆页面,修改form表单提交的action路径

<form action="${pageContext.request.contextPath}/system/user?operation=login" method="post">
</form>

(2)在后台UserServlet添加登陆的方法

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String operation = request.getParameter("operation");
    if("list".equals(operation)){
        this.list(request,response);
    }
    //中间省略
    else if("login".equals(operation)){
        this.login(request,response);
    }
}
private void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String email = request.getParameter("email");
    String pwd = request.getParameter("password");
    User user = userService.login(email,pwd);
    if(user != null) {
        request.getSession().setAttribute("loginUser", user);
        //跳转页面
        request.getRequestDispatcher("/WEB-INF/pages/home/main.jsp").forward(request, response);
    }else{
        response.sendRedirect(request.getContextPath()+"/login.jsp");
    }
}

(3)在因为层接口UserService中添加登陆的方法

/**
     * 根据邮箱和密码登录
     * @param email
     * @param pwd
     * @return
     */
    User login(String email, String pwd);

(4)在对应的实现类中去实现登陆方法

@Override
public User login(String email, String pwd) {
    SqlSession sqlSession = null;
    try{
        //1.获取SqlSession
        sqlSession = MapperFactory.getSqlSession();
        //2.获取Dao
        UserDao userDao = MapperFactory.getMapper(sqlSession,UserDao.class);
        //3.调用Dao层操作
        pwd = MD5Util.md5(pwd);
        return userDao.findByEmailAndPwd(email,pwd);
    }catch (Exception e){
        throw new RuntimeException(e);
        //记录日志
    }finally {
        try {
            TransactionUtil.close(sqlSession);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

(5)在UserDao接口中添加查询方法

User findByEmailAndPwd(@Param("email")String email, @Param("password")String pwd);

(6)在UserDao.xml中添加查询

<select id="findByEmailAndPwd" parameterType="map" resultMap="BaseResultMap">
    select
    <include refid="Base_Column_List"/>
    from ss_user
    where email = #{email,jdbcType=VARCHAR} and password = #{password,jdbcType=VARCHAR}
</select>


(7)将原本在webapp/pages/home下的所有页面统一挪到/WEB-INF/pages下,注意是连同home目录一起挪

(8)修改/WEB-INF/pages/home/main.jsp内容区的路径

<!-- 内容区域 -->
<div class="content-wrapper">
    <iframe id="iframe" name="iframe"
            style="overflow:visible;"
            scrolling="auto"
            frameborder="no" height="100%" width="100%"
            src="${ctx}/system/user?operation=home"></iframe>
</div>

(9)在后台UserServlet中添加方法

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String operation = request.getParameter("operation");
    if("list".equals(operation)){
        this.list(request,response);
    }
    //中间省略
    else if("home".equals(operation)){
        this.home(request,response);
    }
}
private void home(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    request.getRequestDispatcher("/WEB-INF/pages/home/home.jsp").forward(request, response);
}

(10)启动项目测试

2.2 用户菜单控制数据准备

用户菜单控制,需要用到3张表的连查,从用户的id查到中间表,再从中间表查到对应的module表,执行语句可以用子查询和内连接,一定要理清楚其中的关系,再去查询。
菜单控制需要用到循环语句,通过一个ctype来确定是1级菜单还是2级菜单,然后再判断2级菜单中是否包含在1级菜单中来实现对菜单展示的控制

我们先来完成登陆后的注销操作,这是一套的

(1)找到/WEB-INF/pages/home/header.jsp中找到注销,添加请求连接

<div class="pull-right">
    <a href="${ctx}/system/user?operation=logout" class="btn btn-default btn-flat">注销</a>
</div>

(2)在后台UserServlet中添加对应的方法logout

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String operation = request.getParameter("operation");
    if("list".equals(operation)){
        this.list(request,response);
    }
    //中间的省略
    else if("login".equals(operation)){
        this.login(request,response);
    }else if("logout".equals(operation)){
        this.logout(request,response);
    }else if("home".equals(operation)){
        this.home(request,response);
    }
}
private void logout(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    request.getSession().removeAttribute("loginUser");
    response.sendRedirect(request.getContextPath()+"/login.jsp");
}

(3)在用户登陆的时候需要去查询该用户对应的角色对应的所有模块,因此需要在后台的UserServlet中修改用户登陆的方法,添加数据的查询

private void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String email = request.getParameter("email");
    String pwd = request.getParameter("password");
    User user = userService.login(email,pwd);
    if(user != null) {
        request.getSession().setAttribute("loginUser", user);
        //如果登录成功,加载该用户对应的角色对应的所有模块
        List<Module> moduleList = userService.findModuleById(user.getId());
        request.setAttribute("moduleList",moduleList);
        //跳转页面
        request.getRequestDispatcher("/WEB-INF/pages/home/main.jsp").forward(request, response);
    }else{
        response.sendRedirect(request.getContextPath()+"/login.jsp");
    }
}

(4)在UserService接口中添加方法findModuleById

/**
     * 根据用户id查询所有可以操作的菜单对象
     * @param id 用户的id
     * @return
     */
    List<Module> findModuleById(String id);


(5)在实现类中去实现该方法

@Override
public List<Module> findModuleById(String id) {
    SqlSession sqlSession = null;
    try{
        //1.获取SqlSession
        sqlSession = MapperFactory.getSqlSession();
        //2.获取Dao
        ModuleDao moduleDao = MapperFactory.getMapper(sqlSession,ModuleDao.class);
        //3.调用Dao层操作
        return moduleDao.findModuleByUserId(id);
    }catch (Exception e){
        throw new RuntimeException(e);
        //记录日志
    }finally {
        try {
            TransactionUtil.close(sqlSession);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

(6)在ModuleDao接口中添加查询方法findModuleByUserId

List<Module> findModuleByUserId(String id);
1

(7)在ModuleDao.xml中添加对应的查询

<select id="findModuleByUserId" parameterType="java.lang.String" resultMap="BaseResultMap">
        /*userid->用户角色关系表->roleid->角色模块关系表->moduleid->module信息*/
        SELECT DISTINCT
          m.module_id, m.parent_id, m.name, m.ctype, m.state, m.curl, m.remark
        FROM
            ss_module AS m,
            ss_role_module AS rm,
            ss_role_user AS ru
        WHERE
            m.module_id = rm.module_id
        AND	rm.role_id = ru.role_id
        AND	ru.user_id = #{id,jdbcType=VARCHAR}
    </select>

至此:用户的角色对应的模块数据已查询出来了,后续就是要在页面进行控制展示

2.3 登陆用户菜单控制

(1)找到/WEB-INF/pages/home/aside.jsp页面,添加用户菜单的展示

<!-- sidebar menu: : style can be found in sidebar.less -->
<ul class="sidebar-menu">
    <li class="header">菜单</li>

    <c:forEach items="${moduleList}" var="item">
        <c:if test="${item.ctype==0}">
            <li class="treeview">
                <a href="#">
                    <i class="fa fa-cube"></i> <span>${item.name}</span>
                    <span class="pull-right-container"><i class="fa fa-angle-left pull-right"></i></span>
                </a>
                <ul class="treeview-menu">
                    <c:forEach items="${moduleList}" var="item2">
                        <c:if test="${item2.ctype==1 && item2.parentId == item.id}">
                            <li id="${item2.id}">
                                <a οnclick="setSidebarActive(this)" href="${ctx}/${item2.curl}" target="iframe">
                                    <i class="fa fa-circle-o"></i>${item2.name}
                                </a>
                            </li>
                        </c:if>
                    </c:forEach>
                </ul>
            </li>
        </c:if>
    </c:forEach>

启动项目进行测试

3.权限校验

在这里插入图片描述

  1. 主要是用到过滤器,通过拿到url和执行的方法,然后进行拼接,判断和传过来的路径方法是否一致来进行过滤,记得要判断空指针异常,因为很容易对象为空。
  2. 过滤器来回都可以实现,Filter绑定的过滤路径最好为/*,然后把一些css,js,png之类的创建一个static包,放进去,在遇到这堆静态路径的时候直接放行
  3. 很重要的一点是,开始界面和登陆界面操作的时候也要过滤掉,不然会出现一直进不去,死循环的情况。
  4. 同样一些添加,删除等一些按钮,也需要通过后端判断此用户有没有权限来动态生成

3.1 获取请求url

(1)创建过滤器:com.oldlu.web.filters.AuthorFilter

@WebFilter(value = "/*")
public class AuthorFilter implements Filter {

    private FilterConfig filterConfig;

    /**
     * 初始化方法,获取过滤器的配置对象
     * @param filterConfig
     * @throws ServletException
     */
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        this.filterConfig = filterConfig;
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
        //1.定义和协议相关的请求和响应对象
        HttpServletRequest request ;
        HttpServletResponse response;
        try{
            //2.把参数转换成协议相关的对象
            request = (HttpServletRequest)req;
            response = (HttpServletResponse)resp;

            //1.获取本次操作
            String url = request.getRequestURI();
            String queryString = request.getQueryString();

            //1.当前获取到的url:   /system/dept
            url = url.substring(1);
            //2.当前获取到的查询参数:operation=list       operation=toEdit&id=100
            int index = queryString.indexOf('&');
            if(index != -1){
                queryString = queryString.substring(0,index);
            }
            url = url + "?" + queryString;

            //2.获取到当前登录人允许的操作

            //3.比对本次操作是否在当前登录人允许的操作范围内
            //3.1如果允许,放行
            //3.2不允许跳转到非法访问页

            //6.放行
            chain.doFilter(request,response);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public void destroy() {
        //可以做一些清理操作
    }
}

3.2 获取登陆用户可执行操作

(1)登陆成功后需要将用户的觉得对应的模块信息存放到session,找到UserServlet中的登陆方法login

private void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String email = request.getParameter("email");
    String pwd = request.getParameter("password");
    User user = userService.login(email,pwd);
    if(user != null) {
        request.getSession().setAttribute("loginUser", user);
        //如果登录成功,加载该用户对应的角色对应的所有模块
        List<Module> moduleList = userService.findModuleById(user.getId());
        request.setAttribute("moduleList",moduleList);

        //当前登录用户对应的可操作模块的所有url拼接成一个大的字符串
        StringBuffer sbf = new StringBuffer();
        for(Module m: moduleList){
            sbf.append(m.getCurl());
            sbf.append(',');
        }
        request.getSession().setAttribute("authorStr",sbf.toString());

        //跳转页面
        request.getRequestDispatcher("/WEB-INF/pages/home/main.jsp").forward(request, response);
    }else{
        response.sendRedirect(request.getContextPath()+"/login.jsp");
    }
}

(2)修改AuthorFilter

@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
    //1.定义和协议相关的请求和响应对象
    HttpServletRequest request ;
    HttpServletResponse response;
    HttpSession session;
    try{
        //2.把参数转换成协议相关的对象
        request = (HttpServletRequest)req;
        response = (HttpServletResponse)resp;
        session = request.getSession();
        //1.获取本次操作
        String url = request.getRequestURI();
        //.css   .js    .png   .jpg   .index
        if(url.endsWith(".css")
           || url.endsWith(".js")
           || url.endsWith(".png")
           || url.endsWith(".jpg")
           || url.endsWith("index.jsp")
           || url.endsWith("login.jsp")){
            chain.doFilter(request,response);
            return;
        }
        String queryString = request.getQueryString();
        if(queryString.endsWith("operation=login")){
            chain.doFilter(request,response);
            return;
        }


        //1.当前获取到的url:   /system/dept
        url = url.substring(1);
        //2.当前获取到的查询参数:operation=list       operation=toEdit&id=100
        int index = queryString.indexOf('&');
        if(index != -1){
            queryString = queryString.substring(0,index);
        }
        url = url + "?" + queryString;

        //2.获取到当前登录人允许的操作
        String authorStr = session.getAttribute("authorStr").toString();
        //3.比对本次操作是否在当前登录人允许的操作范围内
        //3.1如果允许,放行
        //3.2不允许跳转到非法访问页

        //6.放行
        chain.doFilter(request,response);
    }catch (Exception e){
        e.printStackTrace();
    }
}

(3)启动项目在模块管理功能中去添加一些数据,如下所示

在这里插入图片描述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nWcfoxuz-1596376711087)(./img/5.png)]

然后需要在角色管理中为对应的角色进行授权

3.3 权限校验

开始授权

(1)从day03的课程资料中找到模块页面/unauthorized.jsp,拷贝到项目的webapp下即可

(2)更改AuthorFilter

@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
    HttpServletRequest request ;
    HttpServletResponse response;
    HttpSession session;
    try{
        request = (HttpServletRequest)req;
        response = (HttpServletResponse)resp;
        session = request.getSession();

        //1.获取本次操作
        String url = request.getRequestURI();
        //.css   .js    .png   .jpg   .index
        if(url.endsWith(".css")
           || url.endsWith(".js")
           || url.endsWith(".png")
           || url.endsWith(".jpg")
           || url.endsWith("index.jsp")
           || url.endsWith("unauthorized.jsp")
           || url.endsWith("login.jsp")){
            chain.doFilter(request,response);
            return;
        }
        String queryString = request.getQueryString();
        if(queryString.endsWith("operation=login")
           ||queryString.endsWith("operation=home")
           ||queryString.endsWith("operation=logout")){
            chain.doFilter(request,response);
            return;
        }
        //1.当前获取到的url:   /system/dept
        url = url.substring(1);
        //2.当前获取到的查询参数:operation=list       operation=toEdit&id=100
        int index = queryString.indexOf('&');
        if(index != -1){
            queryString = queryString.substring(0,index);
        }
        url = url + "?" + queryString;

        //2.获取到当前登录人允许的操作
        String authorStr = session.getAttribute("authorStr").toString();

        //3.比对本次操作是否在当前登录人允许的操作范围内
        if(authorStr.contains(url)){
            //3.1如果允许,放行
            chain.doFilter(request,response);
            return;
        }else{
            //3.2不允许跳转到非法访问页
            response.sendRedirect(request.getContextPath()+"/unauthorized.jsp");
        }
    }catch (Exception e){
        e.printStackTrace();
    }
}

(3)对于页面上的元素,如果没有操作权限,我们直接让用户看不到即可,怎么操作呢?在页面上做一个判断,我们举一个例子,其他操作都是一样的

找到/WEB-INF/pages/system/user/list.jsp

<div class="btn-group">
    <c:if test="${sessionScope.authorStr.contains('system/user?operation=toAdd')}">
        <button type="button" class="btn btn-default" title="新建" οnclick='location.href="${ctx}/system/user?operation=toAdd"'><i class="fa fa-file-o"></i> 新建</button>
    </c:if>
    <button type="button" class="btn btn-default" title="删除" οnclick='deleteById()'><i class="fa fa-trash-o"></i> 删除</button>
    <button type="button" class="btn btn-default" title="刷新" οnclick="window.location.reload();"><i class="fa fa-refresh"></i> 刷新</button>
    <c:if test="${sessionScope.authorStr.contains('system/user?operation=userRoleList')}">
        <button type="button" class="btn btn-default" title="角色" οnclick="roleList()"><i class="fa fa-user-circle-o"></i> 角色</button>
    </c:if>
</div>

(4)启动项目,测试

4.注册

在这里插入图片描述

4.1 前台系统搭建与注册功能分析

(1)创建新的web项目,使用骨架模板,

groupId: com.oldlu

artifactId: mm_exam

补全项目结构,创建对应的包结构,删除自动创建的web.xml,

(2)修改pom.xml,找到今日课程资料工程资源文件\pom.xml,拷贝里面的内容覆盖项目下的pom

(3)拷贝静态页面,找到今日课程资料前台系统页面下的所有页面倒霉项目webapp

(4)分析注册页面-基于VUE+ElementUI

4.2 注册功能json数据解析

(1)创建BaseServlet:com.oldlu.web.controller.BaseServlet

public class BaseServlet extends HttpServlet {
}

(2)创建MemberServlet:com.oldlu.web.controller.front.MemberServlet

@WebServlet("/member/register")
public class MemberServlet extends BaseServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.收集数据(request数据)
        Object json = JSON.parseObject(request.getInputStream(), String.class);
        System.out.println(json);
        //2.组织成一个实体类(Member)
        //3.调用逻辑层API
        //4.返回结果(json数据解析)
        response.setContentType("application/json;charset=utf-8");
        JSON.writeJSONString(response.getOutputStream(),"{data:'abc',aa:'aa,bb:1}");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req, resp);
    }
}

(3)可以在前台页面regiester.html中接收数据

submitForm(formName) {
    this.$refs[formName].validate((valid) => {
        if (valid) {
            // alert('submit!');
            axios.post('/member/register', this.ruleForm).then(function (response) {
                alert(response.data);
            }).catch(function (err) {
                console.log(err)
            });
        } else {
            console.log('error submit!!');
            return false;
        }
    });
},

启动项目,测试

4.3 注册功能业务实现

(1)创建实体类:com.oldlu.domain.front

public class Member {

    private String id;
    private String nickName;
    private String password;
    private Date birthday;
    private String gender;
    private String email;
    private String telephone;
    private String address;
    private Date registerDate;
    private String state;
	// getter/setter略
}

(2)创建dao接口:com.oldlu.dao.front.MemberDao,并添加保存方法

public interface MemberDao {
    int save(Member member);
}

1234

(3)从今日课程资料中的工程资源文件中将除了pom.xml外的其他资源全部拷贝到项目的src/main/resources目录下,

(4)创建MemberDao的映射配置文件,首先在src/main/resources下创建目录:com/oldlu/dao/front,直接从今日课程资料中找到:dao层资源文件\MemberDao.xml,复制到该目录下

(5)创建业务层接口:com.oldlu.service.front.MemberService

public interface MemberService {
    /**
     * 注册新用户
     * @param member
     * @return
     */
    boolean register(Member member);
}

(6)创建其实现类:com.oldlu.service.front.impl.MemberServiceImpl

public class MemberServiceImpl implements MemberService {
    @Override
    public boolean register(Member member) {
        SqlSession sqlSession = null;
        try{
            //1.获取SqlSession
            sqlSession = MapperFactory.getSqlSession();
            //2.获取Dao
            MemberDao memberDao = MapperFactory.getMapper(sqlSession, MemberDao.class);
            //id使用UUID的生成策略来获取
            String id = UUID.randomUUID().toString();
            member.setId(id);
            member.setRegisterDate(new Date());
            member.setState("1");
            member.setPassword(MD5Util.md5(member.getPassword()));
            //3.调用Dao层操作
            int row = memberDao.save(member);
            //4.提交事务
            TransactionUtil.commit(sqlSession);
            return row > 0;
        }catch (Exception e){
            TransactionUtil.rollback(sqlSession);
            throw new RuntimeException(e);
            //记录日志
        }finally {
            try {
                TransactionUtil.close(sqlSession);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}

(7)从mm工程拷贝:factory/MapperFactory.java,utils/BeanUtil.java,utils/MD5Util.java,utils/TransactionUtil.java到本项目工程中,同时解决BeanUtil 中的错误

(8)修改:MemberServlet

@WebServlet("/member/register")
public class MemberServlet extends BaseServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.收集数据(request数据)
        String json = JSON.parseObject(request.getInputStream(), String.class);
        //2.组织成一个实体类(Member)
        Member member = JSON.parseObject(json, Member.class);
        //3.调用逻辑层API
        boolean flag = memberService.register(member);
        //4.返回结果(json数据解析)
        response.setContentType("application/json;charset=utf-8");
        JSON.writeJSONString(response.getOutputStream(),"{message:'注册成功'}");
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req, resp);
    }
}

需要在BaseServlet中添加MemberService

public class BaseServlet extends HttpServlet {
    protected MemberService memberService;

    @Override
    public void init() throws ServletException {
        memberService = new MemberServiceImpl();
    }
}

4.4 页面返回结果封装

(1)创建结果集的封装对象:com.oldlu.web.controller.Result

/**
 * 页面返回的结果数据封装对象
 */
public class Result implements Serializable {
    //对应操作的返回消息
    private String message;
    //对应操作的返回结果是否成功
    private Boolean flag;
    //对应操作返回的具体数据
    private Object data;
    //对应操作的返回状态码
    private Integer code;

    public Result(String message, Object data) {
        this.message = message;
        this.data = data;
        this.code = Code.SUCCESS;
        this.flag = true;
    }

    public Result(String message, Boolean flag, Object data, Integer code) {
        this.message = message;
        this.flag = flag;
        this.data = data;
        this.code = code;
    }

	// getter/setter略
}

(2)定义状态码常量类:com.oldlu.web.controller.Code

//状态码类
public class Code {
    public static final Integer SUCCESS = 20000;
    public static final Integer FAIL = 50000;
}

(3)修改对应的的servlet:MemberServlet

@WebServlet("/member/register")
public class MemberServlet extends BaseServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.收集数据(request数据)
        String json = JSON.parseObject(request.getInputStream(), String.class);
        //2.组织成一个实体类(Member)
        Member member = JSON.parseObject(json, Member.class);
        //3.调用逻辑层API
        boolean flag = memberService.register(member);
        //4.返回的数据封装成一个对象
        Result result = new Result("注册成功!", null);
        //5.返回结果(json数据解析)
        response.setContentType("application/json;charset=utf-8");

        JSON.writeJSONString(response.getOutputStream(),result);
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req, resp);
    }
}

(4)在页面上获取数据,找到regiester.html

submitForm(formName) {
    this.$refs[formName].validate((valid) => {
        if (valid) {
            // alert('submit!');
            axios.post('/member/register', this.ruleForm).then(function (response) {
                //得到响应数据
                var res = response.data;
                //判断成功与否
                if(res.flag){
                    window.open('/index.html','_self');
                }else{
                    alert("提示:"+res.message)
                }
            }).catch(function (err) {
                console.log(err)
            });
        } else {
            console.log('error submit!!');
            return false;
        }
    });
}

启动项目测试

5. Servlet重构

我们要将servlet中重复操作性的代码进行一个抽取

(1)在BaserServlet中封装方法

public class BaseServlet extends HttpServlet {
    protected MemberService memberService;

    @Override
    public void init() throws ServletException {
        memberService = new MemberServiceImpl();
    }

    protected <T> T getData(HttpServletRequest request, Class<T> clazz) throws IOException {
        //1.收集数据(request数据)
        String json = JSON.parseObject(request.getInputStream(), String.class);
        //2.组织成一个实体类(Member)
        return JSON.parseObject(json, clazz);
    }

    protected void returnData(HttpServletResponse response,Result result) throws IOException {
        //5.返回结果(json数据解析)
        response.setContentType("application/json;charset=utf-8");
        JSON.writeJSONString(response.getOutputStream(),result);

    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String url = request.getRequestURI();
        int lastIndex = url.lastIndexOf('/');
        String methodName = url.substring(lastIndex + 1,url.length());
        //获取到了方法名叫做url的方法,然后执行,传递参数即可
        Class clazz = this.getClass();
        try {
            Method method = clazz.getMethod(methodName,HttpServletRequest.class,HttpServletResponse.class);
            Result ret = (Result) method.invoke(this, request, response);
            returnData(response,ret);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req, resp);
    }

}

(2)重构完成后MemberServlet里面只剩如下代码

@WebServlet("/member/*")
public class MemberServlet extends BaseServlet {

    public Result register(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Member member = getData(request,Member.class);
        boolean flag = memberService.register(member);
        return new Result("注册成功!", null);
    }

}

启动项目测试看功能是否完整

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

赵广陆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值