前言
作为一名Java小白,最近使用SpringBoot+MyBatis搭建了一个简单的Spring Web 项目,当然毫无意外的,我采坑了,而这个坑呢,困扰了我足足两天时间😭,不得不记录下。
一、项目结构预览
通过File —> New —>Project ---->Spring Initializer,创建一个Spring Web项目,这样的话,大体的框架IDEA会帮你自动建好,不用自己去手动创建,省了很多时间。当然,这个是专业版的IDEA,如果是社区版的,是没有Spring Initializer的哦!!!
二、结构介绍
- Controller层: 该层主要负责封账API接口,即在浏览器中输入的URL地址。
package com.example.mybatis_mon.Controller;
import com.example.mybatis_mon.Service.UserService;
import com.example.mybatis_mon.entity.WebUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
@RestController
public class UserController {
@Autowired
private UserService userService;
private WebUser getElements(HttpServletRequest request) {
return getWebUser(request);
}
public static WebUser getWebUser(HttpServletRequest request) {
String username = request.getParameter("username");
String password = request.getParameter("password");
String phone = request.getParameter("phone");
String email = request.getParameter("email");
Integer age = Integer.valueOf(request.getParameter("age"));
Integer sex = Integer.valueOf(request.getParameter("sex"));
Double salary = Double.valueOf(request.getParameter("salary"));
return new WebUser(username, phone, email, password, age, sex, salary);
}
@PostMapping("/login")
public WebUser login(HttpServletRequest request) {
String username = request.getParameter("username");
String password = request.getParameter("password");
return userService.loginUser(username, password);
}
@PostMapping("/register")
public int register(HttpServletRequest request) {
WebUser user = getElements(request);
return userService.registerUser(user);
}
@PostMapping("/addUser")
public int addUser(HttpServletRequest request) {
WebUser user = getElements(request);
return userService.addUser(user);
}
@PostMapping("/updateUser")
public int updateUser(HttpServletRequest request) {
WebUser user = getElements(request);
return userService.updateUser(user);
}
@DeleteMapping("/deleteUser")
public int deleteUser(HttpServletRequest request) {
WebUser user = getElements(request);
return userService.deleteUser(user);
}
@GetMapping("/selectUser")
public WebUser selectUser(HttpServletRequest request) {
return userService.selectUser(request.getParameter("phone"));
}
@GetMapping("/allUsers")
public List<WebUser> allUsers() {
List<WebUser> webUsers = userService.allUsers();
System.out.println(webUsers);
return webUsers;
}
}
对应的接口实现了什么功能可以直接从方法名就可以知道,这也是推荐的方法名定义规范,见名知意!!!
@Autowried主要是把UserService注入Bean中
- entity层:和Model层功能相似,主要是数据表对应的实体类。
注意上面所说的见名知意!!!,所以这里的类命名为数据库中对应的表名称,属性名也可数据表中的字段相对应,类型也是一样。
package com.example.mybatis_mon.entity;
public class WebUser {
private String username;
private String phone;
private String email;
private String passwd;
private Integer age;
private Integer sex;
private Double salary;
public WebUser() {
}
public WebUser(String username, String password) {
this.username = username;
this.passwd = password;
}
public WebUser(String username, String phone, String email, String password, Integer age, Integer sex, Double salary) {
this.username = username;
this.phone = phone;
this.email = email;
this.passwd = password;
this.age = age;
this.sex = sex;
this.salary = salary;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return passwd;
}
public void setPassword(String password) {
this.passwd = password;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Integer getSex() {
return sex;
}
public void setSex(Integer sex) {
this.sex = sex;
}
public Double getSalary() {
return salary;
}
public void setSalary(Double salary) {
this.salary = salary;
}
@Override
public String toString() {
return "WebUser{" +
"username='" + username + '\'' +
", phone='" + phone + '\'' +
", email='" + email + '\'' +
", password='" + passwd + '\'' +
", age='" + age + '\'' +
", sex='" + sex + '\'' +
", salary='" + salary + '\'' +
'}';
}
}
快速生成getter,setter方法小技巧(MAC):
Control + 回车键, 之后就可以看到这样的小界面,然后就可以选择你想创建的getter和setter, 以及构造方法等等。
- mapper:严格来说,这不算一个“层”,我们大多把mapper接口和其对应的mapper.xml文件放在这个package中。
package com.example.mybatis_mon.mapper;
import com.example.mybatis_mon.entity.WebUser;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface UserMapper {
int addUser(WebUser user);
int updateUser(WebUser user);
int deleteUser(String phone, String password);
WebUser login(String username, String password);
int register(WebUser user);
WebUser selectUser(String phone);
List<WebUser> allUsers();
}
UserMapper对应的UserMapper.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.example.mybatis_mon.mapper.UserMapper">
<!-- 通用查询结果列-->
<sql id="Base_Column_list">
username, phone, email, passwd, age, sex, salary
</sql>
<select id="selectUser" parameterType="com.example.mybatis_mon.entity.WebUser"
resultType="com.example.mybatis_mon.entity.WebUser">
select
<include refid="Base_Column_list"></include>
from web_user
where phone=#{phone}
</select>
<insert id="addUser" parameterType="com.example.mybatis_mon.entity.WebUser">
insert into web_user(username, phone, email, passwd, age, sex, salary)
values (#{username}, #{phone}, #{email}, #{password}, #{age}, #{sex}, #{salary})
</insert>
<update id="updateUser">
update web_user
<trim prefix="set" suffixOverrides=",">
<if test="username!=null">username=#{username},</if>
<if test="phone!=null">phone=#{phone},</if>
<if test="email!=null">email=#{email},</if>
<if test="password!=null">passwd=#{password},</if>
<if test="age!=null">age=#{age},</if>
<if test="sex!=null">sex=#{sex},</if>
<if test="salary!=null">salary=#{salary}</if>
</trim>
where
phone=#{phone}
</update>
<delete id="deleteUser" parameterType="java.lang.String">
delete
from web_user
where phone = #{phone}
or email = #{phone}
and passwd = #{password}
</delete>
<select id="login" resultType="com.example.mybatis_mon.entity.WebUser">
select
<include refid="Base_Column_list"></include>
from web_user
where
username=#{username} and passwd=#{password}
</select>
<insert id="register" parameterType="com.example.mybatis_mon.entity.WebUser">
insert into web_user (username, passwd, phone, email, age, sex, salary)
values (#{username}, #{password}, #{phone}, #{email}, #{age}, #{sex}, #{salary})
</insert>
<select id="allUsers" resultType="com.example.mybatis_mon.entity.WebUser">
select
<include refid="Base_Column_list"></include>
from web_user
</select>
</mapper>
切记:
- UserMapper.xml文件中的namespace需要填写UserMapper文件的全限定名称
- xml文件中对应的SQL语句的ID值需要和Mapper接口中的方法名称相同
- 返回值(restultType)和参数类型(parameterType)和对应方法的返回值和参数类型相同
- 做到上面几点之后,我们就再写一个UserMapper接口的实现类UserMapperImpl了。
- 判断是否都实现了,也有一个小技巧:写完这两个文件之后,可以看看Idea中是否出现这种标识。而且这个标识是可以点击的,可以直接达到对应的方法。
4.Service层:该层是对业务的封装,比如我们的登录注册就是一个个功能(业务点),在该层对参数等进行校验,返回值进行封装。
package com.example.mybatis_mon.Service;
import com.example.mybatis_mon.entity.WebUser;
import java.util.List;
public interface UserService {
WebUser loginUser(String username, String password);
int registerUser(WebUser user);
int addUser(WebUser user);
int deleteUser(WebUser user);
int updateUser(WebUser user);
WebUser selectUser(String phone);
List<WebUser> allUsers();
}
对应接口的实现类UserServiceImpl
package com.example.mybatis_mon.Service;
import com.example.mybatis_mon.entity.WebUser;
import com.example.mybatis_mon.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public WebUser loginUser(String username, String password) {
return userMapper.login(username, password);
}
@Override
public int registerUser(WebUser user) {
return userMapper.register(user);
}
@Override
public int addUser(WebUser user) {
if (selectUser(user.getPhone())!=null){
return 0;
};
return userMapper.addUser(user);
}
@Override
public int deleteUser(WebUser user) {
return userMapper.deleteUser(user.getPhone(), user.getPassword());
}
@Override
public int updateUser(WebUser user) {
return userMapper.updateUser(user);
}
@Override
public WebUser selectUser(String phone) {
return userMapper.selectUser(phone);
}
@Override
public List<WebUser> allUsers() {
return userMapper.allUsers();
}
public void setUserMapper(String userMapper) {
}
}
我们可以看到UserServiceImpl中很简单,没有想象中的对数据库进行访问啊,对传入的参数进行校验啊之类的。其中对数据库的访问我们在xml文件中就以及写好了,对于参数校验,因为这只是个测试项目,所以没有对参数进行校验,当然实际开发中,肯定是需要的,但是我们可以把这些放到一个名为Utils的package中。
好了,现在来说说困扰了我两天的问题
报错信息:
说我的UserMapper中的login方法没有找到,但是呢,我们从上面代码中可以看到该方法是存在的,然后呢,我找度娘,在网上找到了很多出现我同样问题的情况,但是他们的解决方法我统统尝试了,并没有解决我的问题。苦思冥想了许久,突然灵机一动,我把那些解决方法用到的都集成起来会怎么样呢?
出乎我的意料,问题解决了,Surprised!!!
下面是我的解决方法:
- 在UserMapper接口上面添加注解:@Mapper
- 在UserServiceImpl中使用@Autowried把UserMapper注入Bean
- 在pom.xml文件中重新定义xml文件的扫描规则
<resources>
<resource>
<!--资源目录-->
<directory>src/main/java</directory>
<includes>
<!-- 新添加 */代表一级目录, **/代表多级目录-->
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
除此之外也遇到了其他问题,但是呢,使用了上面的方法之后,问题都解决了。但是呢,我还是不明白,为什么我在application.properties中注入xml的扫描路径并没有起作用,反而还需要在pom.xml中重新定义xml文件扫描规则。
总之,在初学阶段,确实会遇到各种各样的问题,而这些问题呢,有时候连大佬都不一定能帮你解决,这时候呢,就需要你自己去查各种资料,看各种视频了。最后,都会解决了。加油,继续学习!!!