1、Dao层
1.1、创建BaseRepository
package com.vivi.xxl.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.NoRepositoryBean;
import java.io.Serializable;
//父类使用泛型,在配置扫描包的时候也会管理这个接口,@NoRepositoryBean注解就可以防止Spring管理实现
@NoRepositoryBean
public interface BaseRepository<T, ID extends Serializable> extends JpaRepository<T, ID>, JpaSpecificationExecutor<T> {
}
1.2、修改EmployeeRepsitory
注意:必需改成继承BaseRepsitory
public interface EmployeeRepository extends BaseRepository<Employee,Long> {}
2、service层
2.1、父接口IBaseService
这里除了基本的CRUD,还拓展了3个查询
package com.vivi.xxl.service;
public interface IBaseService<T,ID extends Serializable> {
//添加或者修改
void save(T t);
void delete(ID id);
T findOne(ID id);
List<T> findAll();
//1、根据查询对象进行查询
List<T> queryAll(BaseQuery query);
//2、根据查询对象拿到分页数据
Page<T> queryPage(BaseQuery query);
//3、根据JPQL进行查询
/**
* jpql:语句 select o from Employee where name = ? and age > ?
* params:参数(类型与数量不确定的)
*/
List<Object> queryByJpql(String jpql, Object... params);
}
2.2、子接口IEmployeeService
package com.vivi.xxl.service;
import com.vivi.xxl.domain.Employee;
/**
* 这里一句代码都没有,但是以后会有很多自己的
*/
public interface IEmployeeService extends IBaseService<Employee,Long> {
}
2.3、父实现BaseServiceImpl
package com.vivi.xxl.service.impl;
/**
* 父接口的实现 ,这个类就是一个父类,根本就不用它创建对象
*/
@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
public abstract class BaseServiceImpl<T, ID extends Serializable> implements IBaseService<T, ID> {
/*
* 这里自动注入的是BaseRepository的实现,但是BaseRepository已经被注解不在spring中实现
* 从而找他的子接口,子接口的实现有很多个,这里需要注意类型的关系
* BaseServiceImpl 这个父类,不会创建对象,这里类型不明确。
* 对象由继承的子类来创建,类型已经可以明确。
* */
@Autowired
private BaseRepository<T, ID> baseRepository;
@PersistenceContext
private EntityManager entityManager;
@Override
@Transactional
public void save(T t) {
baseRepository.save(t);
}
@Override
@Transactional
public void delete(ID id) {
baseRepository.delete(id);
}
@Override
public T findOne(ID id) {
return baseRepository.findOne(id);
}
@Override
public List<T> findAll() {
return baseRepository.findAll();
}
@Override
public List<T> queryAll(BaseQuery query) {
//1.拿到查询规则
Specification spec = query.createSpecification();
//2.进行查询
return baseRepository.findAll(spec);
}
@Override
public Page<T> queryPage(BaseQuery query) {
//1.拿到排序对象
Sort sort = query.createSort();
//2.拿到分页对象
Pageable pageable = new PageRequest(query.getCurrentPage2(), query.getPageSize(), sort);
//3.拿到查询规则
Specification spec = query.createSpecification();
//4.进行查询
return baseRepository.findAll(spec, pageable);
}
@Override
public List<Object> queryByJpql(String jpql, Object... params) {
//1.创建query对象
Query query = entityManager.createQuery(jpql);
//2.把参数放进去
for (int i = 0; i < params.length; i++) {
query.setParameter(i + 1, params[i]);
}
//3.获到数据
return query.getResultList();
}
}
2.4、子实现EmployeeServiceImpl
//对象由此类创建
@Service
public class EmployeeServiceImpl extends BaseServiceImpl<Employee,Long> implements IEmployeeService {
}
3、集成SpringMVC
3.1、配置applicationContext-mvc.xml
配置5个内容
- 扫描包
- 注解支持
- 静态资源放行
- 视图解析器
- 上传解析器 id必需叫:multipartResolver
<?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.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
">
<!--1.扫描包-->
<context:component-scan base-package="com.vivi.xxl.controller"/>
<!--2.注解支持-->
<mvc:annotation-driven/>
<!--3.静态资源放行-->
<mvc:default-servlet-handler/>
<!--4.视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!--5.上传解析器 id必需叫:multipartResolver-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize">
<value>10485760</value>
</property>
</bean>
</beans>
3.2、配置web.xml
- 运行与读取spring的配置
- 配置mvc的核心控制器
- 读取mvc配置
- tomcat启动用创建
- 编码过滤
注意:SpringMVC的配置和Spring的配置要单独读取,否则后面集成其它框架会出问题
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
id="WebApp_ID" version="3.1">
<!--SpringMVC的配置和Spring的配置要单独读取,否则后面集成其它框架会出问题-->
<!--运行与读取spring的配置-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!--配置mvc的核心控制器-->
<servlet>
<servlet-name>dispatchServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--读取mvc配置-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext-mvc.xml</param-value>
</init-param>
<!--tomcat启动用创建-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatchServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--编码过滤-->
<filter>
<filter-name>encodingFilter</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-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
4、Controller层
4.1、BaseController
package com.vivi.xxl.controller;
//暂时没有内容
public abstract class BaseController {
}
4.2、EmployeeController
@Controller
@RequestMapping("/employee")
public class EmployeeController extends BaseController {
@Autowired
private IEmployeeService employeeService;
@RequestMapping("/index")
public String index() {
//配置对应的路径和页面
return "employee/index";
}
@RequestMapping("/list")
@ResponseBody//响应json格式,前台页面直接展示
public List<Employee> list() {
return employeeService.findAll();
}
}
5、EasyUI的集成
5.1、head.jsp
- 将引用样式抽取出来统一交给head.jsp管理
- 以后要使用easyui直接引入即可
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--easyui的样式--%>
<link rel="stylesheet" type="text/css" href="/easyui/themes/default/easyui.css">
<%--easyui的图标 --%>
<link rel="stylesheet" type="text/css" href="/easyui/themes/icon.css">
<%--jQuery的支持--%>
<script type="text/javascript" src="/easyui/jquery.min.js"></script>
<%--jQuery的扩展包 --%>
<script type="text/javascript" src="/easyui/plugin/jquery.jdirk.js"></script>
<%--easyui的核心功能--%>
<script type="text/javascript" src="/easyui/jquery.easyui.min.js"></script>
<%--国际化--%>
<script type="text/javascript" src="/easyui/locale/easyui-lang-zh_CN.js"></script>
5.2、index.jsp
- pagination:true 分页条
- toolbar:’#toolbar’ 绑定工具栏【保存】【修改】【删除】【查询】
- data-method=“add” 绑定事件,统一写在页面对应的employee.js中
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@include file="/WEB-INF/views/head.jsp" %>
<html>
<head>
<title>Title</title>
<%--引入当前页面对应的js文件--%>
<script src="/js/model/employee.js"></script>
</head>
<body>
<!--工具栏-->
<div id="toolbar">
<div style="margin-bottom:5px">
<a href="#" data-method="add" class="easyui-linkbutton" iconCls="icon-add" plain="true">保存</a>
<a href="#" data-method="edit" class="easyui-linkbutton" iconCls="icon-edit" plain="true">修改</a>
<a href="#" data-method="delete" class="easyui-linkbutton" iconCls="icon-remove" plain="true">删除</a>
</div>
<form id="searchForm" method="post">
用户名: <input name="username" class="easyui-textbox" style="width:80px">
邮件: <input name="email" class="easyui-textbox" style="width:80px">
<a href="#" data-method="search" class="easyui-linkbutton" iconCls="icon-search">查询</a>
</form>
</div>
<%--pagination:true分页条--%>
<table id="datagrid" class="easyui-datagrid"
data-options="url:'/employee/page',fitColumns:true,singleSelect:true,fit:true,pagination:true,toolbar:'#toolbar'">
<thead>
<tr>
<th data-options="field:'id',width:100">编码</th>
<th data-options="field:'username',width:100">名称</th>
<th data-options="field:'age',width:100">年龄</th>
<th data-options="field:'password',width:100">密码</th>
<th data-options="field:'email',width:100">邮件</th>
</tr>
</thead>
</table>
</body>
</html>
5.3、employee.js
$(function () {
//常用的元素都先在这里获取到
var datagrid = $("#datagrid");
var searchForm = $("#searchForm");
$("*[data-method]").on("click", function () {
//拿到点击触发的方法名
var methodName = $(this).data("method");
//动态调用方法
vivi[methodName]();
})
vivi= {
//方法的简写,需要javascript language version 6版本才行
add() {},
edit() {},
delete() {},
search() {}
};
})
5.4、search方法
①employee.js代码
这里使用datagrid的一个方法datagrid(“load”, params),数据表格刷新至第一页加载
search() {
//1.拿到查询的值,
// var username = $("#username").val();
//var email = $("#email").val();
//下面这个方法需要引入jquery.jdirk.js
var params = searchForm.serializeObject();
//2.进行查询
datagrid.datagrid("load", params);
//datagrid.datagrid("load", {username: username, email: email});
}
②对应的EmployeeController,这样写会有下面的错误
@RequestMapping("/page")
@ResponseBody
public Page<Employee> list(EmployeeQuery query) {
return employeeService.queryPage(query);
}
返回Page< Employee >会创建如下图格式的JSON对象
而正确显示查询结果响应的JSON格式如下图
③因为响应的JSON对象格式不匹配,所以下面进行修改。
两种方法:
- 使用Map<k,value>响应
- 创建EasyUI专属page【下面介绍使用】
④UIPage
/*
*EasyUI专属page
* 解决响应格式不对
* content/totlalElements转换成
* rows/total
* */
public class UIPage<T> {
private Long total;
//提前创建好
private List<T> rows = new ArrayList<>();
public UIPage(Page page) {
this.total = page.getTotalElements();
this.rows = page.getContent();
}
//get和set
}
⑤修改EmployeeController
@RequestMapping("/page")
@ResponseBody
public UIPage<Employee> list(EmployeeQuery query) {
Page<Employee> page = employeeService.queryPage(query);
return new UIPage(page);
}
5.5、delete方法
①employee.js代码
delete() {
//获取选择的行
var row = datagrid.datagrid("getSelected");
//判断是否选择了一行
if (!row) {
//没有选择提示并结束
$.messager.alert('提示', '请先选择一行进行删除', "info");
return;
}
//选择了提示是否确认删除
$.messager.confirm('确认', '您确认想要删除记录吗?', function (r) {
if (r) {
//通过ajax删除
$.get("/employee/delete", {id: row.id}, function (result) {
//如果成功,重新加载页面
if (result.success) {
datagrid.datagrid("reload");
}else{
//失败给出提示消息,这里使用飘~,可以使用el表达式,不用拼接字符串了
$.messager.alert('提示',`删除失败,原因是:${result.msg}`,"error");
}
});
}
});
},
②JsonResult
package com.vivi.xxl.common;
/**
* 删除返回结果
*/
public class JsonResult {
//删除结果true表示成功,false失败
private boolean success = true;
//失败的原因
private String msg;
public JsonResult() {
}
public JsonResult(boolean success, String msg) {
this.success = success;
this.msg = msg;
}
//get和set
}
③EmployeeController
@RequestMapping("/delete")
@ResponseBody
public JsonResult delete(Long id) {
try {
employeeService.delete(id);
return new JsonResult();
} catch (Exception e) {
e.printStackTrace();
return new JsonResult(false, e.getMessage());
}
}