您好,登錄后才能下訂單哦!
這篇文章主要介紹“怎么實(shí)現(xiàn)web與后臺(tái)的聯(lián)動(dòng)”,在日常操作中,相信很多人在怎么實(shí)現(xiàn)web與后臺(tái)的聯(lián)動(dòng)問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對(duì)大家解答”怎么實(shí)現(xiàn)web與后臺(tái)的聯(lián)動(dòng)”的疑惑有所幫助!接下來,請(qǐng)跟著小編一起來學(xué)習(xí)吧!
一.項(xiàng)目結(jié)構(gòu):
1.common:工具類
2.domain:主體類
3.repository:持久化類/接口
4.query:查詢類
5.service:服務(wù)層
6.web:前端
①controller:控制層
二.今日目標(biāo)
1.完成SpringDataJpa的擴(kuò)展抽取,然后就可以直接使用了
2.完成流程搭建,并運(yùn)行成功
①后臺(tái)代碼搭建
②前臺(tái)主頁連通
③完善類與展示頁面
④加入高級(jí)查詢
⑤功能擴(kuò)展
三.代碼完成
[toc]
# 一.SpringDataJpa擴(kuò)展
> 對(duì)SpringDataJpa的原來功能進(jìn)行了相應(yīng)的增加(代碼是拷備)## 1.BaseRepository 接口
> @NoRepositoryBean:讓SpringdataJpa不要自動(dòng)為它生成子類
@NoRepositoryBean public interface BaseRepository<T, ID extends Serializable> extends JpaRepository<T,ID>, JpaSpecificationExecutor<T> { //根據(jù)Query拿到分頁對(duì)象(分頁) Page findPageByQuery(BaseQuery baseQuery); //根據(jù)Query拿到對(duì)應(yīng)的所有數(shù)據(jù)(不分頁) List<T> findByQuery(BaseQuery baseQuery); //根據(jù)jpql與對(duì)應(yīng)的參數(shù)拿到數(shù)據(jù) List findByJpql(String jpql,Object... values); }
## 2.BaseRepositoryImpl 實(shí)現(xiàn) BaseRepository
public class BaseRepositoryImpl<T,ID extends Serializable> extends SimpleJpaRepository<T,ID> implements BaseRepository<T,ID> { private final EntityManager entityManager; //必需要實(shí)現(xiàn)父類的這個(gè)構(gòu)造器 public BaseRepositoryImpl(Class<T> domainClass, EntityManager em) { super(domainClass, em); this.entityManager = em; } @Override public Page findPageByQuery(BaseQuery baseQuery) { //第一步:拿到所有高級(jí)查詢條件 Specification spec = baseQuery.createSpec(); //第二步:拿到排序的值 Sort sort = baseQuery.createSort(); //第三步:根據(jù)條件查詢分頁數(shù)據(jù)并且返回 Pageable pageable = new PageRequest(baseQuery.getJpaPage(), baseQuery.getPageSize(),sort); Page<T> page = super.findAll(spec, pageable); return page; } @Override public List<T> findByQuery(BaseQuery baseQuery) { //第一步:拿到所有高級(jí)查詢條件 Specification spec = baseQuery.createSpec(); //第二步:拿到排序的值 Sort sort = baseQuery.createSort(); //第三步:拿到數(shù)據(jù)返回 return findAll(spec, sort); } @Override public List findByJpql(String jpql, Object... values) { //第一步:創(chuàng)建Query對(duì)象 Query query = entityManager.createQuery(jpql); //第二步:把值設(shè)置到Query對(duì)象中去 if (values!=null) { for (int i = 0; i < values.length; i++) { query.setParameter(i + 1, values[i]); } } //第三步:返回?cái)?shù)據(jù) return query.getResultList(); } }
## 3.讓SpringDataJpa使用我們自己的實(shí)現(xiàn)
> 原來默認(rèn)使用SimpleJpaRepository來實(shí)現(xiàn),把它修改成BaseRepositoryImpl### 3.1 BaseRepositoryFactoryBean
/** * 如果要擴(kuò)展SpringDataJpa必需寫它 */ public class BaseRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extends Serializable> extends JpaRepositoryFactoryBean<T,S,ID> { @Override protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) { return new MyRepositoryFactory<T,ID>(entityManager); //注:這里創(chuàng)建是我們的自定義類 } //繼承JpaRepositoryFactory后,把返回的對(duì)象修改成我們自己的實(shí)現(xiàn) private static class MyRepositoryFactory<T,ID extends Serializable> extends JpaRepositoryFactory { private final EntityManager entityManager; /** * Creates a new {@link JpaRepositoryFactory}. * * @param entityManager must not be {@literal null} */ public MyRepositoryFactory(EntityManager entityManager) { super(entityManager); this.entityManager = entityManager; } //這里返回最后的功能對(duì)象 @Override protected Object getTargetRepository(RepositoryInformation information) { return new BaseRepositoryImpl<T,ID>((Class<T>)information.getDomainType(),entityManager); } //確定功能對(duì)象的類型 @Override protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) { return BaseRepositoryImpl.class; } } }
### 3.2 applicationContext.xml配置
> 關(guān)鍵就是factory-class配置
<!-- 集成SpringDataJpa (這層單獨(dú)掃描)--> <jpa:repositories base-package="cn.itsource.aisell.repository" entity-manager-factory-ref="entityManagerFactory" transaction-manager-ref="transactionManager" factory-class="cn.itsource.aisell.repository.BaseRepositoryFactoryBean" ></jpa:repositories>
### 3.3使用的時(shí)候繼承BaseRepository
public interface EmployeeRepository extends BaseRepository<Employee,Long>{...}
# 二.Service層的調(diào)用
BaseServiceImpl 實(shí)現(xiàn) IBaseService
IEmployeeService 繼承 IBaseService
> 注意點(diǎn)泛型注入
@Autowired private BaseRepository<T,ID> baseRepository;
# 三.集成SpringMVC與EasyUI
## 3.1 noSession問題
> 我們?cè)陉P(guān)閉了EntityManager之前,依然在使用它操作數(shù)據(jù)庫(懶加載時(shí)出現(xiàn))
>> 解決方案:web.xml中添加OpenEntityManagerInViewFilter
<!-- 解決no-session的問題 -->
<filter> <filter-name>openEntityManager</filter-name> <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class> </filter> <filter-mapping> <filter-name>openEntityManager</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
## 3.2 no serializer問題
> 原因:jpa的懶加載對(duì)象自己為加一些屬性("hibernateLazyInitializer","handler","fieldHandler") 會(huì)影響到SpringMVC返回Json(因?yàn)榉祷貢r(shí)有個(gè)內(nèi)省機(jī)制)
### 解決方案一:加注解
`@JsonIgnoreProperties(value={"hibernateLazyInitializer","handler","fieldHandler"})`
### 解決方案二:一勞永逸- 重寫:ObjectMapper
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; //重寫了原生的映射關(guān)系 public class CustomMapper extends ObjectMapper { public CustomMapper() { this.setSerializationInclusion(JsonInclude.Include.NON_NULL); // 設(shè)置 SerializationFeature.FAIL_ON_EMPTY_BEANS 為 false this.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); } }
- 在applicationContext-mvc.xml 配置這個(gè)映射
<!-- Spring MVC 配置 -->
<mvc:annotation-driven> <mvc:message-converters> <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> <property name="supportedMediaTypes"> <list> <value>application/json; charset=UTF-8</value> <value>application/x-www-form-urlencoded; charset=UTF-8</value> </list> </property> <!-- No serializer:配置 objectMapper 為我們自定義擴(kuò)展后的 CustomMapper,解決了返回對(duì)象有關(guān)系對(duì)象的報(bào)錯(cuò)問題 --> <property name="objectMapper"> <bean class="cn.itsource.aisell.common.CustomMapper"></bean> </property> </bean> </mvc:message-converters> </mvc:annotation-driven>
## 3.3 分頁獲取數(shù)據(jù)
> 后臺(tái)返回的是Page對(duì)象{content:..,totalElements:..}
>> 前臺(tái)要拿代碼是{rows:..,total:...}
>>> 它們的結(jié)果對(duì)應(yīng)不上- 搞了一個(gè)UIPage
public class UIPage <T>{ private List<T> rows; private Long total; public UIPage(Page page) { this.rows = page.getContent(); this.total = page.getTotalElements(); } //省略getter與setter }
- 返回的時(shí)候代碼如下:
@RequestMapping("/page") @ResponseBody public UIPage page(EmployeeQuery query){ return new UIPage(employeeService.findPageByQuery(query)); }
## 3.4 分頁傳數(shù)據(jù)
> 傳的是page與rows,但是我們之前的query名稱沒對(duì)應(yīng)上
- BaseQuery加上兼容
//為了兼容前臺(tái)的easyui而準(zhǔn)備的,添加額外的setter
public void setPage(int page) { this.currentPage = page; } public void setRows(int rows) { this.pageSize = rows; }
## 3.5 高級(jí)查詢
- 高級(jí)查詢的時(shí)候獲取對(duì)應(yīng)的表單值
### 引入[jquery.jdirk.js]
> 它對(duì)jQuery的功能進(jìn)行擴(kuò)展
`<script type="text/javascript" src="/easyui/plugin/jquery.jdirk.js"></script>`
### 獲取表單的功能
search(){ //直接獲取到表單中的所有值 var params = $("#searchForm").serializeObject(); //進(jìn)行相應(yīng)的查詢 $("#employeeGrid").datagrid("load",params); }
## 3.6 擴(kuò)展部分
一.排序功能
BaseQuery后臺(tái)支持
/** * 公共的條件與規(guī)范 */ public abstract class BaseQuery { ... //兼容Easyui的排序 public void setSort(String sort) { this.orderByName = sort; } public void setOrder(String order) { this.orderByType = order; } }
2.employee.js支持 : 在需要支持的字段添加sortable="true"屬性
<th width="20" field="headImage" data-options="formatter:formatImage">頭像</th> <th width="20" field="username" sortable="true">用戶名</th> <th width="20" field="password">密碼</th> <th width="20" field="email">郵件</th> <th width="20" field="age" align="right" sortable="true">年齡</th> <th width="20" field="department" align="center" data-options="formatter:formatDept" sortable="true">部門</th>
3.隱藏字段
可以找到http://www.easyui-extlib.com/ -> grid部分找到這個(gè)效果
并獲取需要的支持和源碼;
需要的部分:
<!-- datagrid-隱藏列的支持 --> <link href="/easyui/plugin/datagrid/jeasyui.extensions.datagrid.css" rel="stylesheet" /> <script src="/easyui/plugin/menu/jeasyui.extensions.menu.js"></script> <script src="/easyui/plugin/datagrid/jeasyui.extensions.datagrid.getColumnInfo.js"></script> <script src="/easyui/plugin/datagrid/jeasyui.extensions.datagrid.columnToggle.js"></script>
在table標(biāo)簽中添加 enableHeaderClickMenu="true"屬性即可
<table id="employeeGrid" class="easyui-datagrid" data-options="fit:true,fixed:true,fitColumns:true,toolbar:'#tb',singleSelect:true" url="/employee/page" iconCls="icon-save" enableHeaderClickMenu="true" rownumbers="true" pagination="true">
到此,關(guān)于“怎么實(shí)現(xiàn)web與后臺(tái)的聯(lián)動(dòng)”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。