使用IDEA基于Maven搭建SSM(Spring+SpringMVC+MyBatis)框架并完成登录注册案例(附源码)

一、环境准备

  1. 开发工具:IntelliJ IDEA 2017.3.1 x64
  2. 数据库:MySQL 5.5,其中MySQL的管理工具为Navicat
  3. JDK版本:JDK1.8
  4. Maven版本:apache-maven-3.2.2
  5. Tomcat版本:apache-tomcat-7.0.91
    当然了,以上只是我个人电脑上的开发环境,只要版本不过于老旧,应该是没有什么问题的。除此之外,有关于IDEA的基本操作以及JDK、Maven、Tomcat等的配置,这些也需要大家配置好(可以百度搜索一下)。本案例的完整代码会在文章末尾给出。

二、框架搭建

1.使用IDEA创建一个基本的Maven工程

(1)打开IDEA,点击Create New Project
使用IDEA基于Maven搭建SSM(Spring+SpringMVC+MyBatis)框架并完成登录注册案例(附源码)_第1张图片

(2)
使用IDEA基于Maven搭建SSM(Spring+SpringMVC+MyBatis)框架并完成登录注册案例(附源码)_第2张图片

(3)
使用IDEA基于Maven搭建SSM(Spring+SpringMVC+MyBatis)框架并完成登录注册案例(附源码)_第3张图片
(4)
使用IDEA基于Maven搭建SSM(Spring+SpringMVC+MyBatis)框架并完成登录注册案例(附源码)_第4张图片
(5)进去之后的界面如下
使用IDEA基于Maven搭建SSM(Spring+SpringMVC+MyBatis)框架并完成登录注册案例(附源码)_第5张图片
(6)由于IDEA创建maven的Java web项目时,main文件夹下没有java,resources目录等源文件夹,所以我们需要自己创建,具体过程可以查看这篇博客。这样一个基本的项目结构就创建好了。

2.在pom.xml中添加该项目所需要依赖jar包





  4.0.0
  war

  ssmtest
  com.test
  ssmtest
  1.0-SNAPSHOT

  
    
      
        org.mortbay.jetty
        maven-jetty-plugin
        6.1.7
        
          
            
              8888
              30000
            
          
          ${project.build.directory}/${pom.artifactId}-${pom.version}
          /
        
      
    
  

  
    

    
    

    
    
    
      org.springframework
      spring-webmvc
      4.3.7.RELEASE
    

    
    
    
      org.springframework
      spring-jdbc
      4.3.7.RELEASE
    

    
    
    
      org.springframework
      spring-aspects
      4.3.7.RELEASE
    

    
    
    
      org.mybatis
      mybatis
      3.4.2
    

    
    
    
      org.mybatis
      mybatis-spring
      1.3.1
    

    
    
    
      c3p0
      c3p0
      0.9.1
    

    
    
      mysql
      mysql-connector-java
      5.1.41
    

    
    
    
      jstl
      jstl
      1.2
    

    
    
      javax.servlet
      javax.servlet-api
      3.0.1
      
      provided
    

    
    
    
      junit
      junit
      4.12
    

    
    
      com.fasterxml.jackson.core
      jackson-core
      2.9.6
    
    
      com.fasterxml.jackson.core
      jackson-annotations
      2.9.6
    
    
      com.fasterxml.jackson.core
      jackson-databind
      2.9.6
    
    
  


添加完成之后,刷新该工程
使用IDEA基于Maven搭建SSM(Spring+SpringMVC+MyBatis)框架并完成登录注册案例(附源码)_第6张图片

这样便可以看见已经添加成功的jar包
使用IDEA基于Maven搭建SSM(Spring+SpringMVC+MyBatis)框架并完成登录注册案例(附源码)_第7张图片

3.配置web.xml文件





  
  
    contextConfigLocation
    classpath*:spring/spring-*.xml
  
  
    org.springframework.web.context.ContextLoaderListener
  


  
  
    springmvc
    org.springframework.web.servlet.DispatcherServlet
    
      contextConfigLocation
      classpath:spring/springmvc-context.xml
    
    1
  
  
    springmvc
    /   
  


  
  
    encoding
    org.springframework.web.filter.CharacterEncodingFilter
    
      encoding
      UTF-8
    
    
      forceEncoding
      true
    
  
  
    encoding
    springmvc
  


4.在resource目录下分别创建spring和mybatis目录,并且添加相应的配置文件
使用IDEA基于Maven搭建SSM(Spring+SpringMVC+MyBatis)框架并完成登录注册案例(附源码)_第8张图片
(1)spring-context.xml




    
    
        
    

    
    
        
        
        
        
    

    
    
        
        
        
            
                classpath*:mybatis/mapper-*.xml
            
        
    
    
    
        
    


    
    
        
        
    
    
        
            
            
        
    
    
        
    



(2)springmvc-context.xml




    
    
        
    

    
    
    
    

    
    
        
        
        
    

(3)config.xml




    

    

(4)mapper-user.xml






5.在java目录下创建一些基本的包
使用IDEA基于Maven搭建SSM(Spring+SpringMVC+MyBatis)框架并完成登录注册案例(附源码)_第9张图片

包名 作用
bean 存放一些实体类,有些一与数据库的表相对应,例如,用户类等等
controller 控制层
dao 数据传输层,与数据库进行交数据交互
service 编写 业务逻辑的接口
serviceImpl 实现业务逻辑

当然了,每个人给包的命名或者结构安排可能不一样,我所给出的只是一种参考。

三、分析需求创建表并连接数据库

1.由于本文的案例比较简单,只有用户的登录和注册功能,所以在名为ssmtest的数据库(自己在MySQL创建)中只建立了一张t_user表,如下图所示。
使用IDEA基于Maven搭建SSM(Spring+SpringMVC+MyBatis)框架并完成登录注册案例(附源码)_第10张图片
2.在IDEA中连接到该名为ssmtest的数据库
使用IDEA基于Maven搭建SSM(Spring+SpringMVC+MyBatis)框架并完成登录注册案例(附源码)_第11张图片使用IDEA基于Maven搭建SSM(Spring+SpringMVC+MyBatis)框架并完成登录注册案例(附源码)_第12张图片
这样便连接成功了!与此同时在User.java中添加相应的属性
User.java

package com.test.bean;

public class User {

    private String username;
    private String password;
    //用于判断是否记住用户名
    private String flag;

    public String getFlag() {
        return flag;
    }

    public void setFlag(String flag) {
        this.flag = flag;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

四、添加前端页面

具体目录结构如下图所示
使用IDEA基于Maven搭建SSM(Spring+SpringMVC+MyBatis)框架并完成登录注册案例(附源码)_第13张图片
1.login.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="com.test.utils.*" %>




    
    登录页面
    



<%
    //完成用户名的回显
    String username="";
    //获得从客户端携带过来的所有Cookie
    Cookie[] cookies=request.getCookies();
    //从Cookie的数组中查找指定名称的Cookie
    Cookie cookie = CookieUtils.findCookie(cookies, "username");
    if(cookie!=null)
    {
        username=cookie.getValue();
    }
%>



    

    
    


    




2.register.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8"%>




    
    用户注册
    



    
用户名
密码

五、完成前端与后台的交互

后台的目录结构如下所示

使用IDEA基于Maven搭建SSM(Spring+SpringMVC+MyBatis)框架并完成登录注册案例(附源码)_第14张图片
AjaxResult.java

package com.test.bean;

public class AjaxResult {

    //用于后台的逻辑判断
    private boolean success;
    //后台向前端返回的对象
    private Object data;

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public boolean isSuccess() {
        return success;
    }

    public void setSuccess(boolean success) {
        this.success = success;
    }

}

1.登录与注册功能
(1)控制器类 DispatcherController.java,用于转发各种请求

package com.test.controller;

import com.test.bean.AjaxResult;
import com.test.bean.User;
import com.test.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

@Controller
public class DispatcherController {

    @Autowired
    private UserService userService;

    //1.跳转到登录页面
    @RequestMapping("login")
    public String login(){
        return "login";
    }

    //2.跳转到注册页面
    @RequestMapping("register")
    public String register(){
        return "register";
    }

    //2.登录成功后跳转到index.jsp页面
    @RequestMapping("index")
    public String index(){
        return "index";
    }

    //3.用Ajax完成登录操作,但不跳转页面
    @ResponseBody
    @RequestMapping("doAjaxLogin")
    public Object doAjaxLogin(User user, HttpSession session, HttpServletResponse response){

        //创建一个AjaxResult对象,用于保存各种
        AjaxResult ajaxResult = new AjaxResult();

        User dbUser = userService.queryForLogin(user);

        //登录成功
        if(dbUser != null){
            //将用户放入session中
            session.setAttribute("loginUser",dbUser.getUsername());

            //获取是否记住用户名单选框的状态
            if("true".equals(user.getFlag())){
                // 完成记住用户名的功能:
                Cookie cookie = new Cookie("username",user.getUsername());
                //设置有效路径:
                cookie.setPath("/ssmtest");
                // 设置有效时间:
                cookie.setMaxAge(60*60*24);// 保存24小时
                // 将cookie回写到浏览器:
                response.addCookie(cookie);
            }

            ajaxResult.setSuccess(true);
        }else{
            ajaxResult.setSuccess(false);
        }

        return ajaxResult;
    }

    //3.用Ajax完成注册操作,但不跳转页面
    @ResponseBody
    @RequestMapping("doAjaxRegister")
    public Object doAjaxRegister(User user){

        //创建一个AjaxResult对象,用于保存各种
        AjaxResult ajaxResult = new AjaxResult();

        User dbUser = userService.queryForLogin(user);

        if(dbUser != null){
            //该用户已经被注册
            ajaxResult.setSuccess(false);
        }else{
            try {
                userService.insertUser(user);

                ajaxResult.setSuccess(true);
            }catch (Exception e){
                e.printStackTrace();
                ajaxResult.setSuccess(false);
            }
        }
        return ajaxResult;
    }
}

(2).业务逻辑层(接口) UserService

package com.test.service;

import com.test.bean.User;

public interface UserService {

    //查询登录用户
    User queryForLogin(User user);

    //注册用户
    void insertUser(User user);
}

(3).业务逻辑实现 UserServiceImpl

package com.test.serviceImpl;

import com.test.bean.User;
import com.test.dao.UserDao;
import com.test.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    @Override
    public User queryForLogin(User user) {
        return userDao.queryForLogin(user);
    }

    @Override
    public void insertUser(User user) {
        userDao.insertUser(user);
    }
}

(4)数据访问层

package com.test.dao;

import com.test.bean.User;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;

@Repository
public interface UserDao {

    //由于该查询语句较为简单,所以可以直接在@Select注解中写SQL语句
    @Select("select * from t_user where username = #{username} and password = #{password}")
    User queryForLogin(User user);
      
   //sql语句在mapper-user.xml文件中编写
    void insertUser(User user);
}

此时应该在mapper-user.xml文件中添加insertUser方法对应的SQL语句
mapper-user.xml





    
    
        insert INTO t_user (username, password)
        values (#{username},#{password})
    
    

此时进行测试
使用IDEA基于Maven搭建SSM(Spring+SpringMVC+MyBatis)框架并完成登录注册案例(附源码)_第15张图片
使用IDEA基于Maven搭建SSM(Spring+SpringMVC+MyBatis)框架并完成登录注册案例(附源码)_第16张图片
不出问题的话,注册应该也是没有什么问题的。

2.使用拦截器阻止未登陆的用户访问index.jsp页面
可能有人会想到如果直接在浏览器中输入http://localhost:8080/ssmtest/index,那么能不能直接访问到index.jsp页面?如果在用户访问该页面之前不进行登陆信息验证的话,那么是可以直接访问到的,这显然是不安全的。所以这里可以使用SpringMVC的组件拦截器(具体相关内容可以参考我之前整理的浅谈SpringMVC中的拦截器控件)
(1)添加拦截器类LoginInteceptor.java

package com.test.web;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class LoginInteceptor implements HandlerInterceptor{

    /*在拦截器拦截之前判断是否之后的操作
     * @return false:不再继续执行后面的操作
     *         true:继续执行后面的操作
     * */
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        //判断当前的用户是否已经登录
        HttpSession session = httpServletRequest.getSession();
        String loginUser = (String)session.getAttribute("loginUser");

        //用户未登陆,跳转到登录页面
        if(loginUser == null){
            String path = session.getServletContext().getContextPath();
            httpServletResponse.sendRedirect(path + "/login");
            return false;
        }else{
            return true;
        }

    }

    //在拦截器拦截完毕之后进行的操作
    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {

    }

    //在完成视图渲染之后进行的操作
    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

    }
}

(2)在springmvc-context.xml文件中配置该拦截器




    
    
        
    


    
    
    
    


    
    
        
        
        
    

    
    
        
        
            
            
            
            
            
            
            
            
            
            
            
            
        
    


3.使用Cookie完成记住用户名的功能
在CookieUtils .java中创建findCookie方法,便于寻找用户名

package com.test.utils;

import javax.servlet.http.Cookie;

//在浏览器中回显用户名
public class CookieUtils {

    public static Cookie findCookie(Cookie[] cookies , String name){
        if(cookies == null){
            // 说明客户端没有携带Cookie:
            return null;
        }else{
            // 说明客户端携带Cookie:
            for (Cookie cookie : cookies) {
                if(name.equals(cookie.getName())){
                    return cookie;
                }
            }
            return null;
        }
    }
}

其余相关的操作在前面的代码已经给出

4.防止用户多处登录
(1).创建一个用户缓存类LoginCache.java,用于在session中保存用户的相关信息,以便于之后的验证

package com.test.utils;

import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.Map;

public class LoginCache {

    //使用单例模式
    private LoginCache(){}

    private static LoginCache instance = new LoginCache();

    public static LoginCache getInstance(){
        return instance;
    }

    // key值:登录用户登录名,value值:登录用户sessionId
    private Map loginUserSession = new HashMap();
    //key值:登录用户sessionId,value值:登录用户session对象
    private Map loginSession = new HashMap();

    /**
     * 通过登录名获取对应登录用户的sessionId
     * @param username
     * @return
     */
    public String getSessionIdByUsername(String username){
        return loginUserSession.get(username);
    }

    /**
     * 通过sessionId获取对应的session对象
     * @param sessionId
     * @return
     */
    public HttpSession getSessionBySessionId(String sessionId){
        return loginSession.get(sessionId);
    }

    /**
     * 存储登录名与对应的登录sessionID至缓存对象
     * @param username
     * @param sessionId
     */
    public void setSessionIdByUserName(String username,String sessionId){
        loginUserSession.put(username, sessionId);
    }

    /**
     * 存储sessionId与对应的session对象至缓存对象
     * @param sessionId
     * @param session
     */
    public void setSessionBySessionId(String sessionId,HttpSession session){
        loginSession.put(sessionId, session);
    }

}

(2)创建LoginSessionListener类,用户监听用户属性在session中的变化

package com.test.listener;

import com.test.utils.LoginCache;

import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;

public class LoginSessionListener implements HttpSessionAttributeListener{

    private static final String LOGINUSER="loginUser";

    @Override
    public void attributeAdded(HttpSessionBindingEvent httpSessionBindingEvent) {
        //获得session中添加的属性值的名称
        String attrName = httpSessionBindingEvent.getName();

        if(LOGINUSER.equals(attrName)){
            //获取添加的属性值,即用户登录名
            String attrValue = (String)httpSessionBindingEvent.getValue();
            //该次操作的session对象
            HttpSession session1 = httpSessionBindingEvent.getSession();
            //该次操作的session对象ID
            String sessionId = session1.getId();
            //从缓存对象里面,获得该用户登录名对应的sessionID值
            String sessionId2 = LoginCache.getInstance().getSessionIdByUsername(attrValue);
            //未获得结果,不需要清理前次登录用户会话信息
            if(null == sessionId2){

            }else{
                HttpSession session2 = LoginCache.getInstance().getSessionBySessionId(sessionId2);//获取前次该用户登录对应的session对象
                //清理前次登录用户会话存储信息,使得前次登录失效
                session2.invalidate();
            }

            //完成该次登录用户登录名、sessionID,session对象的缓存对象存储
            LoginCache.getInstance().setSessionIdByUserName(attrValue, sessionId);
            LoginCache.getInstance().setSessionBySessionId(sessionId, session1);
        }
    }

    @Override
    public void attributeRemoved(HttpSessionBindingEvent httpSessionBindingEvent) {

    }

    @Override
    public void attributeReplaced(HttpSessionBindingEvent httpSessionBindingEvent) {

    }
}

(3)在web.xml文件中注册该监听器





  
  
    contextConfigLocation
    classpath*:spring/spring-*.xml
  
  
    org.springframework.web.context.ContextLoaderListener
  


  
  
    springmvc
    org.springframework.web.servlet.DispatcherServlet
    
      contextConfigLocation
      classpath:spring/springmvc-context.xml
    
    1
  
  
    springmvc
    /   
  


  
  
    encoding
    org.springframework.web.filter.CharacterEncodingFilter
    
      encoding
      UTF-8
    
    
      forceEncoding
      true
    
  
  
    encoding
    springmvc
  

  
  
    com.test.listener.LoginSessionListener
  


        

这样一来,若同一个用户在两处登录同一个账号时,那么前一个登录的用户信息会被清除,并且由拦截器拦截到用户信息在session中为空之后,直接跳转到login.jsp页面,这样便实现了同一个用户不能多处登录。
好啦!到这里为止,一个基于SSM框架的登录注册案例便完成了。一些必要的注释我已经在代码中给出,由于文字不能完全地还原整个开发过程,所以给出的代码顺序会存在一些前后台不同步的情况,不过给出的代码应该是完整的。如果大家发现了错误可以直接提出来哦~~
该案例源码:ssmtest
提取码:86rm

你可能感兴趣的:(Java,Web开发)