您好,登錄后才能下訂單哦!
這篇文章主要介紹“怎么實現web與后臺的聯動”,在日常操作中,相信很多人在怎么實現web與后臺的聯動問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”怎么實現web與后臺的聯動”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
一.項目結構:
1.common:工具類
2.domain:主體類
3.repository:持久化類/接口
4.query:查詢類
5.service:服務層
6.web:前端
①controller:控制層
二.今日目標
1.完成SpringDataJpa的擴展抽取,然后就可以直接使用了
2.完成流程搭建,并運行成功
①后臺代碼搭建
②前臺主頁連通
③完善類與展示頁面
④加入高級查詢
⑤功能擴展
三.代碼完成
[toc]
# 一.SpringDataJpa擴展
> 對SpringDataJpa的原來功能進行了相應的增加(代碼是拷備)## 1.BaseRepository 接口
> @NoRepositoryBean:讓SpringdataJpa不要自動為它生成子類
@NoRepositoryBean public interface BaseRepository<T, ID extends Serializable> extends JpaRepository<T,ID>, JpaSpecificationExecutor<T> { //根據Query拿到分頁對象(分頁) Page findPageByQuery(BaseQuery baseQuery); //根據Query拿到對應的所有數據(不分頁) List<T> findByQuery(BaseQuery baseQuery); //根據jpql與對應的參數拿到數據 List findByJpql(String jpql,Object... values); }
## 2.BaseRepositoryImpl 實現 BaseRepository
public class BaseRepositoryImpl<T,ID extends Serializable> extends SimpleJpaRepository<T,ID> implements BaseRepository<T,ID> { private final EntityManager entityManager; //必需要實現父類的這個構造器 public BaseRepositoryImpl(Class<T> domainClass, EntityManager em) { super(domainClass, em); this.entityManager = em; } @Override public Page findPageByQuery(BaseQuery baseQuery) { //第一步:拿到所有高級查詢條件 Specification spec = baseQuery.createSpec(); //第二步:拿到排序的值 Sort sort = baseQuery.createSort(); //第三步:根據條件查詢分頁數據并且返回 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) { //第一步:拿到所有高級查詢條件 Specification spec = baseQuery.createSpec(); //第二步:拿到排序的值 Sort sort = baseQuery.createSort(); //第三步:拿到數據返回 return findAll(spec, sort); } @Override public List findByJpql(String jpql, Object... values) { //第一步:創建Query對象 Query query = entityManager.createQuery(jpql); //第二步:把值設置到Query對象中去 if (values!=null) { for (int i = 0; i < values.length; i++) { query.setParameter(i + 1, values[i]); } } //第三步:返回數據 return query.getResultList(); } }
## 3.讓SpringDataJpa使用我們自己的實現
> 原來默認使用SimpleJpaRepository來實現,把它修改成BaseRepositoryImpl### 3.1 BaseRepositoryFactoryBean
/** * 如果要擴展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); //注:這里創建是我們的自定義類 } //繼承JpaRepositoryFactory后,把返回的對象修改成我們自己的實現 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; } //這里返回最后的功能對象 @Override protected Object getTargetRepository(RepositoryInformation information) { return new BaseRepositoryImpl<T,ID>((Class<T>)information.getDomainType(),entityManager); } //確定功能對象的類型 @Override protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) { return BaseRepositoryImpl.class; } } }
### 3.2 applicationContext.xml配置
> 關鍵就是factory-class配置
<!-- 集成SpringDataJpa (這層單獨掃描)--> <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使用的時候繼承BaseRepository
public interface EmployeeRepository extends BaseRepository<Employee,Long>{...}
# 二.Service層的調用
BaseServiceImpl 實現 IBaseService
IEmployeeService 繼承 IBaseService
> 注意點泛型注入
@Autowired private BaseRepository<T,ID> baseRepository;
# 三.集成SpringMVC與EasyUI
## 3.1 noSession問題
> 我們在關閉了EntityManager之前,依然在使用它操作數據庫(懶加載時出現)
>> 解決方案: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的懶加載對象自己為加一些屬性("hibernateLazyInitializer","handler","fieldHandler") 會影響到SpringMVC返回Json(因為返回時有個內省機制)
### 解決方案一:加注解
`@JsonIgnoreProperties(value={"hibernateLazyInitializer","handler","fieldHandler"})`
### 解決方案二:一勞永逸- 重寫:ObjectMapper
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; //重寫了原生的映射關系 public class CustomMapper extends ObjectMapper { public CustomMapper() { this.setSerializationInclusion(JsonInclude.Include.NON_NULL); // 設置 SerializationFeature.FAIL_ON_EMPTY_BEANS 為 false this.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); } }
- 在applicationContext-mvc.xml 配置這個映射
<!-- 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 為我們自定義擴展后的 CustomMapper,解決了返回對象有關系對象的報錯問題 --> <property name="objectMapper"> <bean class="cn.itsource.aisell.common.CustomMapper"></bean> </property> </bean> </mvc:message-converters> </mvc:annotation-driven>
## 3.3 分頁獲取數據
> 后臺返回的是Page對象{content:..,totalElements:..}
>> 前臺要拿代碼是{rows:..,total:...}
>>> 它們的結果對應不上- 搞了一個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 }
- 返回的時候代碼如下:
@RequestMapping("/page") @ResponseBody public UIPage page(EmployeeQuery query){ return new UIPage(employeeService.findPageByQuery(query)); }
## 3.4 分頁傳數據
> 傳的是page與rows,但是我們之前的query名稱沒對應上
- BaseQuery加上兼容
//為了兼容前臺的easyui而準備的,添加額外的setter
public void setPage(int page) { this.currentPage = page; } public void setRows(int rows) { this.pageSize = rows; }
## 3.5 高級查詢
- 高級查詢的時候獲取對應的表單值
### 引入[jquery.jdirk.js]
> 它對jQuery的功能進行擴展
`<script type="text/javascript" src="/easyui/plugin/jquery.jdirk.js"></script>`
### 獲取表單的功能
search(){ //直接獲取到表單中的所有值 var params = $("#searchForm").serializeObject(); //進行相應的查詢 $("#employeeGrid").datagrid("load",params); }
## 3.6 擴展部分
一.排序功能
BaseQuery后臺支持
/** * 公共的條件與規范 */ 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部分找到這個效果
并獲取需要的支持和源碼;
需要的部分:
<!-- 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標簽中添加 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">
到此,關于“怎么實現web與后臺的聯動”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。