本次练习基于how2j和课本,进行SSM的初步整合,理解SSM整合的原理、好处。
how2j
简要的说明:
将我们(用户)作为整个流程的起点:当我们像浏览器发送访问请求时,我们首先出发的是整个web项目的核心配置文件web.xml
,它将所有的请求都交给控制器
处理,同时调用视图解析器,为我们(用户)呈现一个视图,当然,此时的视图是没有数据的。
控制器实例化CategoryService
对象(具体包括:通过Mybatis
在数据库中请求数据,接着通过Spring
的反转控制和依赖注入Category
,实例化对象"CategoryMapper
",然后通过CategoryServiceImpl
的list方法
,获取CategoryMapper
中的数据,最后通过上转型方式,真正实现实例化CategoryService
),该对象的list
方法,其实也就是CategoryServiceImpl
的list
方法,会获取到多个Category
对象,通过mav
的addObject
方法,成为可以被jsp页面调用的数据。至此,用户视图就有了数据。
当阳光更炽烈,黑暗也更加阴冷。我们在使用SSM来开发项目时,可以利用spring框架下很多已经写好的东西,比如说spring中依赖注入和反转控制,我们就不必自己new了,再比如说mybatis中的sql语句配置文件化,提高通用性和可重用性,又比如说springmvc的视图解析器,我们就不需要自己去实现http接口去重定向了。这很大程度上提高了我们的开发效率,但是当我们过度框架化时,我们就会被局限在框架之中,比如说spring的声明式事务管理,我们只能用spring为我们准备好的那一套事务处理的方式,而不能在ssm框架下实现对特殊业务场景的满足。
显然,我们开发新技术,使用新框架不是为了走极端,而是在寻求“中庸之道”,或许ssm是这个中庸之道的“立足点”。
常见的Spring注解:
注解名 | 作用 |
---|---|
@Autowired | 自动装配依赖对象,即自动将需要的对象注入到类中 |
@Resource | JavaEE的注解,不是Spring的注解,但是Spring也支持@Resource注解。它的作用和@Autowired类似,也是用来注入依赖对象的 |
@Component | 将类标记为Spring组件,告诉Spring框架将这个类纳入到Spring容器中管理 |
@Aspect | 定义切面,即声明一组横切关注点和它们的逻辑关系,用来描述在什么时候、在哪里应用哪些通知(Advice) |
@Around | 定义环绕通知,即在方法执行前后都执行一些逻辑 |
@Before | 定义前置通知,即在方法执行前执行一些逻辑 |
@After | 定义后置通知,即在方法执行后执行一些逻辑 |
@ContextConfiguration | 指定Spring应用程序的配置文件或Java配置类,用来配置Spring容器 |
@Service | 将类标记为Spring服务类 |
@Repository | 将类标记为Spring数据访问对象 |
@Scope | 控制Spring容器如何管理Bean的实例化、销毁和缓存 |
@Value | 注入属性值,即将配置文件中的值注入到Bean的属性中 |
SpringMVC常见的注解有两个:@Controller和@RequestMapping,下面举一个简单的例子对两者进行解释和示范:
@Controller注解用于标识一个类是SpringMVC的控制器,处理客户端请求并返回响应结果。通常,控制器类中的方法使用@RequestMapping注解来指定处理的请求URL和请求方法类型。
例如,下面的代码片段展示了一个使用@Controller注解的示例:
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public ModelAndView getUserById(@PathVariable("id") Long id) {
User user = userService.getUserById(id);
ModelAndView modelAndView = new ModelAndView("user");
modelAndView.addObject("user", user);
return modelAndView;
}
// other methods...
}
在上面的示例中,UserController类使用@Controller注解标识为SpringMVC的控制器,并使用@RequestMapping注解指定了处理的请求URL为"/user/{id}",请求方法类型为GET。getUserById方法用于处理该请求,并返回一个包含用户信息的ModelAndView对象。
Mybatis的注解方式是一种使用注解来替代Mapper
XML文件的方式,通过在Java代码中添加注解来定义SQL语句和Java对象之间的映射关系。
Mybatis的一般方式则是通过Mapper
XML文件来定义SQL语句和Java对象之间的映射关系。
下面分别对这两种方式进行详细解释,并且举例说明:
使用注解方式,需要在Mapper接口的方法上添加对应的注解(使用注解方式则不用为Mapper接口写一个xml兄弟文件来定义SQL语句了),如@Select、@Insert、@Update、@Delete等,同时在注解中定义SQL语句和Java对象之间的映射关系。下面是一个使用注解方式的示例:
public interface UserMapper {
@Select("SELECT id, name, age FROM user WHERE id = #{id}")
User getUserById(int id);
}
通过以上代码,我们可以定义一个getUserById方法,使用@Select注解来定义查询语句,并且将查询结果映射成User对象。在使用时,可以直接调用该方法来执行查询操作,如下所示:
// 获取Mapper对象
UserMapper mapper = session.getMapper(UserMapper.class);
// 执行查询操作
User user = mapper.getUserById(1);
// 输出查询结果
System.out.println(user.getId() + ", " + user.getName() + ", " + user.getAge());
使用一般方式,需要在Mapper XML文件中定义SQL语句和Java对象之间的映射关系,然后在Java代码中通过SqlSession对象来执行SQL语句。下面是一个使用一般方式的示例:
UserMapper.xml文件:
<select id="getUserById" resultType="com.example.User">
SELECT id, name, age FROM user WHERE id = #{id}
select>
UserMapper接口:
public interface UserMapper {
User getUserById(int id);
}
在使用时,需要先加载UserMapper.xml文件,并且获取Mapper对象,然后通过该对象来执行查询操作,如下所示:
// 加载UserMapper.xml文件
InputStream inputStream = Resources.getResourceAsStream("UserMapper.xml");
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 创建SqlSession对象
SqlSession session = sessionFactory.openSession();
// 获取Mapper对象
UserMapper mapper = session.getMapper(UserMapper.class);
// 执行查询操作
User user = mapper.getUserById(1);
// 输出查询结果
System.out.println(user.getId() + ", " + user.getName() + ", " + user.getAge());
// 关闭SqlSession对象
session.close();
下面是Mybatis注解方式和一般方式的优劣对比:
优劣:注解方式相对于一般方式来说,开发效率更高,因为注解方式不需要编写Mapper XML文件,可以直接在Java代码中使用注解来定义SQL语句和Java对象之间的映射关系,从而减少了编写和维护Mapper XML文件的工作量。
优劣:一般方式相对于注解方式来说,可读性和可维护性更高,因为Mapper XML文件可以更加清晰地定义SQL语句和Java对象之间的映射关系,方便开发人员进行阅读和修改。而注解方式将SQL语句和Java对象之间的映射关系直接写在Java代码中,可能会导致代码比较冗长,可读性和可维护性较差。
优劣:一般方式相对于注解方式来说,更适合处理复杂的SQL语句,因为Mapper XML文件可以更加灵活地定义SQL语句和Java对象之间的映射关系,支持动态SQL、多表联查等复杂操作。而注解方式则相对简单,不太适合处理复杂的SQL语句。
优劣:注解方式相对于一般方式来说,性能更高,因为注解方式不需要解析Mapper XML文件,可以直接在Java代码中执行SQL语句,从而提高了执行效率。而一般方式需要解析Mapper XML文件,并且使用XML解析器来解析SQL语句,可能会导致性能略微降低。
综上所述,Mybatis注解方式和一般方式各有优劣,需要根据具体的情况来选择合适的方式。如果需要提高开发效率和简化代码结构,可以选择注解方式;如果需要提高可读性和可维护性,以及处理复杂的SQL语句,可以选择一般方式。
值得一提的是:如果Spring框架的设计目标之一是实现松耦合的组件之间的依赖关系,那么我们在SSM框架中通常更多使用的是一般方式。
本次练习基于已经成功整合SSM。
package com.how2java.test;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.how2java.mapper.CategoryMapper;
import com.how2java.pojo.Category;
import com.how2java.util.Page;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class MybatisTest {
@Autowired
private CategoryMapper categoryMapper;
// 测试添加分类
@Test
public void testAdd() {
for (int i = 0; i < 100; i++) {
Category category = new Category();
category.setId(i);
category.setName(" Category"+i);
categoryMapper.add(category);
}
}
}
<insert id="add" parameterType="Category" >
insert into category_ (id, name ) values (#{id},#{name})
insert>
在程序编写框的空白处Run as
——>JUnit Test
修改那两份代码是为了使我们在表中添加的数据的id的标号是升序的。
我们的分页是通过超链接
(更具体来说,是参数传递)和sql语句的limit
关键字来实现的。实现分页,我们必须关心两件事:
①我们的分页的一个页面,即当前页面,是从那一条数据开始的。
②我们当前页需要展示几条数据。
着两个数据恰好就是limit
的两个参数,第一个参数由每一次进行上一页
、下一页
等换页操作实时传递,第二个参数由我们在分页的实体类中规定。
以下一页
为例进行流程分析:
web.xml
的前端拦截器捕获,交由springMVC.xml
控制,进而调用控制器"CategoryController.java",控制器通过Spring
和上转型注入CategoryServicelistCategory
的方法,并向其传递一个对象型参数Page
,Page的属性start被参数传递的start覆盖,值为’5’list(page)
,这个方法会在其函数体的内部调用categoryMapper
的list(page)
方法,此后会执行id为list的sql语句:
<select id="list" resultType="Category">
select * from category_
<if test="start!=null and count!=null">
limit #{start},#{count}
if>
select>
limit
关键字有两个参数,第一个参数定位了查询的起点,第二参数限定了查询几个,在这里我们查询的起点是5,向后查询5个(不包括起点),返回category结果,在CategoryMapper的对象中形成一个Category对象列表,作为函数返回值return给CategoryService我们的crud本质上,也是一种向用户提供的服务,或者说用户的需求。因此为了实现CRUD:
按钮
,以供用户点击接口
,以实现接口最终实现功能DAO
(CategoryMapper),以实现与数据库的交互。控制器
,处理用户不同的/更多的请求在jsp界面增加超链接,以向浏览器发送请求U和D的请求,相关代码片段如下:
<td><a href="editCategory?id=${c.id}">编辑a>td>
<td><a href="myDeleteTest?id=${c.id}">删除a>td>
<div style="text-align:center;margin-top:40px">
<form method="post" action="addCategory">
分类id:<input name="id" value="" type="text"> <br><br>
分类名称: <input name="name" value="" type="text"> <br>
<input type="submit" value="增加分类">
form>
div>
完整的listCategory代码如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="java.util.*"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<div style="width:500px;margin:0px auto;text-align:center">
<table align='center' border='1' cellspacing='0'>
<tr>
<td>idtd>
<td>nametd>
<td>编辑td>
<td>删除td>
tr>
<c:forEach items="${cs}" var="c" varStatus="st">
<tr>
<td>${c.id}td>
<td>${c.name}td>
<td><a href="editCategory?id=${c.id}">编辑a>td>
<td><a href="myDeleteTest?id=${c.id}">删除a>td>
tr>
c:forEach>
table>
<div style="text-align:center">
<a href="?start=0">首 页a>
<a href="?start=${page.start-page.count}">上一页a>
<a href="?start=${page.start+page.count}">下一页a>
<a href="?start=${page.last}">末 页a>
div>
<div style="text-align:center;margin-top:40px">
<form method="post" action="addCategory">
分类id:<input name="id" value="" type="text"> <br><br>
分类名称: <input name="name" value="" type="text"> <br>
<input type="submit" value="增加分类">
form>
div>
div>
void add(Category c);
void update(Category c);
void delete(Category c);
完整的代码如下:
package com.how2java.service;
import java.util.List;
import com.how2java.pojo.Category;
import com.how2java.util.Page;
public interface CategoryService {
List<Category> list();
int total();
List<Category> list(Page page);
void add(Category c);
void update(Category c);
void delete(Category c);
Category get(int id);
}
@Override
public void add(Category c) {
categoryMapper.add(c);
}
@Override
public void update(Category c) {
categoryMapper.update(c);
}
@Override
public void delete(Category c) {
categoryMapper.delete(c.getId());
}
完整代码如下:
package com.how2java.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.how2java.mapper.CategoryMapper;
import com.how2java.pojo.Category;
import com.how2java.service.CategoryService;
import com.how2java.util.Page;
@Service
public class CategoryServiceImpl implements CategoryService{
@Autowired
CategoryMapper categoryMapper;
public List<Category> list(){
return categoryMapper.list();
}
@Override
public List<Category> list(Page page) {
// TODO Auto-generated method stub
return categoryMapper.list(page);
}
@Override
public int total() {
return categoryMapper.total();
}
@Override
public void add(Category c) {
categoryMapper.add(c);
}
@Override
public void update(Category c) {
categoryMapper.update(c);
}
@Override
public void delete(Category c) {
categoryMapper.delete(c.getId());
}
@Override
public Category get(int id) {
// TODO Auto-generated method stub
return categoryMapper.get(id);
};
}
在CategoryMapper.java中添加add、delete、update方法用于支持CUD,原有的list方法支持分页(即为R,分页只是改变了数据的呈现形式)
完整代码如下:
package com.how2java.mapper;
import java.util.List;
import com.how2java.pojo.Category;
import com.how2java.util.Page;
public interface CategoryMapper {
// 添加分类
public int add(Category category);
// 删除分类
public void delete(int id);
// 根据id获取分类
public Category get(int id);
// 更新分类
public int update(Category category);
// 获取所有分类列表
public List<Category> list();
// 分页获取分类列表
public List<Category> list(Page page);
// 获取分类总数
public int total();
}
category.xml:
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.how2java.mapper.CategoryMapper">
<insert id="add" parameterType="Category" >
insert into category_ (id, name ) values (#{id},#{name})
insert>
<delete id="delete" parameterType="Category" >
delete from category_ where id= #{id}
delete>
<select id="get" parameterType="_int" resultType="Category">
select * from category_ where id= #{id}
select>
<update id="update" parameterType="Category" >
update category_ set name=#{name} where id=#{id}
update>
<select id="list" resultType="Category">
select * from category_
<if test="start!=null and count!=null">
limit #{start},#{count}
if>
select>
<select id="total" resultType="int">
select count(*) from category_
select>
mapper>
在CategoryController.java中增加如下代码:
// 处理添加分类的请求
@RequestMapping("addCategory")
public ModelAndView addCategory(Category category){
categoryService.add(category);
ModelAndView mav = new ModelAndView("redirect:/listCategory");
return mav;
}
// 处理删除分类的请求
@RequestMapping("myDeleteTest")
public ModelAndView deleteCategory(Category category){
categoryService.delete(category);
ModelAndView mav = new ModelAndView("redirect:/listCategory");
return mav;
}
// 处理编辑分类的请求
@RequestMapping("editCategory")
public ModelAndView editCategory(Category category){
Category c= categoryService.get(category.getId());
ModelAndView mav = new ModelAndView("editCategory");
mav.addObject("c", c);
return mav;
}
// 处理更新分类的请求
@RequestMapping("updateCategory")
public ModelAndView updateCategory(Category category){
categoryService.update(category);
ModelAndView mav = new ModelAndView("redirect:/listCategory");
return mav;
}
完整代码如下:
// 引入需要的类
package com.how2java.controller;
import java.util.Collections;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import com.how2java.pojo.Category;
import com.how2java.service.CategoryService;
import com.how2java.util.Page;
// 定义一个Spring MVC控制器类
@Controller
@RequestMapping("")
public class CategoryController {
@Autowired
CategoryService categoryService;
// 处理请求,返回模型和视图对象
@RequestMapping("listCategory")
public ModelAndView listCategory(Page page){
ModelAndView mav = new ModelAndView();
List<Category> cs= categoryService.list(page);
int total = categoryService.total();
page.caculateLast(total);
// 添加参数
mav.addObject("cs", cs);
// 设置视图名称
mav.setViewName("listCategory");
return mav;
}
// 处理添加分类的请求
@RequestMapping("addCategory")
public ModelAndView addCategory(Category category){
categoryService.add(category);
ModelAndView mav = new ModelAndView("redirect:/listCategory");
return mav;
}
// 处理删除分类的请求
@RequestMapping("myDeleteTest")
public ModelAndView deleteCategory(Category category){
categoryService.delete(category);
ModelAndView mav = new ModelAndView("redirect:/listCategory");
return mav;
}
// 处理编辑分类的请求
@RequestMapping("editCategory")
public ModelAndView editCategory(Category category){
Category c= categoryService.get(category.getId());
ModelAndView mav = new ModelAndView("editCategory");
mav.addObject("c", c);
return mav;
}
// 处理更新分类的请求
@RequestMapping("updateCategory")
public ModelAndView updateCategory(Category category){
categoryService.update(category);
ModelAndView mav = new ModelAndView("redirect:/listCategory");
return mav;
}
}
File
—>New
—>Other
—>Maven Project
—>Next
X2,到达如下图所示界面,选择最后一个选项,webapp
设置当前Maven工程的三维坐标:
Group Id:
Artifact Id:
Version:
修改Properties
,调整至使用计算机的默认jdk(1.8),如图所示
按照how2j将文件导入对应文件夹后,修改pom.xml,使它为我们管理项目所依赖的jar包,代码如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>com.how2javagroupId>
<artifactId>ssmartifactId>
<version>0.0.1-SNAPSHOTversion>
<packaging>warpackaging>
<properties>
<spring.version>4.1.3.RELEASEspring.version>
<pagehelper.version>5.1.2-betapagehelper.version>
<mysql.version>5.1.6mysql.version>
<mybatis.spring.version>1.2.3mybatis.spring.version>
<mybatis.version>3.1.1mybatis.version>
<junit.version>4.12junit.version>
<jstl.version>1.2jstl.version>
<jsqlparser.version>1.0jsqlparser.version>
<jackson.version>1.2.7jackson.version>
<servlet-api.version>3.1.0servlet-api.version>
<druid.version>1.0.18druid.version>
<log4j.version>1.2.16log4j.version>
<commons-logging.version>1.2commons-logging.version>
<commons-fileupload.version>1.2.1commons-fileupload.version>
<commons-io.version>1.3.2commons-io.version>
<commons-lang.version>2.6commons-lang.version>
<aopalliance.version>1.0aopalliance.version>
<mybatis-generator.version>1.3.5mybatis-generator.version>
properties>
<dependencies>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>${junit.version}version>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>${mybatis.version}version>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatis-springartifactId>
<version>${mybatis.spring.version}version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>${mysql.version}version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
<version>${druid.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-testartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-beansartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-jdbcartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-aspectsartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>jstlgroupId>
<artifactId>jstlartifactId>
<version>${jstl.version}version>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
<version>${servlet-api.version}version>
<scope>providedscope>
dependency>
<dependency>
<groupId>com.github.pagehelpergroupId>
<artifactId>pagehelperartifactId>
<version>${pagehelper.version}version>
dependency>
<dependency>
<groupId>com.github.jsqlparsergroupId>
<artifactId>jsqlparserartifactId>
<version>${jsqlparser.version}version>
dependency>
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>${log4j.version}version>
dependency>
<dependency>
<groupId>commons-logginggroupId>
<artifactId>commons-loggingartifactId>
<version>${commons-logging.version}version>
dependency>
<dependency>
<groupId>commons-fileuploadgroupId>
<artifactId>commons-fileuploadartifactId>
<version>${commons-fileupload.version}version>
dependency>
<dependency>
<groupId>commons-iogroupId>
<artifactId>commons-ioartifactId>
<version>${commons-io.version}version>
dependency>
<dependency>
<groupId>commons-langgroupId>
<artifactId>commons-langartifactId>
<version>${commons-lang.version}version>
dependency>
<dependency>
<groupId>aopalliancegroupId>
<artifactId>aopallianceartifactId>
<version>${aopalliance.version}version>
dependency>
<dependency>
<groupId>org.mybatis.generatorgroupId>
<artifactId>mybatis-generator-coreartifactId>
<version>${mybatis-generator.version}version>
dependency>
dependencies>
<build>
<finalName>${project.artifactId}finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-resources-pluginartifactId>
<version>2.7version>
<configuration>
<encoding>UTF-8encoding>
configuration>
plugin>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-compiler-pluginartifactId>
<version>3.2version>
<configuration>
<source>1.8source>
<target>1.8target>
<encoding>UTF-8encoding>
configuration>
plugin>
plugins>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.tomcat.mavengroupId>
<artifactId>tomcat7-maven-pluginartifactId>
<version>2.2version>
plugin>
plugins>
pluginManagement>
<resource>
<directory>src/main/resourcesdirectory>
<includes>
<include>**/*.propertiesinclude>
<include>**/*.xmlinclude>
<include>**/*.tldinclude>
includes>
<filtering>falsefiltering>
resource>
<resource>
<directory>src/main/javadirectory>
<includes>
<include>**/*.propertiesinclude>
<include>**/*.xmlinclude>
includes>
<filtering>falsefiltering>
resource>
build>
project>
说一句,我怎么知道我的项目需要哪些依赖,需要什么版本。。。