SSM整合 完美支持RESTful(Jsp和客户端<android ios...>)
一 RESTful简介
RESTful是一种网络应用程序的设计风格和开发方式 它结构清晰 符合标准 易于理解 扩展方便
REST 即Representational State Transfer的缩写 这个词组可以翻译成 表现层状态转化
通过URI定位资源(图片 文字 视频等等) 然后根据四个HTTP动词 对服务端资源进行操作 实现表现层状态转化
HTTP协议里面 四个表示操作方式的动词 GET POST PUT DELETE 分别对应四种基本操作 GET用来获取 POST用来新建 PUT用来更新 DELETE用来删除
二 三层架构简介
三层架构是为了符合高内聚 低耦合思想 把各个功能模块划分为表示层 业务层 持久层
开发者分工更明确 将精力更专注于应用核心业务逻辑的分析 设计和开发 加快项目的进度 提高了开发效率 有利于项目的更新和维护工作
表现层: 和客户端进行数据交互 表现层一般会采用MVC设计模型
业务层: 处理具体的业务逻辑
持久层: 操作数据库
三 MVC模型简介
Model View Controller 模型视图控制器
M: 数据模型(JavaBean) 用来进行数据封装
V: JSP HTML 用来展示数据给用户
C: 控制器 用来接收用户请求
四 SSM初体验
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <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.0</modelVersion> <groupId>com.hy.ssm</groupId> <artifactId>ssm-demo</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <!-- 定义依赖版本号 --> <properties> <junit.version>4.12</junit.version> <slf4j-log4j12.version>1.7.25</slf4j-log4j12.version> <javax.servlet-api.version>4.0.1</javax.servlet-api.version> <jsp-api.version>2.0</jsp-api.version> <jstl.version>1.2</jstl.version> <spring.version>5.0.5.RELEASE</spring.version> <jackson-databind.version>2.9.5</jackson-databind.version> <mysql-connector-java.version>8.0.11</mysql-connector-java.version> <druid.version>1.1.10</druid.version> <mybatis.version>3.4.6</mybatis.version> <mybatis-spring.version>1.3.2</mybatis-spring.version> <pagehelper.version>5.1.4</pagehelper.version> </properties> <!-- 管理jar版本号 --> <dependencyManagement> <dependencies> <!-- junit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> </dependency> <!-- slf4j --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>${slf4j-log4j12.version}</version> </dependency> <!-- servlet --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>${javax.servlet-api.version}</version> <scope>provided</scope> </dependency> <!-- jsp --> <dependency> <groupId>javax.servlet</groupId> <artifactId>jsp-api</artifactId> <version>${jsp-api.version}</version> <scope>provided</scope> </dependency> <!-- jstl --> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>${jstl.version}</version> </dependency> <!-- spring --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jms</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring.version}</version> </dependency> <!-- jackson(spring mvc need) --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>${jackson-databind.version}</version> </dependency> <!-- mysql --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql-connector-java.version}</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>${druid.version}</version> </dependency> <!-- mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>${mybatis.version}</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>${mybatis-spring.version}</version> </dependency> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>${pagehelper.version}</version> </dependency> </dependencies> </dependencyManagement> <dependencies> <!-- junit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> </dependency> <!-- slf4j --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </dependency> <!-- servlet --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <scope>provided</scope> </dependency> <!-- jsp --> <dependency> <groupId>javax.servlet</groupId> <artifactId>jsp-api</artifactId> <scope>provided</scope> </dependency> <!-- jstl --> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> </dependency> <!-- spring --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jms</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> </dependency> <!-- jackson(spring mvc need) --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> <!-- mysql --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> </dependency> <!-- mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> </dependency> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> </dependency> </dependencies> <build> <!-- 允许mybatis的mapper.java和mapper.xml在同一目录 --> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>false</filtering> </resource> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>false</filtering> </resource> </resources> <plugins> <!-- 编译 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.7.0</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> <!-- tomcat7 --> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> <configuration> <port>8081</port> <path>/</path> <uriEncoding>UTF-8</uriEncoding> </configuration> </plugin> </plugins> </build> </project>
sql
-- 用户表 CREATE TABLE user ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT '用户id', username VARCHAR(32) COMMENT '用户名', money DOUBLE COMMENT '用户余额' ); INSERT INTO user VALUES (1, '曹操', 8000); INSERT INTO user VALUES (2, '孙权', 8000); INSERT INTO user VALUES (3, '刘备', 8000); INSERT INTO user VALUES (4, '诸葛亮', 5000); INSERT INTO user VALUES (5, '司马懿', 5000); INSERT INTO user VALUES (6, '张飞', 0); INSERT INTO user VALUES (7, '关羽', 0); INSERT INTO user VALUES (8, '马超', 1000); INSERT INTO user VALUES (9, '黄忠', 1000); INSERT INTO user VALUES (10, '赵云', 3000);
2. 新建webapp文件夹及子文件夹和web.xml
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <!-- 指定Spring配置文件的位置 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:application*.xml</param-value> </context-param> <!-- 让Spring容器随项目的启动而创建 随项目的关闭而销毁 --> <!-- 容器创建时 会把所有单例对象都创建出来 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- Jsp支持RESTful --> <filter> <filter-name>hiddenHttpMethodFilter</filter-name> <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class> </filter> <filter-mapping> <filter-name>hiddenHttpMethodFilter</filter-name> <servlet-name>spring-mvc</servlet-name> </filter-mapping> <!-- 客户端(android ios...)支持RESTful --> <filter> <filter-name>httpPutFormContentFilter</filter-name> <filter-class>org.springframework.web.filter.HttpPutFormContentFilter</filter-class> </filter> <filter-mapping> <filter-name>httpPutFormContentFilter</filter-name> <!-- 拦截所有 --> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 处理POST提交乱码 --> <filter> <filter-name>characterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>characterEncodingFilter</filter-name> <!-- 拦截所有 --> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 前端控制器 --> <servlet> <servlet-name>spring-mvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:/spring-mvc.xml</param-value> </init-param> <!-- 配置SpringMVC启动时机 1. 第一次被访问时启动 值为负数 2. 随着容器启动而启动 值为0或正数 --> <load-on-startup>1</load-on-startup> <multipart-config> <!-- 文件上传大小(单位B) 5M = 5 * 1024 * 1024 --> <max-file-size>5242880</max-file-size> <!-- 文件上传请求大小(单位B) 10M = 10 * 1024 * 1024 --> <max-request-size>10485760</max-request-size> </multipart-config> </servlet> <servlet-mapping> <servlet-name>spring-mvc</servlet-name> <!-- 拦截所有(不包含jsp 包含js png css...) --> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
3. 创建jsp webapp/WEB-INF/jsp/index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <h3>事务</h3> ${user6.toString()}<br/> ${user7.toString()}<br/> <a href="${pageContext.request.contextPath}/test/tm">事务模拟操作</a> <h3>分页</h3> <a href="${pageContext.request.contextPath}/test/selectUserList">全部</a><br/> <a href="${pageContext.request.contextPath}/test/selectUserList/1/2">第一页 每页2条</a><br/> <a href="${pageContext.request.contextPath}/test/selectUserList/2/2">第二页 每页2条</a> <h3>RESTful</h3> <p>POST 普通表单</p> <form action="${pageContext.request.contextPath}/test/insert" method="post"> 姓名 <input type="text" name="name"/><br/> <input type="submit" value="提交"/> </form> <p>POST 文件表单</p> <form action="${pageContext.request.contextPath}/test/insertX" enctype="multipart/form-data" method="post"> 姓名 <input type="text" name="name"/><br/> 文件 <input type="file" name="file"/><br/> <input type="submit" value="提交"/> </form> <p>DELETE 普通表单</p> <form action="${pageContext.request.contextPath}/test/delete/1" method="post"> <input type="hidden" name="_method" value="DELETE"/> 姓名 <input type="text" name="name"/><br/> <input type="submit" value="提交"/> </form> <p>PUT 普通表单</p> <form action="${pageContext.request.contextPath}/test/update/1" method="post"> <input type="hidden" name="_method" value="PUT"/> 姓名 <input type="text" name="name"/><br/> <input type="submit" value="提交"/> </form> <p>PUT 文件表单</p> <form action="${pageContext.request.contextPath}/test/updateX/1" enctype="multipart/form-data" method="post"> <input type="hidden" name="_method" value="PUT"/> 姓名 <input type="text" name="name"/><br/> 文件 <input type="file" name="file"/><br/> <input type="submit" value="提交"/> </form> <p>GET 普通表单</p> <form action="${pageContext.request.contextPath}/test/select/1" method="get"> 姓名 <input type="text" name="name"/><br/> <input type="submit" value="提交"/> </form> </body> </html>
4. 配置日志输出 resources/log4j.properties
### 输出到控制台 ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.err
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### 输出到文件 ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=//Users/HUANGYI/Downloads/x-log.txt
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### 日志级别: fatal > error > warn > info > debug > trace ###
### 输出到哪里: stdout|file ###
#log4j.rootLogger=info, stdout
### 输出所有日志 ###
log4j.rootLogger=all, stdout
### 不输出日志 ###
#log4j.rootLogger=off, stdout
5. 配置数据源 resources/druid.properties
url=jdbc:mysql://localhost:3306/demo_hy?characterEncoding=utf8&useSSL=false driverClassName=com.mysql.cj.jdbc.Driver username=root password=root maxActive=10 minIdle=5
6. 创建spring配置文件 resources/application.xml 其中管理了mybatis 无需额外创建mybatis全局配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!-- 引入配置文件 --> <context:property-placeholder location="classpath:*.properties" /> <!-- 扫描Service --> <context:component-scan base-package="com.hy.ssm.service" /> <!-- 文件上传实现类 id名称必须固定 --> <bean id="multipartResolver" class="com.hy.ssm.resolver.PostAndPutMultipartResolver" /> <!-- 数据库连接池 --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close"> <property name="url" value="${url}" /> <property name="driverClassName" value="${driverClassName}" /> <property name="username" value="${username}" /> <property name="password" value="${password}" /> <property name="maxActive" value="${maxActive}" /> <property name="minIdle" value="${minIdle}" /> </bean> <!-- Mybatis会话工厂 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 数据源 --> <property name="dataSource" ref="dataSource" /> <!-- 别名 --> <property name="typeAliasesPackage" value="com.hy.ssm.model" /> <!-- 插件 --> <property name="plugins"> <array> <bean class="com.github.pagehelper.PageInterceptor"> <property name="properties"> <value> helperDialect=mysql </value> </property> </bean> </array> </property> </bean> <!-- Mybatis动态代理 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.hy.ssm.mapper" /> </bean> <!-- 事务核心管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <!-- 事务通知 --> <tx:advice id="advice" transaction-manager="transactionManager"> <tx:attributes> <!-- 以方法为单位 指定方法应用什么事务属性 isolation: 隔离级别 propagation: 传播行为 read-only: 是否只读 --> <tx:method name="insert*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" /> <tx:method name="delete*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" /> <tx:method name="update*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" /> <tx:method name="select*" isolation="DEFAULT" propagation="REQUIRED" read-only="true" /> </tx:attributes> </tx:advice> <!-- 事务织入 --> <aop:config> <!-- expression(表达式): 切点表达式 --> <!-- * com.hy.ssm.service..*.*(..) * = 任意返回值 com.hy.ssm.service. = com.hy.ssm.service包和所有子包 .*.* = .任意类.任意方法名 (..) = 任意参数 --> <aop:pointcut id="pointcut" expression="execution(* com.hy.ssm.service..*.*(..))" /> <aop:advisor pointcut-ref="pointcut" advice-ref="advice" /> </aop:config> </beans>
7. 创建springmvc配置文件 resources/spring-mvc.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd"> <!-- 扫描Controller --> <context:component-scan base-package="com.hy.ssm.controller" /> <!-- 注解驱动 --> <mvc:annotation-driven /> <!-- 视图解析器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- 逻辑视图前缀 --> <property name="prefix" value="/WEB-INF/jsp" /> <!-- 逻辑视图后缀 --> <property name="suffix" value=".jsp" /> </bean> <!-- 加载静态资源 --> <mvc:default-servlet-handler /> </beans>
8. 自定义文件上传实现类 com.hy.ssm.resolver.PostAndPutMultipartResolver 解决客户端(android ios...) PUT提交文件表单异常
public class PostAndPutMultipartResolver extends StandardServletMultipartResolver { @Override public boolean isMultipart(HttpServletRequest request) { if ("POST".equalsIgnoreCase(request.getMethod()) || "PUT".equalsIgnoreCase(request.getMethod())) { return StringUtils.startsWithIgnoreCase(request.getContentType(), "multipart/"); } return false; } }
9. 创建实体类 com.hy.ssm.model.User com.hy.ssm.model.PageWrapper
public class User implements Serializable { private Integer id; private String username; private Double money; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public Double getMoney() { return money; } public void setMoney(Double money) { this.money = money; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", money=" + money + '}'; } }
public class PageWrapper implements Serializable { private Long total; private List list; public PageWrapper() {} public PageWrapper(Long total, List list) { this.total = total; this.list = list; } public Long getTotal() { return total; } public void setTotal(Long total) { this.total = total; } public List getList() { return list; } public void setList(List list) { this.list = list; } }
10. 创建mapper接口 com.hy.ssm.mapper.UserMapper
public interface UserMapper { User selectUserById(Integer id); List<User> selectUserList(); Integer updateUserMoney(Map map); }
11. 创建mapper映射文件 com.hy.ssm.mapper.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.hy.ssm.mapper.UserMapper"> <select id="selectUserById" parameterType="Integer" resultType="User"> SELECT * FROM user WHERE id = #{value} </select> <select id="selectUserList" resultType="User"> SELECT * FROM user </select> <update id="updateUserMoney" parameterType="HashMap"> UPDATE user SET money = money + #{money} WHERE id = #{id} </update> </mapper>
12. 创建service接口 com.hy.ssm.service.IUserService
public interface IUserService { User selectUserById(Integer id); List<User> selectUserList(); PageWrapper selectUserList(Integer pageNum, Integer pageSize); Boolean updateUserMoney(Map map1, Map map2); }
13. 创建service实现类 com.hy.ssm.service.imp.UserService
@Service public class UserService implements IUserService { @Autowired private UserMapper userMapper; @Override public User selectUserById(Integer id) { return userMapper.selectUserById(id); } @Override public List<User> selectUserList() { return userMapper.selectUserList(); } @Override public PageWrapper selectUserList(Integer pageNum, Integer pageSize) { PageHelper.startPage(pageNum, pageSize); List<User> userList = userMapper.selectUserList(); PageInfo<User> pageInfo = new PageInfo<>(userList); return new PageWrapper(pageInfo.getTotal(), userList); } @Override public Boolean updateUserMoney(Map map1, Map map2) { Integer integer1 = userMapper.updateUserMoney(map1); int i = 3 / 0; //模拟异常 Integer integer2 = userMapper.updateUserMoney(map2); return 0 != integer1 && 0 != integer2; } }
14. 创建控制器 com.hy.ssm.controller.TestController
@Controller @RequestMapping("/test") public class TestController { @Autowired private IUserService userService; @RequestMapping("/index") public String index(Model model) { User user6 = userService.selectUserById(6); User user7 = userService.selectUserById(7); model.addAttribute("user6", user6); model.addAttribute("user7", user7); return "/index"; } @RequestMapping("/tm") public String tm() { Map<String, Object> map1 = new HashMap<>(); map1.put("id", 6); map1.put("money", -1000.0); Map<String, Object> map2 = new HashMap<>(); map2.put("id", 7); map2.put("money", +1000.0); userService.updateUserMoney(map1, map2); return "redirect:index"; } @RequestMapping("/selectUserList") @ResponseBody public List<User> selectUserList() { return userService.selectUserList(); } @GetMapping("/selectUserList/{page}/{size}") @ResponseBody public PageWrapper selectUserList(@PathVariable Integer page, @PathVariable Integer size) { return userService.selectUserList(page, size); } /** RESTful 只进行演示 没有做数据持久化 同时支持Jsp 客户端(android ios...) **/ @PostMapping("/insert") @ResponseBody public Map insert(String name) { Map<String, Object> map = new HashMap<>(); map.put("name", name); return map; } @PostMapping("/insertX") @ResponseBody public Map insertX(HttpServletRequest request, String name, MultipartFile file) throws Exception { Map<String, Object> map = new HashMap<>(); map.put("name", name); map.put("path", saveFile(request, file)); return map; } @DeleteMapping("/delete/{id}") @ResponseBody public Map delete(@PathVariable Integer id, String name) { Map<String, Object> map = new HashMap<>(); map.put("id", id); map.put("name", name); return map; } @PutMapping("/update/{id}") @ResponseBody public Map update(@PathVariable Integer id, String name) { Map<String, Object> map = new HashMap<>(); map.put("id", id); map.put("name", name); return map; } @PutMapping("/updateX/{id}") @ResponseBody public Map updateX(@PathVariable Integer id, HttpServletRequest request, String name, MultipartFile file) throws Exception { Map<String, Object> map = new HashMap<>(); map.put("id", id); map.put("name", name); map.put("path", saveFile(request, file)); return map; } @GetMapping("/select/{id}") @ResponseBody public Map select(@PathVariable Integer id, String name) { Map<String, Object> map = new HashMap<>(); map.put("id", id); map.put("name", name); return map; } private String saveFile(HttpServletRequest request, MultipartFile file) throws Exception { if (null != file && !file.isEmpty()) { String fileName = UUID.randomUUID().toString().replace("-", ""); //文件名 String originalFilename = file.getOriginalFilename(); String substring = originalFilename.substring(originalFilename.lastIndexOf(".")); String path = request.getServletContext().getRealPath("/upload") + "/" + fileName + substring; file.transferTo(new File(path)); return path; } return ""; } }
启动项目 访问 http://localhost:8081/test/index
android客户端核心代码
public interface Api { @POST("/test/insert") @FormUrlEncoded Call<ResponseBody> insert(@Field("name") String name); @POST("/test/insertX") @Multipart Call<ResponseBody> insertX(@Part MultipartBody.Part name, @Part MultipartBody.Part file); @DELETE("/test/delete/{id}") Call<ResponseBody> delete(@Path("id") Integer id, @Query("name") String name); @PUT("/test/update/{id}") @FormUrlEncoded Call<ResponseBody> update(@Path("id") Integer id, @Field("name") String name); @PUT("/test/updateX/{id}") @Multipart Call<ResponseBody> updateX(@Path("id") Integer id, @Part MultipartBody.Part name, @Part MultipartBody.Part file); @GET("/test/select/{id}") Call<ResponseBody> select(@Path("id") Integer id, @Query("name") String name); }
private void insert() { Call<ResponseBody> call = mApi.insert("祎哥哥"); call.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {} @Override public void onFailure(Call<ResponseBody> call, Throwable t) {} }); } private void insertX() { MultipartBody.Part name = MultipartBody.Part.createFormData("name", "祎哥哥"); RequestBody body = RequestBody.create(MediaType.parse("application/octet-stream"), card("text.txt")); MultipartBody.Part file = MultipartBody.Part.createFormData("file", "text.txt", body); Call<ResponseBody> call = mApi.insertX(name, file); call.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {} @Override public void onFailure(Call<ResponseBody> call, Throwable t) {} }); } private void delete() { Call<ResponseBody> call = mApi.delete(3, "黄祎"); call.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {} @Override public void onFailure(Call<ResponseBody> call, Throwable t) {} }); } private void update() { Call<ResponseBody> call = mApi.update(3, "黄祎"); call.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {} @Override public void onFailure(Call<ResponseBody> call, Throwable t) {} }); } private void updateX() { MultipartBody.Part name = MultipartBody.Part.createFormData("name", "黄祎"); RequestBody body = RequestBody.create(MediaType.parse("application/octet-stream"), card("text.txt")); MultipartBody.Part file = MultipartBody.Part.createFormData("file", "text.txt", body); Call<ResponseBody> call = mApi.updateX(3, name, file); call.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {} @Override public void onFailure(Call<ResponseBody> call, Throwable t) {} }); } private void select() { Call<ResponseBody> call = mApi.select(3, "黄祎"); call.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {} @Override public void onFailure(Call<ResponseBody> call, Throwable t) {} }); }
五 通过注解管理事务
初体验项目中是使用申明式事务管理 还可以使用注解式事务管理 2种事务管理方式都很常见 任选其中一种即可
1. 修改resources/application.xml 将下面配置拷贝进去 替换掉 事务通知 事务织入
<!-- 事务注解 --> <tx:annotation-driven />
2. 在com.hy.ssm.service.imp.UserService上添加注解
@Transactional(isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED, readOnly = false)