一、配置数据库信息
1. 新建数据库与表
在数据库服务器中新建数据库和表。
2. 配置 jdbc 信息
在 src/main/resources 新建 jdbc.properties 文件,并配置数据库信息:
jdbc.username=rootjdbc.password=rootjdbc.url=jdbc:mysql://localhost:3306/nl_crowd_fundingjdbc.driver=com.mysql.jdbc.Driver
3. 配置数据源
在 src/main/resources 新建 applicationContext.xml 文件,并配置数据源:
<!-- 加载 jdbc 配置文件 --><context:property-placeholder location="classpath:jdbc.properties"/><!-- 配置数据源 --><bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource"><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/><property name="url" value="${jdbc.url}"/><property name="driverClassName" value="${jdbc.driver}"/></bean>
这里需要在 pom.xml 引入 mysql-connector-java 、 druid / c3p0 依赖:
<!-- MySQL 驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>${mysql.jdbc.version}</version></dependency><!-- 数据源 --><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>${druid.version}</version></dependency>
4. 测试 Spring 能否获取数据库连接
在 src/test/java 下新建 com.nigream.crowfunding.test.TestDataSource.java 类:
@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations = { "classpath:applicationContext.xml" })public class TestDataSource {@Autowiredprivate DataSource dataSource;@Testpublic void testConn() throws SQLException {Connection connection = dataSource.getConnection();System.out.println(connection);}}
这里需要引入如下依赖:
JUnit: 用于单元测试。spring-test: 用于整合Spring与JUnit,使用@RunWith与@ContextConfiguration注解。spring-beans: 使用@Autowired注解。spring-context: 使用@ContextConfiguration需要spring-context的支持;。
<!-- 测试工具 ========================================================== --><!-- junit 测试(引入 hamcrest-core、junit ) --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>${junit.version}</version><scope>test</scope></dependency><!-- spring-test(引入 core 与 test ) --><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>${spring.version}</version><scope>test</scope></dependency><!-- Spring 框架 ========================================================== --><!-- spring-beans(引入 beans、core ) --><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>${spring.version}</version></dependency><!-- spring-context(引入 context、beans、expression、core 与 aop ) --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency>
若输出没问题,即可进入下一步。
二、整合 MyBatis
1. MyBatis 逆向工程
注意:建议另建 Maven 项目执行逆向工程,避免因操作失误覆盖掉重要文件。逆向工程可以生成
实体类、*Example.java、*Mapper.java、*mapper.xml文件。
在 src/main/resources 下,新建 generator-config.xml 文件,进行如下配置:
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE generatorConfigurationPUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN""http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"><generatorConfiguration><properties resource="jdbc.properties" /><!-- mybatis-generator:generate --><context id="DBTables" targetRuntime="MyBatis3"><commentGenerator><!-- 是否去除自动生成的注释 true:是;false:否 --><property name="suppressAllComments" value="true" /></commentGenerator><!--数据库连接的信息:驱动类、连接地址、用户名、密码 --><jdbcConnection driverClass="${jdbc.driver}"connectionURL="${jdbc.url}" userId="${jdbc.username}"password="${jdbc.password}"></jdbcConnection><!-- 默认 false,把 JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true 时把 JDBC DECIMAL和 NUMERIC 类型解析为 java.math.BigDecimal --><javaTypeResolver><property name="forceBigDecimals" value="false" /></javaTypeResolver><!-- targetProject:生成 Entity 类的路径 --><javaModelGenerator targetProject=".\src\main\java"targetPackage="com.nigream.crowdfunding.entity"><!-- enableSubPackages:是否让 schema 作为包的后缀 --><property name="enableSubPackages" value="false" /><!-- 从数据库返回的值被清理前后的空格 --><property name="trimStrings" value="true" /></javaModelGenerator><!-- targetProject:XxxMapper.xml 映射文件生成的路径 --><sqlMapGenerator targetProject=".\src\main\resources"targetPackage="mybatis/mapper"><!-- enableSubPackages:是否让 schema 作为包的后缀 --><property name="enableSubPackages" value="false" /></sqlMapGenerator><!-- targetPackage:Mapper 接口生成的位置 --><javaClientGenerator type="XMLMAPPER"targetProject=".\src\main\java"targetPackage="com.nigream.crowdfunding.mapper"><!-- enableSubPackages:是否让 schema 作为包的后缀 --><property name="enableSubPackages" value="false" /></javaClientGenerator><!-- 数据库表名字和我们的 entity 类对应的映射指定 --><table tableName="t_admin" domainObjectName="Admin" /></context></generatorConfiguration>
1.1 方法一
在 pom.xml 中引入如下依赖与配置:
<dependencies><!-- 持久层相关 --><!-- Mybatis --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>${mybatis.version}</version></dependency></dependencies><build><plugins><plugin><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-maven-plugin</artifactId><version>${mybatis-generator.version}</version><dependencies><!-- jdbc --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>${mysql.version}</version></dependency><!-- 数据库连接池 --><dependency><groupId>com.mchange</groupId><artifactId>c3p0</artifactId><version>${c3p0.version}</version></dependency><!-- 逆向工程 --><dependency><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-core</artifactId><version>${mybatis-generator.version}</version></dependency></dependencies></plugin></plugins></build>
右击 pom.xml ,点击 Run as 下的 Maven Build... ,在 Goals 中输入 mybatis-generator:generate ,点击 Run 即可生成相应文件,将生成的文件移回原项目即可。
1.2 方法二
将 generator-config.xml 移动到 项目根目录 下,通过如下代码来生成文件:
public class MBGTest {public static void main(String[] args) throws Exception {// TODO Auto-generated method stubList<String> warnings = new ArrayList<String>();boolean overwrite = true;File configFile = new File("generator-config.xml");ConfigurationParser cp = new ConfigurationParser(warnings);Configuration config = cp.parseConfiguration(configFile);DefaultShellCallback callback = new DefaultShellCallback(overwrite);MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);myBatisGenerator.generate(null);}}
但要在这样引入依赖:
<dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>${mybatis.version}</version></dependency><!-- jdbc --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>${mysql.version}</version></dependency><dependency><groupId>com.mchange</groupId><artifactId>c3p0</artifactId><version>${c3p0.version}</version></dependency><!-- 逆向工程 --><dependency><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-core</artifactId><version>${mybatis-generator.version}</version></dependency>
2. 配置 applicationContext.xml
按如下要求准备好所需文件:
src/main/java下的com.nigream.crowdfunding.mapper: 放操作数据库的接口类。src/main/java下的com.nigream.crowdfunding.entity: 放实体类。src/main/resources下的mybatis/mapper: 放mapper配置文件,以Mapper.xml结尾。src/main/resources下 : 放mybatis-config.xml,这里可以先不写内容。
在 applicationContext.xml 中加入如下配置:
<!-- 配置SqlSessionFactoryBean用于Spring与MyBatis整合 --><bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactoryBean"><property name="configLocation" value="classpath:mybatis-config.xml"/><property name="mapperLocations" value="classpath:mybatis/mapper/*Mapper.xml"/><property name="dataSource" ref="dataSource"/></bean><!-- 配置MapperScannerConfigurer扫描Mapper接口所在的包 --><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer" id="mapperScannerConfigurer"><property name="basePackage" value="com.nigream.crowdfunding.mapper"/></bean>
这里需要引入如下依赖:
MyBatismybatis-spring: MyBatis 与 Spring 整合,使用 SqlSessionFactoryBean 读取 MyBatis 配置文件和 mapper 文件。spring-jdbc: 整合 MyBatis 时需要,没有的话,下面的测试会报错。
<!-- MyBatis --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>${mybatis.version}</version></dependency><!-- MyBatis 与 Spring 整合 --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>${mybatis-spring.version}</version></dependency><!-- spring-jdbc(引入 beans、core 与 tx 与 jdbc ) --><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>${spring.version}</version></dependency>
3. 测试 Mybatis 是否整合成功
在 TestDataSource.java 中,添加如下代码并执行,若数据库成功保存代码,即可视为 Mybatis 整合成功。
@Autowiredprivate AdminMapper adminMapper;@Testpublic void testInsert() throws SQLException {Admin admin = new Admin(null, "jerry", "123456", "杰瑞", "jerry@gmail.com", null);adminMapper.insertSelective(admin);}
三、两种日志系统
有两种常用配置:
1. 使用 log4j
引入以下依赖:
<!-- slf4j:日志系统的接口 --><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId></dependency><!-- log4j --><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-core</artifactId></dependency><!-- log4j的适配器 --><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId></dependency>
在 src/main/resources 下新建 log4j.properties 进行配置:
# Set root category priority to INFO and its only appender to CONSOLE.#log4j.rootCategory=INFO, CONSOLE debug info warn error fatal# 包消息级别log4j.rootCategory=debug, CONSOLE, LOGFILE# Set the enterprise logger category to FATAL and its only appender to CONSOLE.log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE# CONSOLE is set to be a ConsoleAppender using a PatternLayout.log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppenderlog4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayoutlog4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n# LOGFILE is set to be a File appender using a PatternLayout.log4j.appender.LOGFILE=org.apache.log4j.FileAppenderlog4j.appender.LOGFILE.File=src/main/resources/log.txtlog4j.appender.LOGFILE.Append=truelog4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayoutlog4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n# 输出消息编码 GB2312log4j.appender.LOGFILE.encoding=UTF-8
2. 使用 logBack
2.1 排除 commons-logging
注意:不排除也可以用,嫌麻烦可以不进行这步。
首先引入如下依赖:
<!-- spring-core(引入 core,core 依赖于 commons-logging ) --><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>${spring.version}</version><exclusions><exclusion><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId></exclusion></exclusions></dependency>
因为这里直接依赖了 spring-core ,根据依赖传递的 就近优先原则 ,其他 jar包 依赖的 spring-core 都不会传入,所以只要 spring-core 本身排除了commons-logging 依赖,就不会再有其他包传入该依赖。
2.2 使用 jcl
引入如下依赖:
<!-- slf4j --><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>${slf4j.version}</version></dependency><!-- slf4j 的实现 --><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>${logback.version}</version></dependency><!-- jcl 替换掉 Spring 自带的 commons-logging --><dependency><groupId>org.slf4j</groupId><artifactId>jcl-over-slf4j</artifactId><version>${jcl.version}</version></dependency>
在 src/main/resources 下新建 logback.xml 进行配置:
<?xml version="1.0" encoding="UTF-8"?><configuration debug="true"><!-- 指定日志输出的位置 --><appender name="STDOUT"class="ch.qos.logback.core.ConsoleAppender"><encoder><!-- 日志输出的格式 --><!-- 按照顺序分别是:时间、日志级别、线程名称、打印日志的类、日志主体 内容、换行 --><pattern>[%d{HH:mm:ss.SSS}] [%-5level] [%thread] [%logger] [%msg]%n</pattern></encoder></appender><!-- 设置全局日志级别。日志级别按顺序分别是:DEBUG、INFO、WARN、ERROR --><!-- 指定任何一个日志级别都只打印当前级别和后面级别的日志。 --><root level="DEBUG"><!-- 指定打印日志的 appender,这里通过“STDOUT”引用了前面配置的 appender --><appender-ref ref="STDOUT" /></root><!-- 根据特殊需求指定局部日志级别 --><logger name="com.nigream.crowdfunding.dao" level="DEBUG" /></configuration>
四、声明式事务
1. 配置
引入以下依赖:
<!-- 业务层 ========================================================== --><!-- spring-aop(引入 beans、core 与 aop ) --><dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId></dependency><!-- aspectjweaver:负责切点织入 spring-aop需要依赖此包 --><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId></dependency><!-- spring-tx:事务控制(引入 beans、core 与 tx ) --><dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId></dependency>
在 applicationContext.xml 中加入如下内容:
<!-- 配置自动扫描的包:为了将Service扫描到IOC容器中 --><context:component-scan base-package="com.nigream.crowdfunding.service"/><!-- 配置事务管理器 --><bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager" ><!-- 装配数据源:只要spring-persist-mybatis.xml也加载了,就能使用这个数据源 --><property name="dataSource" ref="dataSource"/></bean><tx:advice transaction-manager="transactionManager" id="txAdvice"><tx:attributes><!-- 查询方法:配置只读属性,让数据库知道这是一个查询操作,能进行一定优化。 --><tx:method name="find*" read-only="true" propagation="SUPPORTS"/><!-- 增删改方法:配置事务传播行为、回滚异常 --><!--propagation属性:REQUIRED:默认值,表示当前方法必须工作在事务中,如果当前线程上没有已经开启的事务,则自己开新事务;如果已有事务,就使用这个已有事务。(别的方法回滚他也会回滚)REQUIRED_NEW:不管当前线程上有没有已经开启的事务,都要自己开事务,在自己新开的事务中运行。(不受其他事务回滚的影响)--><!--rollback-fors属性:配置事务方法针对什么样的异常回滚默认:运行时异常回滚建议:编译时异常和运行时异常都回滚--><tx:method name="save*" propagation="REQUIRED" rollback-for="java.lang.Exception"/><tx:method name="update*" propagation="REQUIRED" rollback-for="java.lang.Exception"/><tx:method name="remove*" propagation="REQUIRED" rollback-for="java.lang.Exception"/><tx:method name="batch*" propagation="REQUIRED" rollback-for="java.lang.Exception"/><tx:method name="*"/></tx:attributes></tx:advice><aop:config><!-- 定位到以ServiceImpl结尾的类中的方法 --><aop:pointcut expression="execution(* *..*ServiceImpl.*(..))" id="txPointCut"/><aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/></aop:config>
2. 测试
在 src/main/java 的 com.nigream.crowdfunding.service.api 下新建并编辑 AdminService.java :
public interface AdminService {void saveOne(Admin admin);}
在 src/main/java 的 com.nigream.crowdfunding.service.impl 下新建并编辑 AdminServiceImpl.java :
@Servicepublic class AdminServiceImpl implements AdminService {@AutowiredAdminMapper adminMapper;@Overridepublic void saveOne(Admin admin) {adminMapper.insertSelective(admin);}}
在 TestDataSource.java 中加入如下代码:
@Autowiredprivate AdminService adminService;@Testpublic void testSave() {Admin admin = new Admin(null, "tom", "123456", "汤姆", "tom@gmail.com", null);adminService.saveOne(admin);}
若成功保存数据,则可进入下一步。
五、整合 Spring MVC
1. web.xml
引入依赖:
<!-- controller 层 ========================================================== --><!-- spring-webmvc(引入 context、beans、expression、core 与 aop、web、webmvc ) --><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>${spring.version}</version></dependency>
在 web.xml 中加入:
<!-- needed for ContextLoaderListener --><context-param><param-name>contextConfigLocation</param-name><param-value>classpath:applicationContext.xml</param-value></context-param><!-- Bootstraps the root web application context before servlet initialization --><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><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><init-param><!-- 强制响应和请求设置字符集 --><param-name>forceEncoding</param-name><param-value>true</param-value></init-param></filter><filter-mapping><!-- 在所有Filter前执行,所以要放在所有Filter前 --><!-- 因为 request.setCharacterEncoding(encoding);必须要在request.getParameter()前面执行;response.setCharacterEncoding(encoding);必须要在response.getWriter()前面执行; --><filter-name>characterEncodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping><!-- The front controller of this Spring Web application, responsible for handling all application requests --><servlet><servlet-name>springDispatcherServlet</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:springmvc.xml</param-value></init-param><!-- Servlet默认生命周期中,创建对象是在第一次接收到请求时 --><!-- DispatcherServlet创建对象后有大量的“框架初始化”工作,不适合在第一次请求时来做 --><!-- 设置load-on-startup就是为了让DispatcherServlet在Web应用启动时创建对象、初始化 --><load-on-startup>1</load-on-startup></servlet><!-- Map all requests to the DispatcherServlet for handling --><servlet-mapping><servlet-name>springDispatcherServlet</servlet-name><url-pattern>/</url-pattern></servlet-mapping><!-- psot 转换成 delete 或 put --><filter><filter-name>hiddenHttpMethodFilter</filter-name><filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class></filter><filter-mapping><filter-name>hiddenHttpMethodFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping><!-- 使put请求可以封装数据 --><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>
2. springmvc.xml
在 src/main/resources 下新建 springmvc.xml 文件:
<!-- 配置自动扫描的包 --><context:component-scan base-package="com.nigream.crowdfunding.controller"/><!-- 配置SpringMVC的注解驱动 --><mvc:annotation-driven/><!-- 处理静态资源 --><mvc:default-servlet-handler /><!-- 配置视图解析器 --><!-- 将jsp文件放在WEB-INF目录下保护起来 --><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="viewResolver"><property name="prefix" value="/WEB-INF/views/"/><property name="suffix" value=".jsp"/></bean>
3. 测试(以 .jsp 为例)
引入如下依赖:
<!-- 引入 Servlet 容器中相关依赖 --><dependency><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId><version>${servlet.version}</version><scope>provided</scope></dependency><!-- JSP 页面使用的依赖 --><dependency><groupId>javax.servlet.jsp</groupId><artifactId>jsp-api</artifactId><version>${jsp.version}</version><scope>provided</scope></dependency>
在 /webapp 目录下新建 index.jsp :
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%><!DOCTYPE html><html><head><meta charset="UTF-8"><title>Insert title here</title></head><body><a href="${pageContext.request.contextPath}/findAll">测试</a></body></html>
为了避免每次写链接都要带上 ${pageContext.request.contextPath} ,可以改成如下代码:
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%><!DOCTYPE html><html><head><meta charset="UTF-8"><title>Insert title here</title><basehref="http://${pageContext.request.serverName }:${pageContext.request.serverPort }${pageContext.request.contextPath }/"/><!-- 这里必须加上/,否则拼接不上 --></head><body><!-- 这里必须加上/,否则不会引用 <base/>里的内容 --><a href="/findAll">测试</a></body></html>
在 /webapp/WEB-INF/views 目录下新建 target.jsp :
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%><!DOCTYPE html><html><head><meta charset="UTF-8"><title>Insert title here</title></head><body><h1>Success</h1>${requestScope.adminList}</body></html>
在 AdminService 和 AdminServiceImpl 的类中添加 findAll 方法。
在 com.nigream.crowdfunding.controller 下新建 TestController.java :
@Controllerpublic class TestController {@Autowiredprivate AdminService adminService;@RequestMapping("/findAll")public String testSSM(ModelMap modelMap) {modelMap.addAttribute("adminList",adminService.findAll());return "target";}}
访问 http://localhost:8080/findAll ,若无异常,则测试通过。
六、 Ajax
1. 准备
在 src/main/webapp 下放入 jQuery 文件,在前端页面引入 jQuery
JSON 数据转换需要 jackson 的支持:
<!-- JSON 数据转换 --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>${jackson.version}</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>${jackson.version}</version></dependency>
2. 数组传输(方法一)
js 代码
$.ajax({"url": "array/one", // 请求目标资源的地址"type": "post", // 请求方式"data": { // 要发送的请求参数"array": [5,8,12]},"dataType": "text", // 如何对待服务器端返回的数据"success": function(response) { // 服务器端成功处理请求后调用的回调函数,response是响应体数据alert(response);},"error":function(response) { // 服务器端处理请求失败后调用的回调函数,response是响应体数据alert(response);}});
java 代码
@RequestMapping("array/one")@ResponseBody// 前端 JQuery 传 array 时,会使他变成 array[] ,后端用 @RequestParam("array[]") 可接收public String testArrayOne(@RequestParam("array[]") int[] array) {for (int i = 0; i < array.length; i++) {System.out.println(array[i]);}return "Success";}
3. 数组传输(方法二)
js 代码
$.ajax({"url": "array/two", // 请求目标资源的地址"type": "post", // 请求方式"data": { // 要发送的请求参数"array[0]": 5,"array[1]": 8,"array[2]": 12},"dataType": "text", // 如何对待服务器端返回的数据"success": function(response) { // 服务器端成功处理请求后调用的回调函数,response是响应体数据alert(response);},"error":function(response) { // 服务器端处理请求失败后调用的回调函数,response是响应体数据alert(response);}});
java 代码
@RequestMapping("array/two")@ResponseBodypublic String testArrayTwo(ParamData paramData) {List<Integer> array = paramData.getArray();for (int i = 0; i < array.size(); i++) {System.out.println(array.get(i));}return "Success";}
public class ParamData {private List<Integer> array;public ParamData() {super();}public ParamData(List<Integer> array) {super();this.array = array;}public List<Integer> getArray() {return array;}public void setArray(List<Integer> array) {this.array = array;}@Overridepublic String toString() {return "ParamData [array=" + array + "]";}}
4. 数组传输(方法三)
// 准备好要发送到服务器端的数组var array = [5, 8, 12];console.log(array.length);// 将JSON数组转换为JSON字符串var requestBody = JSON.stringify(array);// "['5','8','12']"console.log(requestBody.length);$.ajax({"url": "array/three", // 请求目标资源的地址"type": "post", // 请求方式"data": requestBody, // 请求体"contentType": "application/json;charset=UTF-8", // 设置请求体的内容类型,告诉服务器端本次请求的请求体是JSON数据"dataType": "text", // 如何对待服务器端返回的数据"success": function(response) { // 服务器端成功处理请求后调用的回调函数,response是响应体数据alert(response);},"error":function(response) { // 服务器端处理请求失败后调用的回调函数,response是响应体数据alert(response);}});
java 代码
@RequestMapping("array/three")@ResponseBodypublic String testArrayThree(@RequestBody List<Integer> array) {for (int i = 0; i < array.size(); i++) {System.out.println(array.get(i));}return "Success";}
5. 传输复杂对象(统一返回的对象)
js 代码
// 准备要发送的数据var student = {"stuId": 5,"stuName":"tom","address": {"province": "广东","city": "深圳","street":"后瑞"},"subjectList": [{"subjectName": "JavaSE","subjectScore": 100},{"subjectName": "SSM","subjectScore": 99}],"map": {"k1":"v1","k2":"v2"}};// 将JSON对象转换为JSON字符串var requestBody = JSON.stringify(student);// 发送Ajax请求$.ajax({"url":"compose/object.json","type":"post","data":requestBody,"contentType":"application/json;charset=UTF-8","dataType":"json","success":function(response){console.log(response);},"error":function(response){console.log(response);}});
java 代码
/*** 统一整个项目中Ajax请求返回的结果(未来也可以用于分布式架构各个模块间调用时返回统一类型)*/public class ResultEntity<T> {public static final String SUCCESS = "SUCCESS";public static final String FAILED = "FAILED";// 用来封装当前请求处理的结果是成功还是失败private String result;// 请求处理失败时返回的错误消息private String message;// 要返回的数据private T data;/*** 请求处理成功且不需要返回数据时使用的工具方法* @return*/public static <Type> ResultEntity<Type> successWithoutData() {return new ResultEntity<Type>(SUCCESS, null, null);}/*** 请求处理成功且需要返回数据时使用的工具方法* @param data 要返回的数据* @return*/public static <Type> ResultEntity<Type> successWithData(Type data) {return new ResultEntity<Type>(SUCCESS, null, data);}/*** 请求处理失败后使用的工具方法* @param message 失败的错误消息* @return*/public static <Type> ResultEntity<Type> failed(String message) {return new ResultEntity<Type>(FAILED, message, null);}public ResultEntity() {}public ResultEntity(String result, String message, T data) {super();this.result = result;this.message = message;this.data = data;}@Overridepublic String toString() {return "ResultEntity [result=" + result + ", message=" + message + ", data=" + data + "]";}public String getResult() {return result;}public void setResult(String result) {this.result = result;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public T getData() {return data;}public void setData(T data) {this.data = data;}}
@RequestMapping("compose/object")@ResponseBodypublic ResultEntity<Student> testReceiveComposeObject(@RequestBody Student student, HttpServletRequest request) {// 将“查询”到的Student对象封装到ResultEntity中返回ResultEntity<Student> resultEntity = ResultEntity.successWithData(student);return resultEntity;}
七、异常映射
1. 异常映射机制
两种请求:
两种处理方式:
注:springmvc.xml 中的 <mvc:view-controller path="/xxx/xxx" view-name-name="target"/> 配置,可以直接设置请求访问的视图。
2. 基于 XML 的异常映射
在 springmvc.xml 中插入如下配置,当出现异常,则会跳转到 system-error 页面:
<!-- 配置基于XML的异常映射 --><bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver" id="simpleMappingExceptionResolver"><!-- 配置异常类型和具体视图页面的对应关系 --><property name="exceptionMappings"><props><!-- key属性指定异常全类名 --><!-- 标签体中写对应的视图(这个值会拼前后缀得到具体路径) --><prop key="java.lang.Exception">system-error</prop></props></property></bean>
3. 判断请求类型
java 代码,在从 controller 方法中调用如下 judgeRequestType() 方法即可知道请求类型:
public class CrowdUtil {/*** 判断当前请求是否为Ajax请求* @param request 请求对象* @return* true:当前请求是Ajax请求* false:当前请求不是Ajax请求*/public static boolean judgeRequestType(HttpServletRequest request) {// 1.获取请求消息头String acceptHeader = request.getHeader("Accept");String xRequestHeader = request.getHeader("X-Requested-With");// 2.判断return (acceptHeader != null && acceptHeader.contains("application/json"))||(xRequestHeader != null && xRequestHeader.equals("XMLHttpRequest"));}}
4. 基于注解的异常映射
// @ControllerAdvice表示当前类是一个基于注解的异常处理器类@ControllerAdvicepublic class CrowdExceptionResolver {@ExceptionHandler(value = ArithmeticException.class)public ModelAndView resolveMathException(ArithmeticException exception,HttpServletRequest request,HttpServletResponse response) throws IOException {String viewName = "system-error";return commonResolve(viewName, exception, request, response);}@ExceptionHandler(value = NullPointerException.class)public ModelAndView resolveNullPointerException(NullPointerException exception,HttpServletRequest request,HttpServletResponse response) throws IOException {String viewName = "system-error";return commonResolve(viewName, exception, request, response);}// @ExceptionHandler将一个具体的异常类型和一个方法关联起来private ModelAndView commonResolve(// 异常处理完成后要去的页面String viewName,// 实际捕获到的异常类型Exception exception,// 当前请求对象HttpServletRequest request,// 当前响应对象HttpServletResponse response) throws IOException {// 1.判断当前请求类型boolean judgeResult = CrowdUtil.judgeRequestType(request);// 2.如果是Ajax请求if(judgeResult) {// 3.创建ResultEntity对象ResultEntity<Object> resultEntity = ResultEntity.failed(exception.getMessage());// 4.创建Gson对象Gson gson = new Gson();// 5.将ResultEntity对象转换为JSON字符串String json = gson.toJson(resultEntity);// 6.将JSON字符串作为响应体返回给浏览器response.getWriter().write(json);// 7.由于上面已经通过原生的response对象返回了响应,所以不提供ModelAndView对象return null;}// 8.如果不是Ajax请求则创建ModelAndView对象ModelAndView modelAndView = new ModelAndView();// 9.将Exception对象存入模型modelAndView.addObject("exception", exception);// 10.设置对应的视图名称modelAndView.setViewName(viewName);// 11.返回modelAndView对象return modelAndView;}}
