SkillAgentSearch skills...

Ssm

:bowtie: Spring、SpringMVC、Mybatis introduction case

Install / Use

/learn @TyCoding/Ssm
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

手把手教你入门SSM框架开发

关于SSM框架环境搭建,请点击这里前往我的博客:SSM框架整合之环境搭建 由于本项目采用了maven,关于IDEA搭建maven项目过程请点击这里前往我的博客:maven起步

如果觉得不错就点击右上角star鼓励一下作者吧!

关于项目

测试环境

后端:spring+mybatis+springmvc 
前端:bootstrap+Font Awesome图标集
测试环境:IDEA + tomcat8 + mysql5.7 + jdk8 + maven

项目功能

1. 实现用户登录功能
2. 实现客户信息的增删改查功能
3. 实现分页查询功能(使用PageHelper分页插件实现)

文档

更多文档将在我的公众号 程序员涂陌 中陆续发布,请持续关注!

| 程序员涂陌 | | ----------------------------------------------------------- | | qrcode_for_gh |

捐赠

| Alipay | WechatPay | | ---------------------------------------------------------- | ---------------------------------------------------------- | | alipay_258px | wechat_258px |

项目结构

.
├── README.md 
├── img  -- 放了一些README.md文档所需要的图片,没有实际意义
├── pom.xml
└── src
    └── main
        ├── java
        │   └── cn
        │       └── tycoding
        │           ├── controller  -- SpringMVC-WEB层控制器
        │           ├── mapper  -- Mybatis接口和映射文件。本项目采用了mybatis的接口开发,所以接口和映射文件放在同一目录下,并且名称相同。
        │           ├── pojo  -- JavaBean实体类
        │           └── service  -- service业务层
        ├── resources  -- maven项目存放配置文件的根目录(classpath:)
        │   ├── sys_schema.sql  -- 项目数据库创建和表创建的SQL语句
        │   ├── resource  -- 日志打印和数据源配置文件
        │   └── spring  -- spring和springmvc的配置文件
        └── webapp  -- 项目的根目录
            ├── WEB-INF
            ├── fonts  -- 字体的配置文件
            └── lib  -- 前端静态资源

整合思路

继上一篇博文:Spring MVC起步其实我们已经了解了如何整合Spring和Spring MVC框架。那么,接下来我们就需要了解如何在此基础上整合Mybatis框架。 首先须知Mybatis框架是一个持久层框架,而Spring MVC是WEB层框架,Spring框架则充当着业务层的角色。那么将三者联系起来正好组成了web--service--dao的三层架构体系。那么整合思路就如下所示了:

  1. 整合dao(即mapper),实现Mybatis和Spring的整合
  2. 整合service,由Spring管理service接口,在service中可以调用dao(mapper)
  3. 整合web(controller),实现Spring MVC和Spring的整合,在controller中调用service

需求实现

1. 实现用户登录功能

1.1 创建表结构

SQL语句请查看GitHub中resources目录下的.sql文件 除了创建表,我们同样要创建pojo对象,并提供属性setter和getter方法。(注意尽量保持pojo属性参数和表字段名称对应相等)

1.2 编写Controller层

@RequestMapping(value = "/login")
public String login(@RequestParam String username,@RequestParam String password, Model model) {
    User user = userService.login(username);
    if (user != null) {
        if (user.getPassword().equals(password)) {
            //登录成功
            return "page/page";
        } else {
            model.addAttribute("message", "登录失败");
            return "page/loginInfo";
        }
    } else {
        model.addAttribute("message", "你输入的用户名或密码有误");
        return "page/loginInfo";
    }
}

注意

  • @RequestMapping标注login()方法有两个作用(前提是必须在XML中开启注解扫描<context:component-scan/>):1.表示该方法是请求处理方法;2.指明了该方法的请求路径。

  • @RequestMapping可以标记类或方法,分别表示了不同层级的请求路径。例如当前的login()方法的请求路径应为:localhost:8080/xxx/login.do(需要注意的是:本例中使用了IDEA开发工具,访问其部署到Tomcat上的项目默认是不加项目名的,但是使用eclipse访问项目可能默认需要加上项目名,具体要看实际开发工具中对Tomcat的配置)

  • 对于请求体中包含多个参数的情况,我们尽量用@RequestParam注解标记参数,以免出现未知错误(但这不是必须的)。@RequestParam注解能帮助识别请求体中的参数,比如请求体中传递的参数名是id,但是你用int uid接收就可能会报错400(请求参数错误),这时我们使用@RequestParam("id")就能帮助Spring装配这个参数。

用户登录,我们首先获取到用户登录的用户名username和密码password,然后根据用户名查询并返回,根据此用户名查询到的密码与登录的密码进行equals,如果相等就登录成功。(当然我们要判断根据username查询后的返回值是否为null,不做判断会产生空指针问题,如果一个空值和另一个值相比显然会报错)。 如果登录成功,将返回到page/page.jsp页面(这是根据我们在springmvc.xml下配置的视图解析器InternalResourceViewResolver决定的);如果登录失败将返回到page/loginInfo.jsp页面。比如本项目中配置的视图解析器:

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	<property name="prefix" value="/WEB-INF/"/>
	<property name="suffix" value=".jsp"/>
</bean>

只要在SpringMVC的配置文件中配置了这个选项,SpringMVC就默认匹配Controller层(用@Controller标识的类)中返回值为String类型的映射方法中return的数据和webapps/WEB-INF/xx.jsp中JSP页面的文件名,映射方法(用@RequestMapping标识的方法)return的值和/WEB-INF/下某个JSP页面文件名相同就跳转到这个页面,否者就报错404。当然除了使用@ResponseBody标识的方法和@RestController标识的类,因为这两个注解会将其下的方法返回值都转换为JSON 格式的数据,并且不会被InternalResourceViewResolver识别。

1.3 编写Mapper.xml

<select id="login" parameterType="String" resultType="User">
    select * from user where username = #{username}
</select>

我们使用了Mybatis的接口代理开发模式(保证接口和配置文件在同一目录下且名称相同),直接在Mapper.xml中编写原生sql语句,即可进行与数据库间的交互。其中:

  • id指明是哪个方法调用这个sql;

  • parameterType指定了接口传递的参数类型(我们根据用户名查询所以是String类型);

  • resultType指定该查询语句返回值的数据类型(因为我们已经在配置文件启用了别名配置typeAliases,所以这里直接指定pojo对象类名即可;若没有启动别名配置,就必须写类的全限定名)。使用#{}会将传递的参数值会自动添加"";注意#{}${}区分,后者则是直接拼接传递进来的字符串,而不会添加任何符号,且前者能避免sql注入。

2. 实现客户信息的添加

所谓添加客户信息,就是将JSP中提交的表单数据持久化到数据库中。

2.1 创建表结构

建表SQL请看github项目中的resources目录下的.sql文件 同样我们还要创建对应的pojo,并提供getter和setter方法。(尽量保持pojo中的元素属性名称和表中字段名称相同)。

2.2 编写Controller层

@RequestMapping(value = "/save")
public String save(Customer customer, Model model) {
    customerService.save(customer);
    model.addAttribute("message", "保存客户信息系成功");
    return "page/info";
}

当点击了提交按钮,表单中的所有数据都应该被持久化到数据库中,而要知道表单中的参数有很多,我们直接在请求映射方法的参数列表中写参数显然是不可取的,那么我们如果写一个pojo对象,Spring就会根据这个pojo对象中的属性和JSP表单中的参数进行对应,如果完全对应那么请求方法会正常执行,一但有某个参数不对应,那么就会报错。(注意我们表单中并不需要指定id主键值,因为设计表时已经指定了该id主键为自增长,即使不指定值,id依然会自增,你指定了却可能会产生错误,因为到保证每次的id值都是递增的)。当数据持久化成功,就使用Spring的Model对象在域对象中设置一个名为message的值。最后再返回到视图层。

2.3 编写Mapper.xml

<insert id="save" parameterType="Customer">
        insert into
        customer(
          name,
          telephone,
          address,
          remark)
        values(
          #{name},
          #{telephone},
          #{address},
          #{remark}
        );
</insert>

如上这仍然是普通的SQL语句,注意parameterType如上我们设置为Customer其实代表的是cn.tycoding.pojo.Customer这个对象,因为我们已经在beans.xml中启用了mybatis的别名配置。SQL插入语句中不需要指定id这个字段,原因是我们已经配置了id为自增主键

3. 实现客户信息的删除功能

3.1 编写Controller层

@RequestMapping(value="/delete")
public String delete(@RequestParam int id,Model model){
    if(customerService.delete(id) > 0){
        model.addAttribute("message","删除客户信息成功");
        return "page/info";
    }else{
        model.addAttribute("message","删除客户信息失败");
        return "page/info";
    }
}

删除功能只需要根据点击删除按钮时获取到的id值,在SQL的delete语句中where这个id值,即可以实现根据id删除客户信息。

3.2 编写Mapper.xml

<delete id="delete" parameterType="int">
    delete from customer where id = #{id}
</delete>

如此,还是一个再普通不过的SQL语句,既可以实现根据id删除的功能。

4. 更新客户信息

更新客户信息需要我们实现两个功能:1.再点击编辑按钮时(我们在按钮设置了onclick="return edit(${xx.id};"),如此我们用js监听这个事件,点击了按钮,js获取到id,请求后台根据这个id值查询数据库中的数据。那么我们先看一下js部分吧:

function edit(id){
  $.ajax({
    url: 'xxx/findById.do',
    type: 'POST',
    dataType: 'json',
    contentType: 'application/json;charset=UTF-8',
    data: JSON.stringify({id: id}),
    success: function(result){
      $("#username").val(result.username);
      $("#password").val(result.password);
      //继续讲查询到的字段依次进行赋值...
    }
  });
}

以上实际是一个ajax请求json格式数据:

  1. type指定请求类型;

  2. dataType指定了服务器返回数据格式类型;

  3. contentType指定发送给服务器的数据格式,默认是application/x-www-form-urlencoded会使此时的data参数为JSON对象,而设置为application/json后此时的data参数就是json字符串了,同样使用stringify()也是将data参数转换成json字符串。

4.1 编写Controller层

@ResponseBody
@RequestMapping(value="/findById")
public Customer findById(@RequestBody Customer customer){
    Customer customer_info = customerService.findById(customer.getId());
    if(customer_info != null){
        return customer_info;
    }else{
        return null;
    }
}
  • @RequestBody读取http请求内容,并将数据绑定在映射方法的参数上;
  • @ResponseBody将映射需要返回的参数转换成指定的数据格式,而由于我们在ajax请求中指定dataTypejson,那么@ReqponseBody将会返回json格式数据。

当ajax请求了这个映射方法,Controller获取到指定的id去调用Service层根据这个id查询数据库select * from customer where id = #{id}。然后将数据拼装成JSON格式,并返回给页面。最后ajax会走success方法,我们从返回的数据success:function(result)中通过result.xx的方式取出来并通过jquery的val()方式赋值到指定的位置,那么就实现了数据回显。 实现修改功能,首先要知道原本的数据(数据回显),然后将修改后的数据在此存入到数据库中(update customer set xx=#{xx} where id = #{id}。那么我们看一下,更新数据库的Controller:

@RequestMapping(value="/update")
public String update(Customer customer,Model model){
    int rows = customerService.update(customer);
    if(rows > 0){
        model.addAttribute("message","更新客户信息成功");
        return "page/info";
    }else{
        model.addAttribute("message","更新客户信息失败");
        return "page/info";
    }
}

因为更新数据其实就是简单的提交表单,表单提交后访问这个映射方法,指定对应的update语句,如果没有异常抛出就更新成功,通过SpringMVC的Model方法向request域对象中存入成功信息,在返回的页面中,通过${message}EL表达式的方式取出提示信息。

最后我们看一下更新的SQL如何写:

4.2 编写Mapper.xml

<!-- 更新客户信息的方法 -->
<update id="update" parameterType="Customer">
    update customer set
        id = #{id},
        name = #{name},
        telephone = #{telephone},
        address = #{address},
        remark = #{remark}
    where id = #{id}
</update>

5. 分页查询

我们先看一下前端Bootstrap的分页效果

5.1 封装PageBean

这里我们使用Mybatis的分页查询插件:PageHelper。

1.首先引入maven依赖:

<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>4.0.0</version>
</dependency>

2.定义一个PageBean,非必要,但是提取通用的PageBean实体类对象用来储存分页数据,能提高代码的重用率。

虽然我们这里使用了PageHelper分页插件,但是请弄清楚:pageHelper只是帮我们进行后端的数据分页,也就是说使用了PageHelper插件我们无需再写类似 limit这样的sql了。

而,我们的数据最终要显示到前端页面上,此时我们使用的bootstrap和javascript技术并不能实现前端分页自动计算,所以前端我们还是需要手动计算分页数据。

那么PageBean的定义不变:

public class PageBean<T> implements Serializable {
    //当前页
    private int pageCode;

    //总页数=总记录数/每页显示的记录数
    private int totalPage;

    //总记录数
    private int totalCount;

    //每页显示的记录数
    private int pageSize;

    //每页显示的数据
    private List<T> beanList;
}

因为我们要实现分页查询,所以无法避免一些参数,这里直接将其封装为一个JavaBean就是为了方便调用,而配置自定义泛型<T>就是为了供多个对象的调用,如果你在对Customer类进行分页查询,那么在调用时只需要new pageBean<Customer>()即可将查询的数据绑定为Customer类的数据;对其他类进行分页亦是这样。

  • pageCode: 表示当前(你点击)的是第几页。

  • totalPage: 表示总页数(总页数=总记录数/每页显示的记录数

View on GitHub
GitHub Stars368
CategoryDevelopment
Updated1mo ago
Forks134

Languages

Java

Security Score

80/100

Audited on Feb 9, 2026

No findings