基于SSM架构的CRM系统(一):spring+springmvc+mybatis集成 : https://blog.csdn.net/qq_33526760/article/details/94441168
一.ssm搭建
1.1拷贝原来的ssme项目,改名为crm
并且在tomcat的server.xml里配置项目![](https://img-blog.csdnimg.cn/2019070622454590.png)
新建数据库crm及数据库表
修改包名cn.xxx.ssme为cn.xxx.crm
jdbc.properties:数据库名
applicationContext.xml里扫描的包,配置文件.......
1.2写查询所有部门代码
代码流程: domain-->建数据库表-->*Mapper.java-->*Mapper.xml-->service的接口和实现-->junit测试service-->controller
1.2.1 domain:
User相关的全部删掉
package cn.xxx.crm.domain;
public class Department {
private Long id;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Department() {}
public Department(Long id, String name) {
super();
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "Department [id=" + id + ", name=" + name + "]";
}
}
1.2.2 数据库表:![](https://img-blog.csdnimg.cn/20190706214754532.png)
![](https://img-blog.csdnimg.cn/20190706214714908.png)
1.2.3 DepartmentMapper.java:
package cn.xxx.crm.mapper;
import java.util.List;
import cn.xxx.crm.domain.Department;
public interface DepartmentMapper {
//查询所有部门
List<Department> loadAll();
}
注意:为什么mapper里的查询方法用load,因为按照语义,load是加载,更倾向于持久层方法,业务层的方法一般用get,query,find,以后方法命名要注意,接口DepartmentMapper不用我们自己实现,所以前面没有加i
1.2.4 DepartmentMapper.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="cn.xxx.crm.mapper.DepartmentMapper">
<select id="loadAll" resultType="cn.xxx.crm.domain.Department">
select id,name from t_department
</select>
</mapper>
1.2.5 service的接口和实现:
package cn.xxx.crm.service;
import java.util.List;
import cn.xxx.crm.domain.Department;
public interface IDepartmentService {
//查询所有部门
List<Department> getAll();
}
package cn.xxx.crm.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import cn.xxx.crm.domain.Department;
import cn.xxx.crm.mapper.DepartmentMapper;
import cn.xxx.crm.service.IDepartmentService;
@Service
public class DepartmentServiceImpl implements IDepartmentService{
@Autowired
private DepartmentMapper departmentMapper;
@Override
public List<Department> getAll() {
List<Department> list = departmentMapper.loadAll();
return list;
}
}
1.2.6 junit测试service:
测试结果:
1.2.7 controller
启动项目,访问:
注意:由于每一个domain都对应一个service,那么,就要写多个测试类来对service进行测试,那么我们可以抽取一个公共的测试类,每个domain测测试类继承它就可以了,主要是抽取@RunWith和@ContextConfiguration:
1.3 项目改进
要改进成方案2,把他们的启动分开来管理,更加模块化
扫描包
扫描Conroller
扫描Mapper
扫描Service
注意:为什么分开启动之后,applicationContext.xml里直接扫描cn.xxx.crm,但是扫描不出controller,而要在applicationContext-mvc.xml里面扫描controller?因为第一种方式是通过dispatcherServlet启动的时候加载applicationContext.xml,所以能扫描controller,而优化成第二种方式之后,dispatcherServlet启动的时候只加载applicationContext-mvc.xml,所以并没有包的扫描,所以要加上
启动服务器,访问:
1.4 抽取BaseMapper&BaseService
base抽取架构图:
由于crm系统有很多domain,比如部门,员工,客户......,那么每个domain都要进行CRUD,那么就可以抽一个公共的接口
BaseMapper:
package cn.xxx.crm.mapper;
import java.io.Serializable;
import java.util.List;
/**
* 基础的Mapper里实现了基本的CRUD,其他Mapper可以通过继承它就拥有crud
* 为什么 id要用Serializable?因为有的domain的id是Long,有的domain的id又是Integer
*/
public interface BaseMapper<T> {
//通过id加载一个对象
T loadById(Serializable id);
//加载所有对象
List<T> loadAll();
//插入一个对象
void save(T t);
//根据id删除对象
void remove(Serializable id);
//根据id修改对象
void update(T t);
}
DepartmentMapper.java:
DepartmentMapper.xml:(这里面的id类型就不用Serializeble了)
<?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="cn.xxx.crm.mapper.DepartmentMapper">
<!-- //通过id加载一个对象
T (Serializable id); -->
<select id="loadById" parameterType="long" resultType="cn.xxx.crm.domain.Department">
select id,name from t_department where id=#{id}
</select>
<!-- //加载所有对象
List<T> loadAll(); -->
<select id="loadAll" resultType="cn.xxx.crm.domain.Department">
select id,name from t_department
</select>
<!-- //插入一个对象
void save(T t); -->
<insert id="save" parameterType="cn.xxx.crm.domain.Department">
insert into t_department(name) values(#{name})
</insert>
<!-- //根据id删除对象
void remove(Serializable id); -->
<delete id="remove" parameterType="long">
delete from t_department where id=#{id}
</delete>
<!-- //根据id修改对象
void update(T t); -->
<update id="update" parameterType="cn.xxx.crm.domain.Department">
update t_department set name = #{name} where id=#{id}
</update>
</mapper>
(注意:①为什么mapper里的查询方法用load,因为按照语义,load是加载,更倾向于持久层方法,业务层的方法一般用get,query,find
②抽取的接口BaseMapper不用我们自己实现,所以前面没有加i
)
IBaseService:
package cn.xxx.crm.service;
import java.io.Serializable;
import java.util.List;
public interface IBaseService<T> {
//通过id加载一个对象
T getById(Serializable id);
//加载所有对象
List<T> getAll();
//插入一个对象
void add(T t);
//根据id删除对象
void delete(Serializable id);
//根据id修改对象
void update(T t);
}
BaseServiceImpl:
package cn.xxx.crm.service.impl;
import java.io.Serializable;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import cn.xxx.crm.mapper.BaseMapper;
import cn.xxx.crm.service.IBaseService;
public class BaseServiceImpl<T> implements IBaseService<T> {
/*虽然注入的是BaseMapper,但是DepartmentServiceImpl继承BaseServiceImpl,IDepartmentService继承IBaseService之后,
* 注入的是DepartmentMapper
*/
@Autowired
private BaseMapper<T> baseMapper;
@Override
public T getById(Serializable id) {
T t = baseMapper.loadById(id);
return t;
}
@Override
public List<T> getAll() {
List<T> all = baseMapper.loadAll();
return all;
}
@Override
public void add(T t) {
baseMapper.save(t);
}
@Override
public void delete(Serializable id) {
baseMapper.remove(id);
}
@Override
public void update(T t) {
baseMapper.update(t);
}
}
DepartmentServiceImpl
package cn.xxx.crm.service;
import cn.xxx.crm.domain.Department;
public interface IDepartmentService extends IBaseService<Department>{
}
DepartmentServiceImpl
package cn.xxx.crm.service.impl;
import org.springframework.stereotype.Service;
import cn.xxx.crm.domain.Department;
import cn.xxx.crm.service.IDepartmentService;
@Service
public class DepartmentServiceImpl extends BaseServiceImpl<Department> implements IDepartmentService{
}
生成测试类测试(查看前面生成方法):
package cn.xxx.crm.service;
import static org.junit.Assert.*;
import java.util.List;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import cn.xxx.crm.domain.Department;
public class IDepartmentServiceTest extends BaseServiceTest{
@Autowired
private IDepartmentService departmentService;
@Test
public void testGetById() {
Department department = departmentService.getById(2L);
System.out.println(department);
}
@Test
public void testGetAll() {
List<Department> all = departmentService.getAll();
for (Department department : all) {
System.out.println(department);
}
}
@Test
public void testAdd() {
for (int i = 0; i < 20; i++) {
departmentService.add(new Department("test"+i));
}
// departmentService.add(new Department("test"+100));
}
@Test
public void testDelete() {
Department department = departmentService.getById(3L);
System.out.println(department);
departmentService.delete(3L);
department = departmentService.getById(3L);
System.out.println(department);
}
@Test
public void testUpdate() {
Department department = departmentService.getById(4L);
System.out.println(department);
department.setName(department.getName()+"->你被修改了!");
departmentService.update(department);
department = departmentService.getById(4L);
System.out.println(department);
}
}
1.5 事务处理
Spirng事务处理有两种方式:
声明式事务(XML)
注解式事务(注解)
spring的事务管理器是DataSourceTransactionManager
applicationContext.xml写tx标签的时候,alt+/没有提示,那么要配置约束:
配置了之后需要有网络,如果没有网络,那么要手动引入:
选择
Key就是我们复制的内容粘贴进去
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
">
<!-- 使用注解要进行扫描 -->
<context:component-scan base-package="cn.xxx.crm" />
<context:property-placeholder location="classpath:jdbc.properties" />
<!-- jdbc.properties->dataSource->sqlSessionFactory->mapper(dao)->service->controller(action) -->
<!-- 数据源dataSource -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<!-- 依赖注入连接池需要的属性 -->
<!-- property name="是BasicDataSource的set方法,本质属性" -->
<!-- property value="是jdbc.properties配置文件的key" -->
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<!--maxActive: 最大连接数量 -->
<property name="maxActive" value="150" />
<!--minIdle: 最小空闲连接 -->
<property name="minIdle" value="5" />
<!--maxIdle: 最大空闲连接 -->
<property name="maxIdle" value="20" />
<!--initialSize: 初始化连接 -->
<property name="initialSize" value="30" />
<!-- 连接被泄露时是否打印 -->
<property name="logAbandoned" value="true" />
<!--removeAbandoned: 是否自动回收超时连接 -->
<property name="removeAbandoned" value="true" />
<!--removeAbandonedTimeout: 超时时间(以秒数为单位) -->
<property name="removeAbandonedTimeout" value="10" />
<!--maxWait: 超时等待时间以毫秒为单位 1000等于60秒 -->
<property name="maxWait" value="1000" />
<!-- 在空闲连接回收器线程运行期间休眠的时间值,以毫秒为单位. -->
<property name="timeBetweenEvictionRunsMillis" value="10000" />
<!-- 在每次空闲连接回收器线程(如果有)运行时检查的连接数量 -->
<property name="numTestsPerEvictionRun" value="10" />
<!-- 1000 * 60 * 30 连接在池中保持空闲而不被空闲连接回收器线程 -->
<property name="minEvictableIdleTimeMillis" value="10000" />
<property name="validationQuery" value="SELECT NOW() FROM DUAL" />
</bean>
<
<!-- SSJ集成时候需要entityManagerFactory SSM集成时候需要sqlSessionFactory 集成jpa的时候需要一个EntityManagerFactory对象
-> 需要一个FactoryBean来完成功能 需要用到SqlSessionFactoryBean -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 引用datasource -->
<property name="dataSource" ref="dataSource" />
<!-- 读取核心配置文件 -->
<property name="mapperLocations" value="classpath:cn/xxx/crm/mapper/*Mapper.xml" />
<!-- 配置别名 -->
<!-- 配置mybatis 类型别名 -->
<!-- <property name="typeAliasesPackage"> -->
<!-- <value> -->
<!-- cn.itsource.ssm.domain -->
<!-- cn.itsource.ssm.query -->
<!-- </value> -->
<!-- </property> -->
</bean>
<!-- MapperFactoryBean:对应到我们的Mapper -->
<!-- 引用sqlSessoinFactory -->
<!-- 指向对应的接口 -->
<!-- 一劳永逸(不要有id) -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="cn.xxx.crm.mapper" />
</bean>
<!-- 事务处理:
1.配置一个事务管理器
2.开启注解事务支持
3.类里面加注解 -->
<!-- 1.配置一个事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 2.开启注解事务支持 -->
<tx:annotation-driven/>
<!-- 引入 mvc的配置 -->
<!-- <import resource="classpath:plugins/applicationContext-mvc.xml" /> -->
</beans>
事务处理第三步: 类里面加注解
package cn.xxx.crm.service.impl;
import java.io.Serializable;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import cn.xxx.crm.mapper.BaseMapper;
import cn.xxx.crm.service.IBaseService;
//由于查询比较多,所以在类上配置默认的查询事务,对应里面的增删改,单独配置写事务
@Transactional(propagation=Propagation.SUPPORTS,readOnly=true)
public class BaseServiceImpl<T> implements IBaseService<T> {
/*虽然注入的是BaseMapper,但是DepartmentServiceImpl继承BaseServiceImpl,IDepartmentService继承IBaseService之后,
* 注入的是DepartmentMapper
*/
@Autowired
private BaseMapper<T> baseMapper;
@Override
public T getById(Serializable id) {
T t = baseMapper.loadById(id);
return t;
}
@Override
public List<T> getAll() {
List<T> all = baseMapper.loadAll();
return all;
}
@Override
@Transactional(propagation=Propagation.REQUIRED,readOnly=false)
public void add(T t) {
baseMapper.save(t);
}
@Override
@Transactional//和上面@Transactional(propagation=Propagation.REQUIRED,readOnly=false)是一样,因为propagation=Propagation.REQUIRED,readOnly=false都是默认值
public void delete(Serializable id) {
baseMapper.remove(id);
}
@Override
@Transactional
public void update(T t) {
baseMapper.update(t);
}
}
SUPPORTS:有事务就用,没有就算求. readOnly=true:只读事务,用于查询
REQUIRED:必须要有事务.
@Transactional默认就是@Transactional(propagation=Propagation.REQUIRED,readOnly=false)
@Transactional等价于@Transactional(propagation=Propagation.REQUIRED,readOnly=false)
测试事务:
二. 集成easyui
解压,改名去掉版本号(因为版本以后可能升级)
2.1目录规划
把easyui放到新建路径webapp/resources/js下面,因为easyui里面包含了jquery.min.js,jquery也是前端框架,为了区分我们把jquery.min.js拖出来放到webapp/resources/js下面
2.2抽取公共的common.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!-- easyui的主题样式 -->
<!-- <link rel="stylesheet" type="text/css" href="easyui/themes/default/easyui.css"> -->
<!-- 变相对为绝对路径 -->
<!-- <link rel="stylesheet" type="text/css" href="/resources/js/easyui/themes/default/easyui.css"> -->
<!-- 路径应该加上APPPATH -->
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/resources/js/easyui/themes/default/easyui.css">
<!-- easyui的主题图标 -->
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/resources/js/easyui/themes/icon.css">
<!-- easyui的主题颜色-->
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/resources/js/easyui/themes/color.css">
<!-- easyui的依赖的jQuery-->
<script type="text/javascript" src="${pageContext.request.contextPath}/resources/js/jquery.min.js"></script>
<!-- easyui的所有插件 -->
<script type="text/javascript" src="${pageContext.request.contextPath}/resources/js/easyui/jquery.easyui.min.js"></script>
<!-- easyui的国际化 -->
<script type="text/javascript" src="${pageContext.request.contextPath}/resources/js/easyui/locale/easyui-lang-zh_CN.js"></script>
Common.jsp里面引入了easyUI,我们的界面直接导入Common.jsp就相当于引入easyUI:
注意,common.jsp里面的路径一定要根据项目写,路径不对会找不到,如下图:
三.CRUD
页面:
直接从easyui的demo里面copy页面代码:
接下来修改页面代码:
步骤:刷新功能-->删除功能-->保存和编辑功能
注意:1.copy的代码,按钮都是a标签,里面用onClick()绑定的事件,太low了,要把事件去掉,在js里面绑定
2.前端进行表单提交的时候,接口方法打上@Responsebody返回的不是json对象,而是json字符串,要使用json对象要进行转换,ajax请求的时候,才是返回的json对象,直接使用,如下代码中注释有说明 list.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<%@include file="/WEB-INF/views/common.jsp"%>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>部门管理</title>
</head>
<body>
<!-- 管理表格 -->
<table id="deptDatagrid" title="部门管理" class="easyui-datagrid"
style="width: 700px; height: 250px" url="/department/list"
toolbar="#deptToolbar" pagination="true" rownumbers="true" fit="true"
fitColumns="true" singleSelect="true">
<thead>
<tr>
<th field="name" width="50">部门名称</th>
</tr>
</thead>
</table>
<!-- 管理表格toolbar -->
<div id="deptToolbar">
<a id='saveDeptBtn' class="easyui-linkbutton c1" iconCls="icon-add"
plain="true">新增</a> <a id='editDeptBtn' class="easyui-linkbutton c3"
iconCls="icon-edit" plain="true">编辑</a> <a id='deleteDeptBtn'
class="easyui-linkbutton c5" iconCls="icon-remove" plain="true">删除</a>
<a id='reloadDeptBtn' class="easyui-linkbutton c7"
iconCls="icon-remove" plain="true">刷新</a>
</div>
<!-- 添加和修改对话框 -->
<div id=saveOrUpdateDeptDlg class="easyui-dialog" style="width: 400px"
data-options="closed:true,modal:true,border:'thin',buttons:'#dlg-buttons'">
<form id="fm" method="post" novalidate
style="margin: 0; padding: 20px 50px">
<div style="margin-bottom: 10px">
<input name="id" type="hidden" /> <input name="name"
class="easyui-textbox" required="true" label="部门名称:"
style="width: 100%" />
</div>
</form>
</div>
<!-- 添加和修改对话框按钮 -->
<div id="dlg-buttons">
<a id="confirmSaveOrUpdateBtn" class="easyui-linkbutton c6"
iconCls="icon-ok" style="width: 90px">保存</a> <a
id="cancelSaveOrUpdateBtn" class="easyui-linkbutton c8"
iconCls="icon-cancel" style="width: 90px">取消</a>
</div>
<script type="text/javascript">
var url;
$('#saveDeptBtn').click(function(){
//清空模态框里字段的内容
$('#fm').form('clear');
//打开
$('#saveOrUpdateDeptDlg').dialog('open').dialog('center').dialog('setTitle','新增');
// url = 'save_user.php';?
});
$('#editDeptBtn').click(function(){
//清空模态框里字段的内容
$('#fm').form('clear');
//对编辑的数据进行回显
var row = $('#deptDatagrid').datagrid('getSelected');
if (row){
$('#saveOrUpdateDeptDlg').dialog('open').dialog('center').dialog('setTitle','编辑');
$('#fm').form('load',row);
// url = 'update_user.php?id='+row.id;
}else{
$.messager.alert('提示','请选择一条数据!','info');
}
});
$('#deleteDeptBtn').click(function(){
var row = $('#deptDatagrid').datagrid('getSelected');
// console.log(row);
if (row){
$.messager.confirm('Confirm','确定要删除这条记录吗?',function(r){
if (r){
$.post('/department/delete',{id:row.id},function(result){
if (result.success){
$.messager.alert('提示',result.message,'info');
$('#deptDatagrid').datagrid('reload'); // reload the user data
} else {
$.messager.alert('错误',result.message,'error');
$('#deptDatagrid').datagrid('reload');
}
},'json');
}
});
}else{
$.messager.alert('提示','请选择一条数据!','info');
}
});
$('#reloadDeptBtn').click(function(){
$('#deptDatagrid').datagrid('reload');
});
$('#confirmSaveOrUpdateBtn').click(function(){
$('#fm').form('submit',{
url : '/department/save',
success : function(data){
//应该返回一个AjaxResult转换的结果
//由于这儿是做表单提交,不是通过JQuery发送的Ajax请求,返回的是Json字符串需要转换为Json对象
// 1 eval 2 $.parseJSON 3....
data = $.parseJSON(data);
if(data.success){
$.messager.alert('提示',data.message,'info');
$('#deptDatagrid').datagrid('reload');
}else{
$.messager.alert('错误',data.message,'error');
$('#deptDatagrid').datagrid('reload');
}
}
});
$('#saveOrUpdateDeptDlg').dialog('close');
});
$('#cancelSaveOrUpdateBtn').click(function(){
$('#saveOrUpdateDeptDlg').dialog('close');
});
</script>
</body>
</html>
controller:
package cn.xxx.crm.controller;
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.bind.annotation.ResponseBody;
import cn.xxx.crm.domain.Department;
import cn.xxx.crm.service.IDepartmentService;
import cn.xxx.crm.util.AjaxResult;
@Controller
@RequestMapping("/department")
public class DepartmentController {
@Autowired
private IDepartmentService departmentService;
@RequestMapping("/index")
public String index(){
return "department/list";
}
@RequestMapping("/list")
@ResponseBody
public List<Department> list(){
List<Department> list = departmentService.getAll();
return list;
}
@RequestMapping("/delete")
@ResponseBody
public AjaxResult delete(Long id){
try {
departmentService.delete(id);
// int i=1/0;事务处理有问题,发生异常没有把删除操作进行回滚
return new AjaxResult();//成功就直接返回无参构造函数new的对象,不用设置参数,失败就通过有参构造函数构造对象,这种思想很重要
} catch (Exception e) {
e.printStackTrace();
//成功就直接返回无参构造函数new的对象,不用设置参数,失败就通过有参构造函数构造对象,这种思想很重要,并且把异常返回给前端
return new AjaxResult(false,"删除失败 : "+e.getMessage());
}
}
@RequestMapping("/save")
@ResponseBody
public AjaxResult save(Department department){
try {
Long id = department.getId();
if(id == null){
departmentService.add(department);
}else{
departmentService.update(department);
}
return new AjaxResult();
} catch (Exception e) {
e.printStackTrace();
return new AjaxResult(false,"保存失败 : "+e.getMessage());
}
}
}
package cn.xxx.crm.util;
public class AjaxResult {
private Boolean success=true;
private String message="操作成功!";
public Boolean getSuccess() {
return success;
}
public void setSuccess(Boolean success) {
this.success = success;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public AjaxResult() {}
public AjaxResult(Boolean success, String message) {
super();
this.success = success;
this.message = message;
}
}
注意:AjaxResult 成功就直接返回无参构造函数new的对象,不用设置参数,失败就通过有参构造函数构造对象,这种思想很重要!!
额外知识点:
(
返回json:
Struts2方案 response.getWriter().write("{\"success\":false,\"msg\":\""+e.getMessage()+"\"}");
SpringMVC方案 写一个类来描述这个json,导入只需把这个类的一个对象返回回去,加上@ResponseBody,由框架自动转换。
)
代码下载:https://download.csdn.net/download/qq_33526760/11348484