当前位置: 首页 > news >正文

基于maven的spring项目实现登录注册(SSM)

先前参考这位大佬的文章写项目出了很多问题,经过不断修改之后终于项目得以平稳运行了。

以下是我的踩坑记录以及对应的de解决方案(不过有一个问题是解决了但是我不懂深层次理由,对此有理解的友友希望可以帮我解答。)

首先上出现最多最严重以及我没理解报错原理的一个问题。

大概就是我已经定义了sqlsessionFactory的bean,但项目无法识别出来无法创建sqlsessionFactory对象。

解决的方案仅仅是删掉以下代码,大家可以对比一下,上面是正确的,下面是最初我错误的那一版。

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">

        <!-- 引用上面已经配置好的数据库连接池 -->
        <property name="dataSource" ref="dataSource" />
    </bean>

    <!-- 配置mapper接口的扫描器,将Mapper接口的实现类自动注入到IoC容器中 实现类Bean的名称默认为接口类名的首字母小写 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">

        <!-- basePackage属性指定自动扫描mapper接口所在的包 -->
        <property name="basePackage" value="com.test.dao"/>

    </bean>



<!--上面正确,下面的是错的-->

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean" >
        <property name="configLocation" value="classpath:mybatis/config.xml" />
        <property name="dataSource" ref="dataSource" />
        <property name="mapperLocations" >
            <list>
                <value>classpath*:mybatis/mapper-user.xml</value>
            </list>
        </property>
    </bean>

 <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">

        <!-- 引用上面已经配置好的数据库连接池 -->
        <property name="dataSource" ref="dataSource" />
    </bean>

    <!-- 配置mapper接口的扫描器,将Mapper接口的实现类自动注入到IoC容器中 实现类Bean的名称默认为接口类名的首字母小写 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">

        <!-- basePackage属性指定自动扫描mapper接口所在的包 -->
        <property name="basePackage" value="com.test.dao"/>

    </bean>

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean" >
    <property name="configLocation" value="classpath:mybatis/config.xml" />
    <property name="dataSource" ref="dataSource" />
    <property name="mapperLocations" value="classpath*:mybatis/mapper-user.xml" >
    </property>
</bean>

不一致的部分是两版不同,初版是通过mapper-user.xml文件加载SQL语句,而第二版是存在一个userMapper的接口类来加载SQL语句。让人在意的是标了红色不一致的这行代码。

查了一下说法是:

 <property name="configLocation" value="classpath:mybatis-config.xml"/>

单独新建一个mybatis-config.xml文件,然后依赖注入进Spring容器里

spring容器里引入mybatis-config,mybatis-config里有Mapper映射文件地址就直接获取了。

但我运行的时候出现了严重的问题

 删除这一行并且添加:  

<!-- basePackage属性指定自动扫描mapper接口所在的包 -->
        <property name="basePackage" value="com.test.dao"/>

   <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">

通过MapperScannerConfigurer来扫描Dao包里面的mapper接口,动态的将mapper接口进行实例化;

2、并将sqlSessionFactory注入到mapper实例中并自动创建sqlsession。

运行成功!

 按理说我原本的配置了config.xml文件,它应该能能够索引到,但是不知道为什么无法创建sqlsession对象还报错没有相关的bean。

接下来是整个项目的流程。

创建项目没啥好说的。

主要是项目结构不要出错,接下来我们先要明确需求——完成登录和注册两个功能,那么就需要登录方法和查询用户的SQL语句和注册方法。

准备工作如下:

pom文件所需要的依赖:

<dependencies>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>4.3.7.RELEASE</version>
  </dependency>
  <!-- Spring-JDBC
    包含对Spring对JDBC数据访问进行封装的所有类。外部依赖spring-beans,spring-dao
 -->
  <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>4.3.7.RELEASE</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>4.3.7.RELEASE</version>
  </dependency>

  <!--MyBatis包 -->
  <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
  <dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.2</version>
  </dependency>

  <!-- MyBatis整合Spring的适配包 -->
  <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
  <dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>1.3.1</version>
  </dependency>
  <!-- 数据库连接池、驱动 -->
  <!-- https://mvnrepository.com/artifact/c3p0/c3p0 -->
  <dependency>
    <groupId>c3p0</groupId>
    <artifactId>c3p0</artifactId>
    <version>0.9.1.2</version>
  </dependency>

  <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
  <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.28</version>
  </dependency>

  <!-- JSP:标准标签库
    引入jstl/jar保证jsp页面可以使用EL表达式 -->
  <!-- https://mvnrepository.com/artifact/jstl/jstl -->
  <dependency>
    <groupId>jstl</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
  </dependency>

  <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
  <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.0.1</version>
    <!-- provided表明该包只在编译和测试的时候用,
        当启动tomcat(在其中有servlet-api包)的时候,就不会冲突了-->
    <scope>provided</scope>
  </dependency>

  <!-- 单元测试junit包 -->
  <!-- https://mvnrepository.com/artifact/junit/junit -->
  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
  </dependency>

  <!--与json有关的包-->
  <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.9.6</version>
  </dependency>
  <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>2.9.6</version>
  </dependency>
  <dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.6</version>
  </dependency>
</dependencies>

准备好tomcat,这里选用的是tomcat8版本,pom文件依赖的版本根据自己实际情况更改。

 准备好这些之后,我们要在源文件夹写入相关的类和实现业务。

 如果Java文件夹不是蓝色的,前往项目结构-模块,选中自己的项目,在src目录下找到Java目录,选中Java目录然后点击原码,Java就变蓝了,同理resource文件如果没有资源目录标识也是选中resource目录然后点击有跟源码同一栏的Recourse即可。

 接下来是准备好实体类在pojo(domain)或者你自己实体类的包下面。

创建实体类步骤很简单,就是访问数据库所需要的字段、关于字段的有参无参构造和getset方法以及根据需要要不要生成toString();

大致这个样子。

 

按照流程走,接下来是需要准备好数据库驱动的连接。(数据库加载驱动和连接的参数XXX.properties)

一般内容如下;

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/你要连接的数据库名称
jdbc.username=你数据库的用户名
jdbc.password=你访问数据库的密码

为了能方便加载驱动,我们在spring-context.xml文件里面配置bean来获取properties文件的内容

我用的是c3p0,德鲁伊的要用德鲁伊的class。

    <!-- 3.加载数据库的属性文件并配置数据库连接池(c3p0) -->
    <context:property-placeholder location="classpath:jdbc.properties"/>
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" >
        <property name="driverClass" value="${jdbc.driver}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

配置成功你的properties文件应该会变橙色:

配置好数据库之后开始程序员的老本行——CRUD(增删改查)

login功能对应查找select

注册功能对应增加insert

我们可以在dao层自己创建一个mapper接口类来放置这下SQL语句。如下图所示:

@Mapper
@Component
public interface UserMapper {
    //增加用户
    @Insert("insert into user (username,password,name) values (#{username},#{password},#{name})")
    void insert(@Param("username") String username, @Param("password") String password, @Param("name") String name);

    //查询用户
    @Select("select * from user where username = #{username} and password=#{password}")
    User findAll(@Param("username") String username, @Param("password") String password);

}

也可以编写一个mapper.xml文件,甚至这个文件更好,可以动态抽取SQL语句,大致内容如下:

<?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.itheima.mapper.UserMapper">

    <!--sql语句抽取-->
    <sql id="selectUser">select * from user</sql>

    <select id="findByCondition" parameterType="user" resultType="user">
        <include refid="selectUser"></include>
        <where>
            <if test="id!=0">
                and id=#{id}
            </if>
            <if test="username!=null">
                and username=#{username}
            </if>
            <if test="password!=null">
                and password=#{password}
            </if>
        </where>
    </select>

    <select id="findByIds" parameterType="list" resultType="user">
        <include refid="selectUser"></include>
        <where>
            <foreach collection="list" open="id in(" close=")" item="id" separator=",">
                #{id}
            </foreach>
        </where>
    </select>


</mapper>

之后就是老流程dao-service-serviceImpl。

@Mapper
@Component
public interface UserMapper {
    //增加用户
    @Insert("insert into user (username,password,name) values (#{username},#{password},#{name})")
    void insert(@Param("username") String username, @Param("password") String password, @Param("name") String name);

    //查询用户
    @Select("select * from user where username = #{username} and password=#{password}")
    User findAll(@Param("username") String username, @Param("password") String password);

}

 

 由于前后端分离,我们需要把查询到的数据封装为前端数据对象,因此注意!

需要写一个封装类名字自定义来封装我们的数据!千万不能忘记!

package com.test.bean;

import org.springframework.stereotype.Component;

import java.io.Serializable;

/**
 * 用于封装后端返回前端数据对象
 */
@Component
public class ResultInfo implements Serializable {
    private boolean flag;//后端返回结果正常为true,发生异常返回false
    private Object data;//后端返回结果数据对象
    private String errorMsg;//发生异常的错误消息

    //无参构造方法
    public ResultInfo() {
    }
    public ResultInfo(boolean flag) {
        this.flag = flag;
    }
    /**
     * 有参构造方法
     * @param flag
     * @param errorMsg
     */
    public ResultInfo(boolean flag, String errorMsg) {
        this.flag = flag;
        this.errorMsg = errorMsg;
    }
    /**
     * 有参构造方法
     * @param flag
     * @param data
     * @param errorMsg
     */
    public ResultInfo(boolean flag, Object data, String errorMsg) {
        this.flag = flag;
        this.data = data;
        this.errorMsg = errorMsg;
    }

    public boolean isFlag() {
        return flag;
    }

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

    public Object getData() {
        return data;
    }

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

    public String getErrorMsg() {
        return errorMsg;
    }

    public void setErrorMsg(String errorMsg) {
        this.errorMsg = errorMsg;
    }
}

之后就是编写控制类controller来实现我们的需求。

需要注意的是在我自己后端测试的时候是get方式,需要提交前端是则是post,要理解两种方式的区别。

package com.test.controller;


import com.test.bean.ResultInfo;
import com.test.bean.User;
import com.test.service.UserService;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;

@Controller
@RequestMapping(value = "user")
public class DispatcherController {

    @Resource
    private UserService userService;

    @Resource
    private ResultInfo resultInfo;

    @RequestMapping(value = "/login" ,method = RequestMethod.POST)
    @ResponseBody
    public ResultInfo login(User user) {
        User userAll = userService.findAll(user.getUsername(),user.getPassword(),user.getName());

        if (userAll != null ) {
            resultInfo.setFlag(true);
            resultInfo.setErrorMsg("登录成功");
        } else {
            resultInfo.setFlag(false);
            resultInfo.setErrorMsg("账户名或密码错误");
        }

        return resultInfo;
    }

    @RequestMapping(value = "/register" ,method = RequestMethod.POST)
    @ResponseBody
    public ResultInfo register(String username, String password, String email,String name) {
        User name1 = userService.findName(username);

        if (name1 != null) {
            resultInfo.setFlag(false);
            resultInfo.setErrorMsg("用户名已存在");
        } else {
            userService.insert(username, password, email,name);
            resultInfo.setFlag(true);
            resultInfo.setErrorMsg("注册成功");

        }
        return resultInfo;
    }
}

监听器和拦截器留在下章说,之前因为拦截器逻辑设计有点问题——比如我设置了一个未登录用户会自动跳转登录用户,正常来说应该是跳转首页,直接变成了一刀切,就无法完成我的注册需求了。

相关文章:

  • 【C++】动态内存管理
  • 波士顿动力再惊艳!机器人大秀男团舞,举手投足人味满满,多次转卖后展示新标签...
  • Python 代码托管到码云平台,原来这么简单
  • 【MATLAB教程案例26】图像特征点提取算法matlab仿真与分析——sift,surf,kaze,corner,BRISK等
  • 前端深拷贝与浅拷贝(附实现方法)
  • C#工业生产线MES系统,源代码分享
  • 2022软考高项十大领域知识整理(四)-人力资源管理、干系人管理、采购管理
  • 企业级低代码平台Jeecgboot3.4.2及3.4.3版本新功能介绍
  • SQL SERVER Sequence Number 序列号
  • 【Web实战-Tomcat-Servlet-Thymeleaf -JDBC-MySQL】浏览器页面显示数据库数据(水果库存系统)
  • 【超好懂的比赛题解】2022CCPC四川省赛 个人题解
  • Pytest如何执行txt格式的文本测试
  • 目标检测算法——YOLOv5 结合Swin Transformer V2
  • Web3究竟红在哪里,它的出现能为人类社会带来什么?
  • 【学姐面试宝典】前端基础篇Ⅴ——JS深浅拷贝、箭头函数、事件监听等
  • [ 一起学React系列 -- 8 ] React中的文件上传
  • 【译】理解JavaScript:new 关键字
  • Asm.js的简单介绍
  • E-HPC支持多队列管理和自动伸缩
  • happypack两次报错的问题
  • Java IO学习笔记一
  • miniui datagrid 的客户端分页解决方案 - CS结合
  • PHP那些事儿
  • RxJS: 简单入门
  • session共享问题解决方案
  • ucore操作系统实验笔记 - 重新理解中断
  • Webpack 4x 之路 ( 四 )
  • 看完九篇字体系列的文章,你还觉得我是在说字体?
  • 聊聊spring cloud的LoadBalancerAutoConfiguration
  • 罗辑思维在全链路压测方面的实践和工作笔记
  • 微信公众号开发小记——5.python微信红包
  • 微信小程序上拉加载:onReachBottom详解+设置触发距离
  • 主流的CSS水平和垂直居中技术大全
  • # C++之functional库用法整理
  • $emit传递多个参数_PPC和MIPS指令集下二进制代码中函数参数个数的识别方法
  • (C语言)strcpy与strcpy详解,与模拟实现
  • (C语言)输入一个序列,判断是否为奇偶交叉数
  • (Git) gitignore基础使用
  • (多级缓存)缓存同步
  • (强烈推荐)移动端音视频从零到上手(上)
  • (十一)c52学习之旅-动态数码管
  • (转载)深入super,看Python如何解决钻石继承难题
  • .NET 4.0中使用内存映射文件实现进程通讯
  • .Net Core缓存组件(MemoryCache)源码解析
  • .NET DevOps 接入指南 | 1. GitLab 安装
  • .net web项目 调用webService
  • .NetCore 如何动态路由
  • .NET的数据绑定
  • [ Linux 长征路第五篇 ] make/Makefile Linux项目自动化创建工具
  • [20190401]关于semtimedop函数调用.txt
  • [C++]指针与结构体
  • [C++从入门到精通] 14.虚函数、纯虚函数和虚析构(virtual)
  • [CTO札记]盛大文学公司名称对联
  • [Firefly-Linux] RK3568 pca9555芯片驱动详解
  • [LeetCode] Sort List