1.搭建前臺(tái)系統(tǒng)
1.1.前臺(tái)系統(tǒng)架構(gòu)
在互聯(lián)網(wǎng)系統(tǒng)開(kāi)發(fā)當(dāng)中浆竭,我們一般都是采用了分層的方式來(lái)架構(gòu)系統(tǒng)鬼贱,即:
(1)門(mén)戶(hù)層(門(mén)戶(hù)系統(tǒng)):網(wǎng)站的入口
i、渲染視圖始赎,提供用戶(hù)訪問(wèn)的頁(yè)面和橙。
ii、不查詢(xún)數(shù)據(jù)庫(kù)造垛,數(shù)據(jù)來(lái)自對(duì)遠(yuǎn)程服務(wù)(接口)的調(diào)用魔招。
(2)服務(wù)層:基于restful,以接口的形式對(duì)外提供公共的服務(wù)筋搏。
i仆百、連接數(shù)據(jù)庫(kù),返回json格式的數(shù)據(jù)奔脐。
1.1.1.分層架構(gòu)的好處
(1)俄周、有利于系統(tǒng)的維護(hù)和拓展。
(2)髓迎、有利于SOA服務(wù)治理的基礎(chǔ)峦朗。
1.2.搭建服務(wù)層系統(tǒng)
1.2.1.系統(tǒng)簡(jiǎn)介
基于RESTful實(shí)現(xiàn)。以接口的形式排龄,對(duì)外提供公共的服務(wù)波势。(比如購(gòu)物車(chē)档痪、導(dǎo)航菜單、搜索证舟、訂單等等)
RESTful是一種接口設(shè)計(jì)理念酗洒,即:
(1)不同的請(qǐng)求方式,對(duì)應(yīng)不同的業(yè)務(wù)類(lèi)型:
GET :查詢(xún)
POST :添加
PUT :更新
DELETE: 刪除
(2)返回json格式數(shù)據(jù)凛忿。
1.2.2.技術(shù)選擇
核心框架:Spring+SpringMVC+Mybatis-plus
數(shù) 據(jù) 庫(kù):MySQL
前端框架:無(wú)
1.2.3.配置步驟
思路:
(1)創(chuàng)建項(xiàng)目澈灼,導(dǎo)入jar依賴(lài)。
(2)整合SSM框架店溢。
1.2.3.1.第一步:創(chuàng)建maven項(xiàng)目(war)模型
注意:(1)項(xiàng)目繼承ego-project叁熔。
(2)使用maven module創(chuàng)建項(xiàng)目
1.2.3.2.第二步:導(dǎo)入jar依賴(lài)
導(dǎo)包說(shuō)明:
(1)ego-base子工程
(2)Spring核心包
(3)SpringMVC相關(guān)包
(4)AOP相關(guān)包
(5)JDBC、事物相關(guān)包
(6)Mybatis-plus及整合包
(7)JSON依賴(lài)包
導(dǎo)入插件:Tomcat插件(開(kāi)發(fā)階段床牧,啟動(dòng)項(xiàng)目荣回,對(duì)外發(fā)布接口)
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.gzsxt.ego</groupId>
<artifactId>ego-project</artifactId>
<version>1.0</version>
</parent>
<groupId>cn.gzsxt.ego</groupId>
<artifactId>ego-rest</artifactId>
<version>1.0</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>cn.gzsxt.ego</groupId>
<artifactId>ego-base</artifactId>
<version>1.0</version>
</dependency>
<!-- 整合SSM,導(dǎo)入spring戈咳、springmvc心软、mybatis相關(guān)依賴(lài) -->
<!-- 導(dǎo)入spring核心依賴(lài) 4+1 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<!-- 導(dǎo)入spirng-jdbc+事物 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<!-- 導(dǎo)入事物的依賴(lài) :切面 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</dependency>
<!-- 導(dǎo)入springmvc相關(guān)依賴(lài) -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<!-- 導(dǎo)入mybatis相關(guān)依賴(lài) -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
</dependency>
<!-- 導(dǎo)入jdbc、連接池依賴(lài) -->
<!-- MySql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- 連接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>
<!-- Jackson Json處理工具包 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 配置Tomcat插件 -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<configuration>
<port>8081</port>
<path>/</path>
<uriEncoding>UTF-8</uriEncoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
1.2.3.3.第三步:創(chuàng)建web.xml文件
說(shuō)明:可以從ego-manager工程中拷貝除秀,修改<url-pattern>即可糯累。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xml="http://www.w3.org/XML/1998/namespace" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_2_5.xsd ">
<!-- 配置編碼過(guò)濾器,防止post請(qǐng)求亂碼 -->
<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>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-*.xml</param-value>
</init-param>
<!-- 項(xiàng)目啟動(dòng)的時(shí)候册踩,就加載spring容器 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<!-- 所有請(qǐng)求rest服務(wù)層系統(tǒng)的請(qǐng)求泳姐,都必須在url加上/rest前綴,好處:方便做維護(hù)暂吉。 -->
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
1.2.3.4.第四步:整合SSM框架
整合中所需要的配置文件胖秒,均可從ego-manager工程中拷貝,修改局部的配置即可慕的。
1.2.3.4.1.Step1:Spring整合SpringMVC
創(chuàng)建spring-mvc.xml文件阎肝,做如下配置:
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
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-4.1.xsd">
<!-- 開(kāi)啟注解掃描 -->
<context:component-scan base-package="cn.gzsxt.rest"/>
<!-- 開(kāi)啟注解驅(qū)動(dòng) -->
<mvc:annotation-driven/>
</beans>
1.2.3.4.2.Step2:mybatis-plus整合spring
在這里,我們一定要有一個(gè)概念:任何持久層框架和Spring的整合肮街,都是為了使用Spring的事物代理风题。
(1)創(chuàng)建resource.properties文件,配置數(shù)據(jù)庫(kù)連接信息如下:
#配置數(shù)據(jù)源
db.driver=com.mysql.jdbc.Driver
db.url=jdbc:mysql://localhost:3306/ego
db.username=root
db.password=gzsxt
(2)創(chuàng)建spring-data.xml文件嫉父,配置框架整合沛硅。
<?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:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
<context:property-placeholder file-encoding="utf-8" location="classpath:resource.properties"/>
<!-- 1、創(chuàng)建數(shù)據(jù)源 -->
<bean name="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${db.driver}"/>
<property name="url" value="${db.url}"/>
<property name="username" value="${db.username}"/>
<property name="password" value="${db.password}"/>
<property name="maxActive" value="20"/>
<property name="minIdle" value="5"/>
</bean>
<!-- 2绕辖、mybatis-plus整合Spring
任何的數(shù)據(jù)庫(kù)的框架摇肌,要使用spring的事物代理,必須使用spring提供的數(shù)據(jù)源仪际,必須整合spring才可以使用
-->
<bean name="sqlSessionFactoryBean" class="com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean">
<!-- 加載數(shù)據(jù)源 -->
<property name="dataSource" ref="dataSource"/>
<!-- 指定pojo目錄 -->
<property name="typeAliasesPackage" value="cn.gzsxt.base.pojo"/>
<!-- 配置mybatis-plus插件 -->
<property name="plugins">
<list>
<!-- 配置分頁(yè)插件 -->
<bean class="com.baomidou.mybatisplus.plugins.PaginationInterceptor"/>
<!-- 配置攔截器屬性 -->
<bean class="com.baomidou.mybatisplus.plugins.PerformanceInterceptor">
<!-- 配置sql響應(yīng)時(shí)間围小,開(kāi)發(fā)階段方便做調(diào)優(yōu) -->
<property name="maxTime" value="1000"/>
<property name="format" value="true"/>
</bean>
</list>
</property>
<!-- 配置mybatis-plus全局策略 -->
<property name="globalConfig" ref="globalConfiguration"></property>
</bean>
<!-- 3昵骤、配置mybatis的動(dòng)態(tài)代理 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryBean"/>
<property name="basePackage" value="cn.gzsxt.base.mapper"></property>
</bean>
<!-- 配置mybatis-plus全局屬性 -->
<!-- 定義 MybatisPlus 的全局策略配置-->
<bean id ="globalConfiguration" class="com.baomidou.mybatisplus.entity.GlobalConfiguration">
<!-- 在 2.3 版本以后,dbColumnUnderline 默認(rèn)值是 true肯适,即pojo屬性開(kāi)啟駝峰標(biāo)識(shí) -->
<property name="dbColumnUnderline" value="true"></property>
<!-- 全局的主鍵策略 -->
<!--
AUTO->`0`("數(shù)據(jù)庫(kù)ID自增")
INPUT->`1`(用戶(hù)輸入ID")
ID_WORKER->`2`("全局唯一ID")
UUID->`3`("全局唯一ID")
-->
<property name="idType" value="0"></property>
<!-- 全局的表前綴策略配置 -->
<property name="tablePrefix" value="tb_"></property>
</bean>
<!-- 4变秦、配置事物管理器 -->
<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 5、開(kāi)啟注解聲明式事物 -->
<tx:annotation-driven/>
</beans>
1.2.3.5.第五步:整合測(cè)試
在這里我們使用靜態(tài)數(shù)據(jù)(category.json)框舔,來(lái)模擬導(dǎo)航菜單接口的實(shí)現(xiàn)伴栓。
(1)拷貝category.json文件到webapp目錄下。
(2)更新項(xiàng)目雨饺、安裝到本地倉(cāng)庫(kù)(updata、maven clean惑淳、maven install)
(3)啟動(dòng)項(xiàng)目
查看控制臺(tái)额港,啟動(dòng)成功!!!
(4)瀏覽器訪問(wèn),地址:http://localhost:8081/category.json歧焦,整合成功R普丁!绢馍!
1.3.搭建門(mén)戶(hù)系統(tǒng)
1.3.1.系統(tǒng)簡(jiǎn)介
簡(jiǎn)單來(lái)說(shuō)就是網(wǎng)站的入口向瓷,提供用戶(hù)瀏覽、下單的操作頁(yè)面舰涌。
門(mén)戶(hù)系統(tǒng)不直接調(diào)用數(shù)據(jù)庫(kù)猖任,而是通過(guò)服務(wù)系統(tǒng)提供的接口獲取數(shù)據(jù)。電商瓷耙、互聯(lián)網(wǎng)行業(yè)開(kāi)發(fā)都是面向服務(wù)開(kāi)發(fā)朱躺。
1.3.2.技術(shù)選擇
核心框架:Spring+SpringMVC
數(shù) 據(jù) 庫(kù):無(wú)
前端技術(shù):jquery、ajax搁痛、css+div长搀、easyui等
1.3.3.配置步驟
思路:
(1)創(chuàng)建項(xiàng)目
(2)框架整合
1.3.3.1.第一步:創(chuàng)建maven項(xiàng)目(war模型)
注意:
(1)繼承ego-project工程
(2)使用maven module創(chuàng)建子系統(tǒng)
1.3.3.2.第二步:導(dǎo)入jar依賴(lài)
在門(mén)戶(hù)系統(tǒng)中,不直接查詢(xún)數(shù)據(jù)庫(kù)鸡典,所以不需要導(dǎo)入數(shù)據(jù)庫(kù)相關(guān)的jar包源请。
在門(mén)戶(hù)系統(tǒng)中,用戶(hù)能夠搜索彻况、瀏覽商品谁尸,提交訂單等,所以需要添加jsp視圖相關(guān)依賴(lài)疗垛。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.gzsxt.ego</groupId>
<artifactId>ego-parent</artifactId>
<version>1.0</version>
</parent>
<groupId>cn.gzsxt.ego</groupId>
<artifactId>ego-portal</artifactId>
<version>1.0</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>cn.gzsxt.ego</groupId>
<artifactId>ego-base</artifactId>
<version>1.0</version>
</dependency>
<!-- jsp相關(guān)依賴(lài) -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<scope>provided</scope>
</dependency>
<!-- 導(dǎo)入spring核心依賴(lài) 4+1 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<!-- 導(dǎo)入springmvc相關(guān)依賴(lài) -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<!-- Jackson Json處理工具包 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 配置Tomcat插件 -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<configuration>
<port>8082</port>
<path>/</path>
<uriEncoding>UTF-8</uriEncoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
1.3.3.3.第三步:創(chuàng)建web.xml文件
可以從ego-rest工程拷貝症汹,修改<url-parten>配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xml="http://www.w3.org/XML/1998/namespace" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_2_5.xsd ">
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<!-- 配置編碼過(guò)濾器,防止post請(qǐng)求亂碼 -->
<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>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-*.xml</param-value>
</init-param>
<!-- 項(xiàng)目啟動(dòng)的時(shí)候贷腕,就加載spring容器 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<!-- 把請(qǐng)求路徑偽靜態(tài)話(huà)背镇,方便做seo搜索引擎優(yōu)化咬展,有利于做網(wǎng)站推廣 -->
<url-pattern>*.html</url-pattern>
</servlet-mapping>
</web-app>
1.3.3.4.第四步:導(dǎo)入jsp頁(yè)面、靜態(tài)資源
說(shuō)明:
(1)靜態(tài)資源放在/webapp目錄
(2)jsp放到/WEB-INF/JSP目錄下
1.3.3.5.第五步:Spring整合SpringMVC
從ego-rest工程拷貝瞒斩,修改部分配置即可破婆。
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
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-4.1.xsd">
<!-- 開(kāi)啟注解掃描 -->
<context:component-scan base-package="cn.gzsxt.portal"/>
<!-- 開(kāi)啟注解驅(qū)動(dòng) -->
<mvc:annotation-driven/>
<!-- 由于jsp存放路徑在WEB-INF下面,默認(rèn)視圖解析器解析不到胸囱,需要自己配一個(gè)視圖解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
1.3.3.6.第六步:整合測(cè)試
需求:訪問(wèn)門(mén)戶(hù)系統(tǒng)首頁(yè)祷舀。
(1)創(chuàng)建PageController類(lèi)
package cn.gzsxt.portal.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class PageController {
@RequestMapping("/index")
public String showIndex(){
return "index";
}
}
(2)更新項(xiàng)目、安裝到本地倉(cāng)庫(kù)烹笔。(update裳扯、clean、install)
(3)啟動(dòng)項(xiàng)目
(4)訪問(wèn)首頁(yè)谤职,地址:http://localhost:8082
前臺(tái)系統(tǒng)搭建成功J尾颉!允蜈!
2.首頁(yè)導(dǎo)航菜單實(shí)現(xiàn)
說(shuō)明:首頁(yè)導(dǎo)航菜單冤吨,是通過(guò)異步加載實(shí)現(xiàn)的。
好處:只有當(dāng)展開(kāi)導(dǎo)航菜單時(shí)饶套,才會(huì)發(fā)送請(qǐng)求漩蟆,從而節(jié)約cpu資源。
2.1.實(shí)現(xiàn)流程
需要解決的問(wèn)題:
(1)在rest系統(tǒng)中發(fā)布接口妓蛮,封裝導(dǎo)航菜單成json格式數(shù)據(jù)怠李。
(2)在portal系統(tǒng)中,遠(yuǎn)程請(qǐng)求接口(跨域請(qǐng)求)仔引。
2.2.跨越請(qǐng)求
2.2.1.什么是跨域(兩個(gè)不同系統(tǒng)之間的訪問(wèn)扔仓、調(diào)用)
(1)域名不同,即兩個(gè)不同的應(yīng)用咖耘。
(2)域名相同翘簇,但是端口不同,即同一個(gè)應(yīng)用中的不同子系統(tǒng)儿倒。
2.2.2.Ajax跨域請(qǐng)求的缺陷
在ego-rest系統(tǒng)使用靜態(tài)數(shù)據(jù)版保,模擬Ajax的跨域問(wèn)題。
2.2.2.1.第一步:在ego-rest中添加category.json文件夫否。(已實(shí)現(xiàn))
2.2.2.2.第二步:在ego-portal中發(fā)送ajax請(qǐng)求
(1)創(chuàng)建testJsonp.jsp頁(yè)面
<%@ 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>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="/js/jquery-1.6.4.js"></script>
<title>Insert title here</title>
</head>
<body>
<textarea id="text" style="width: 1200px; height: 200px;"></textarea>
<input type="button" value="測(cè)試異步跨越" onclick="testajax()" />
<script type="text/javascript">
function testajax(){
$.ajax({
url:"http://localhost:8081/category.json",
type: "GET",
success: function (data) {
$("#text").val(JSON.stringify(data));
}
});
}
</script>
</body>
</html>
(2)修改PageController彻犁,新增訪問(wèn)非首頁(yè)的方法。
@RequestMapping("/{page}")
public String showPage(@PathVariable("page")String page){
return page;
}
2.2.2.3.第三步:測(cè)試Ajax跨越
(1)重啟啟動(dòng)ego-portal系統(tǒng)凰慈,訪問(wèn)testJsonp.jsp
(2)點(diǎn)擊按鈕汞幢,發(fā)送異步請(qǐng)求
測(cè)試發(fā)現(xiàn),Ajax跨越請(qǐng)求失敗了微谓。
2.2.3.解決方案:jsonp跨域
在前面的測(cè)試中森篷,我們發(fā)現(xiàn)Ajax跨越請(qǐng)求時(shí)输钩,json數(shù)據(jù)被瀏覽器禁用了。
原因:瀏覽器禁止遠(yuǎn)程加載Json數(shù)據(jù)仲智。(瀏覽器安全機(jī)制)
如何解決呢买乃?
答:使用Jsonp方式。
2.2.3.1.Jsonp原理
Jsonp實(shí)現(xiàn)的前提:
瀏覽器允許跨越加載同源數(shù)據(jù)钓辆。
即在JavaScript腳本中發(fā)送請(qǐng)求剪验,就可以遠(yuǎn)程加載js格式數(shù)據(jù)。
請(qǐng)求原理:
(1)異步請(qǐng)求的時(shí)候前联,加上一個(gè)名為callback的回調(diào)函數(shù)
(2)在接口中功戚,將返回的json格式數(shù)據(jù),偽裝成js腳本格式似嗤。
(3)得到j(luò)s格式數(shù)據(jù)后疫铜,提取里面的json數(shù)據(jù)。
2.2.3.2.測(cè)試Jsonp
(1)修改testJsonp.jsp双谆,指定異步請(qǐng)求為jsonp方式。
<script type="text/javascript">
function testajax(){
$.ajax({
url:"http://localhost:8081/category.json",
type: "GET",
dataType: "jsonp", //jsonp請(qǐng)求
jsonp:"callbackFunction", //請(qǐng)求參數(shù)名
jsonpCallback:"showData", //回調(diào)函數(shù)名稱(chēng)
success: function (data) {
$("#text").val(JSON.stringify(data));
}
});
}
</script>
(2)在ego-rest工程中席揽,修改category.json文件顽馋,將返回?cái)?shù)據(jù)包裝成js腳本。
(3)再次發(fā)送ajax異步請(qǐng)求幌羞,使用jsonp方式
結(jié)論:
(1)jsonp是ajax技術(shù)中的一種異步請(qǐng)求方式寸谜。
(2)jsonp能實(shí)現(xiàn)跨越請(qǐng)求。
(3)jsonp跨越時(shí)属桦,需要指定一個(gè)回調(diào)函數(shù)熊痴,并使用該函數(shù)將返回的數(shù)據(jù)偽裝成js腳本。
(4)獲取返回的js腳本后聂宾,jsonp自動(dòng)提取其中的json數(shù)據(jù)果善。
2.3.首頁(yè)導(dǎo)航菜單實(shí)現(xiàn)
思路:
(1)在rest工程中,開(kāi)發(fā)接口系谐,返回js格式數(shù)據(jù)巾陕。(參考category.json)
(2)在portal工程中,修改jsonp請(qǐng)求路徑纪他。請(qǐng)求rest接口鄙煤。
2.3.1.第一部分:在rest工程中開(kāi)發(fā)導(dǎo)航菜單接口
2.3.1.1.第一步:定義導(dǎo)航菜單POJO
導(dǎo)航菜單結(jié)構(gòu)分析。(使用JsonViewer工具查看category.json)
結(jié)論:
(1)需要定義兩個(gè)POJO:菜單POJO茶袒、父目錄節(jié)點(diǎn)POJO
(2)導(dǎo)航菜單的數(shù)據(jù)梯刚,是一次加載出來(lái)的。
創(chuàng)建菜單Menu類(lèi)薪寓。(ego-base中創(chuàng)建)
package cn.gzsxt.base.pojo;
import java.util.List;
/**
* 自定義導(dǎo)航菜單
* @author ccnulyq
*
*/
public class Menu {
private List<?> data; //目錄節(jié)點(diǎn)
public List<?> getData() {
return data;
}
public void setData(List<?> data) {
this.data = data;
}
public Menu() {
super();
}
}
創(chuàng)建父目錄節(jié)點(diǎn)MenuNode類(lèi)
package cn.gzsxt.base.pojo;
import java.util.List;
/**
* 自定義目錄節(jié)點(diǎn)結(jié)構(gòu)
* @author ccnulyq
*
*/
public class MenuNode {
private String u; //目錄的鏈接
private String n; //目錄的名稱(chēng)
private List<?> i; //當(dāng)請(qǐng)目錄的子目錄
public MenuNode() {
super();
}
// 補(bǔ)全get亡资、set方法
}
(3)重新編譯ego-base工程澜共,安裝到本地倉(cāng)庫(kù)。(maven clean沟于、maven install)
2.3.1.2.第二步:創(chuàng)建ItemCatService接口及其實(shí)現(xiàn)類(lèi)
package cn.gzsxt.rest.service.impl;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import cn.gzsxt.base.mapper.ItemCatMapper;
import cn.gzsxt.base.pojo.ItemCat;
import cn.gzsxt.base.vo.Menu;
import cn.gzsxt.base.vo.MenuNode;
import cn.gzsxt.rest.service.ItemCatService;
@Service
public class ItemCatServiceImpl implements ItemCatService{
@Autowired
private ItemCatMapper itemCatMapper;
@Override
public Menu initMenu() {
Menu menu = new Menu();
//從返回值Menu的形式上來(lái)看咳胃,就是把一級(jí)目錄查詢(xún)出來(lái)即可。因此定義一個(gè)查詢(xún)方法旷太,通過(guò)parent_id=0查詢(xún)一級(jí)目錄
List nodes = getNodesByParantId(0L);
menu.setData(nodes);
return menu;
}
//根據(jù)父目錄的id展懈,查詢(xún)子目錄
private List getNodesByParantId(long parentId) {
Map<String, Object> params = new HashMap<>();
params.put("parent_id", parentId);
List<ItemCat> selectByMap = itemCatMapper.selectByMap(params);
List nodes = new ArrayList<>();
MenuNode node = null;
for (ItemCat itemCat : selectByMap) {
if(1==itemCat.getIsParent()){
node = new MenuNode();
node.setU("/products/"+itemCat.getId()+".html"); //u : "/products/1.html"
node.setN("<a href='/products/"+itemCat.getId()+".html'>"+itemCat.getName()+"</a>"); //n : "<a href='/products/1.html'>圖書(shū)、音像供璧、電子書(shū)刊</a>"
node.setI(getNodesByParantId(itemCat.getId()));
nodes.add(node);
}else{
nodes.add("/products/"+itemCat.getId()+".html|"+itemCat.getName()); //[3] : "/products/6.html|多媒體圖書(shū)"
}
}
return nodes;
}
}
2.3.1.3.第三步:創(chuàng)建ItemCatController類(lèi)
說(shuō)明:需要將返回值存崖,包裝成js腳本數(shù)據(jù)。
(1)方式一:手動(dòng)封裝
package cn.gzsxt.rest.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import cn.gzsxt.base.utils.JsonUtils;
import cn.gzsxt.base.vo.Menu;
import cn.gzsxt.rest.service.ItemCatService;
@Controller
public class ItemCatController {
@Autowired
private ItemCatService catService;
/*
* jsonp方法下睡毒,返回值来惧,要使用回調(diào)函數(shù)來(lái)偽裝js腳本
* @return
*/
@RequestMapping(value="/item/all",produces=MediaType.APPLICATION_JSON_VALUE + ";charset=utf-8")
@ResponseBody
public String getMenu(String callback){
Menu menu = catService.initMenu();
String jsonMenu = JsonUtils.objectToJson(menu);
String jsMenu = callback+"("+jsonMenu+")";
return jsMenu;
}
}
(2)方式二:使用MappingJacksonValue對(duì)象封裝
//使用MappingJacksonValue對(duì)象包裝返回結(jié)果,并設(shè)置jsonp的回調(diào)方法
@RequestMapping("/item/all")
@ResponseBody
public MappingJacksonValue queryAll(String callback) {
//查詢(xún)分類(lèi)列表
Menu menu = catService.getMenu();
//包裝jsonp
MappingJacksonValue jacksonValue = new MappingJacksonValue(menu);
//設(shè)置包裝的回調(diào)方法名
jacksonValue.setJsonpFunction(callback);
return jacksonValue;
}
2.3.1.4.第四步:測(cè)試接口
在瀏覽器訪問(wèn)演顾。
地址:http://localhost:8081/rest/item/all?callback=category.getDataService
2.3.2.第二部分:在portal工程中調(diào)用導(dǎo)航菜單接口
2.3.2.1.第一步:指定請(qǐng)求方式為jsonp
(1)修改lib-v1.js文件供搀,指定導(dǎo)航菜單接口地址。
(2)修改lib-v1.js文件钠至,指定請(qǐng)求方式為jsonp葛虐。
2.3.2.2.第二步:測(cè)試導(dǎo)航菜單
(1)重啟portal工程
(2)訪問(wèn)首頁(yè),請(qǐng)求導(dǎo)航菜單
導(dǎo)航菜單開(kāi)發(fā)成功C蘧S炱辍!
3.CMS系統(tǒng)
3.1.概念
CMS系統(tǒng)即為內(nèi)容管理系統(tǒng)宪卿。(Content Management System)
所謂的內(nèi)容的诵,就是出現(xiàn)在網(wǎng)頁(yè)中的圖片、文字佑钾、鏈接等西疤。CMS系統(tǒng)就是用來(lái)維護(hù)網(wǎng)頁(yè)中的內(nèi)容的,實(shí)現(xiàn)網(wǎng)頁(yè)中的內(nèi)容動(dòng)態(tài)休溶、可變瘪阁。
比如廣告位的投放,秒殺欄邮偎、排行榜實(shí)時(shí)更新等管跺,都需要通過(guò)CMS系統(tǒng)來(lái)實(shí)現(xiàn)。
3.2.CMS系統(tǒng)實(shí)現(xiàn)
3.2.1.思路
(1)禾进、將網(wǎng)頁(yè)中的內(nèi)容分類(lèi)
按照網(wǎng)頁(yè)的特性分類(lèi)豁跑,然后將每一類(lèi)網(wǎng)頁(yè)劃分成一個(gè)一個(gè)獨(dú)立的區(qū)域。
(2)在每一個(gè)內(nèi)容分類(lèi)下管理泻云、維護(hù)各自的內(nèi)容列表艇拍。
3.2.2.數(shù)據(jù)庫(kù)表關(guān)系
CMS系統(tǒng)主要涉及兩種表:
(1)內(nèi)容分類(lèi)表:tb_content_category(作用:定位)
(2)內(nèi)容表:tb_content
表之間的對(duì)應(yīng)關(guān)系為1-N
3.2.3.內(nèi)容分類(lèi)實(shí)現(xiàn)
3.2.3.1.需求
在后臺(tái)管理頁(yè)面狐蜕,點(diǎn)擊內(nèi)容分類(lèi)管理菜單,初始化內(nèi)容分類(lèi)樹(shù)結(jié)構(gòu)卸夕。該樹(shù)結(jié)構(gòu)可以添加层释、修改、刪除節(jié)點(diǎn)快集。
3.2.3.2.思路
(1)初始化內(nèi)容分類(lèi)導(dǎo)航樹(shù)贡羔。(這里使用easyui-tree)
(2)對(duì)異步樹(shù)進(jìn)行維護(hù)。(添加節(jié)點(diǎn)个初、刪除節(jié)點(diǎn)乖寒、更新節(jié)點(diǎn))
3.2.3.3.第一部分:初始化內(nèi)容分類(lèi)導(dǎo)航樹(shù)
3.2.3.3.1.第一步:初始化easyui異步樹(shù)插件
3.2.3.3.2.第二步:確定代碼結(jié)構(gòu)
<colgroup><col style="width: 103px;"><col style="width: 323px;"></colgroup>
|
Controller
|
表現(xiàn)層,負(fù)責(zé)交互院溺、綁定參數(shù)楣嘁、響應(yīng)視圖
|
|
Service
|
業(yè)務(wù)層,負(fù)責(zé)業(yè)務(wù)邏輯實(shí)現(xiàn)(封裝樹(shù)結(jié)構(gòu))
|
|
Mapper
|
持久層珍逸,逆向工程生成逐虚,不需要開(kāi)發(fā)。
|
3.2.3.3.3.第三步:確定請(qǐng)求響應(yīng)格式
<colgroup><col style="width: 85px;"><col style="width: 381px;"></colgroup>
|
請(qǐng)求路徑
|
/content/category/list
|
|
請(qǐng)求方式
|
GET請(qǐng)求
|
|
請(qǐng)求參數(shù)
|
id=nodeId(首次加載生成一級(jí)目錄時(shí)谆膳,默認(rèn)id=0)
|
|
響應(yīng)格式
|
List<EUTreeNode> (id,text,state:open|closed)
|
3.2.3.3.4.第四步:創(chuàng)建ContentCategory類(lèi)
在公共工程ego-base中創(chuàng)建痊班。
package cn.gzsxt.base.pojo;
import java.util.Date;
import com.baomidou.mybatisplus.annotations.TableField;
import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.annotations.TableName;
import com.baomidou.mybatisplus.enums.IdType;
@TableName(value="tb_content_category")
public class ContentCategory {
@TableId(value="id",type=IdType.AUTO)
private Long id;
@TableField(value="parent_id")
private Long parentId;
private String name;
private int status;
@TableField(value="sort_order")
private int sortOrdert;
@TableField(value="is_parent")
private byte isParent;
private Date created;
private Date updated;
public ContentCategory() {
super();
}
// 補(bǔ)全get、set方法
}
3.2.3.3.5.第五步:創(chuàng)建ContentCategoryMapper接口
在公共工程ego-base中創(chuàng)建摹量。
package cn.gzsxt.base.mapper;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import cn.gzsxt.base.pojo.ContentCategory;
public interface ContentCategoryMapper extends BaseMapper<ContentCategory>{
}
3.2.3.3.6.第六步:創(chuàng)建ContentCategoryService接口及其實(shí)現(xiàn)類(lèi)
package cn.gzsxt.manager.service.impl;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import cn.gzsxt.base.mapper.ContentCategoryMapper;
import cn.gzsxt.base.pojo.ContentCategory;
import cn.gzsxt.base.vo.EUTreeNode;
import cn.gzsxt.base.vo.EgoResult;
import cn.gzsxt.manager.service.ContentCategoryService;
@Service
public class ContentCategoryServiceImpl implements ContentCategoryService{
@Autowired
private ContentCategoryMapper mapper;
@Override
public List<EUTreeNode> selectByParentId(Long parentId) {
//定義返回值
List<EUTreeNode> nodes = new ArrayList<>();
//封裝查詢(xún)條件,執(zhí)行查詢(xún)
Map<String,Object> columnMap = new HashMap<>();
columnMap.put("parent_id", parentId);
List<ContentCategory> selectByMap = mapper.selectByMap(columnMap);
EUTreeNode node = null;
for (ContentCategory c : selectByMap) {
node = new EUTreeNode();
node.setId(c.getId());
node.setText(c.getName());
//三目運(yùn)算符
node.setState(1==c.getIsParent()?"closed":"open");
nodes.add(node);
}
return nodes;
}
}
3.2.3.3.7.第七步:創(chuàng)建ContentCategoryController類(lèi)
package cn.gzsxt.manager.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.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import cn.gzsxt.base.vo.EUTreeNode;
import cn.gzsxt.manager.service.ContentCategoryService;
@Controller
@RequestMapping("/content/category")
public class ContentCategoryController {
@Autowired
private ContentCategoryService service;
@RequestMapping(value="/list",method=RequestMethod.GET)
@ResponseBody
public List<EUTreeNode> selectByParentId(@RequestParam(name="id",defaultValue="0")Long parentId){
return service.selectByParentId(parentId);
}
}
3.2.3.3.8.第八步:測(cè)試
(1)重新編譯ego-manager工程馒胆。(clean缨称、install)
(2)重新啟動(dòng)ego-manager。
(3)訪問(wèn)內(nèi)容分類(lèi)管理
3.2.3.4.第二部分:添加內(nèi)容分類(lèi)節(jié)點(diǎn)
3.2.3.4.1.第一步:前端js實(shí)現(xiàn)
3.2.3.4.2.第二步:確定代碼結(jié)構(gòu)
<colgroup><col style="width: 105px;"><col style="width: 346px;"></colgroup>
|
Controller
|
視圖層祝迂,接收參數(shù)睦尽,將新增加的節(jié)點(diǎn)響應(yīng)出去
|
|
Service
|
業(yè)務(wù)層,新增節(jié)點(diǎn)型雳、更新父節(jié)點(diǎn)
|
|
Mapper
|
持久層当凡,逆向工程生成,不需要開(kāi)發(fā)纠俭。
|
3.2.3.4.3.第三步:確定請(qǐng)求響應(yīng)格式
<colgroup><col style="width: 89px;"><col style="width: 339px;"></colgroup>
|
請(qǐng)求路徑
|
/content/category/create
|
|
請(qǐng)求方式
|
POST
|
|
請(qǐng)求參數(shù)
|
parentId:node.parentId, name:node.text
|
|
響應(yīng)格式
|
{status:200,data:node} (EgoResult類(lèi)型)
|
3.2.3.4.4.第四步:修改ContentCategoryService及其實(shí)現(xiàn)類(lèi)沿量,新增save方法
注意:先在ContentCategoryService接口中定義save方法
@Transactional(rollbackFor=Exception.class)
@Override
public EgoResult save(Long parentId, String name) {
ContentCategory temp = new ContentCategory();
temp.setParentId(parentId);
temp.setName(name);
temp.setIsParent((byte) 0);
temp.setSortOrdert(1);
temp.setCreated(new Date());
temp.setStatus(1);
temp.setUpdated(temp.getCreated());
//mybatis-plus保存對(duì)象的時(shí)候,已經(jīng)實(shí)現(xiàn)了對(duì)象的id自動(dòng)同步冤荆。前提:數(shù)據(jù)庫(kù)id是自增朴则。
mapper.insert(temp);
/*
* 判斷當(dāng)前添加節(jié)點(diǎn)的父節(jié)點(diǎn)是否是目錄節(jié)點(diǎn)。
*
* 如果不是钓简,則要修改其狀態(tài)為父目錄結(jié)構(gòu)
*/
ContentCategory category = mapper.selectById(parentId);
if(0==category.getIsParent()){
category.setIsParent((byte) 1);
mapper.updateById(category);
}
return EgoResult.ok(temp);
}
3.2.3.4.5.第五步:修改ContentCategoryController類(lèi)乌妒,定義新增內(nèi)容分類(lèi)接口
@RequestMapping(value="/create",method=RequestMethod.POST)
@ResponseBody
public EgoResult create(Long parentId,String name){
EgoResult result = catService.save(name, parentId);
return result;
}
3.2.3.4.6.第六步:測(cè)試
(1)重新編譯ego-base工程汹想。(clean、install)
(2)重新啟動(dòng)ego-manager撤蚊。
(3)新增內(nèi)容分類(lèi)節(jié)點(diǎn)古掏。
3.2.3.5.第三部分:更新內(nèi)容分類(lèi)
3.2.3.5.1.第一步:前端js實(shí)現(xiàn)
3.2.3.5.2.第二步:確定請(qǐng)求響應(yīng)格式
<colgroup><col style="width: 87px;"><col style="width: 342px;"></colgroup>
|
請(qǐng)求路徑
|
/content/category/updata
|
|
請(qǐng)求方式
|
POST
|
|
請(qǐng)求參數(shù)
|
id:node.id, name:node.text
|
|
響應(yīng)格式
|
{status:200,data:node} (EgoResult類(lèi)型)
|
3.2.3.5.3.第三步:修改ContentCategoryService及其接口,新增update方法侦啸。
注意:先在service接口中定義方法槽唾。
@Override
public EgoResult updateNode(String name, Long id) {
ContentCategory contentCat = new ContentCategory();
contentCat.setName(name);
contentCat.setId(id);
contentCatMapper.updateById(contentCat);
return EgoResult.ok();
}
3.2.3.5.4.第四步:修改ContentController類(lèi),定義更新的接口
@RequestMapping(value="/update",method=RequestMethod.POST)
@ResponseBody
public EgoResult updateNode(Long id,String name){
EgoResult result = catService.updateNode(name, id);
return result;
}
3.2.3.5.5.第五步:測(cè)試
(1)重新編譯ego-manager工程匹中。(clean夏漱、install)
(2)重新啟動(dòng)ego-manager。
(3)更新內(nèi)容分類(lèi)節(jié)點(diǎn)顶捷。
3.2.3.6.第四部分:刪除內(nèi)容分類(lèi)
3.2.3.6.1.第一步:前端js實(shí)現(xiàn)
3.2.3.6.2.第二步:確定請(qǐng)求響應(yīng)格式
<colgroup><col style="width: 90px;"><col style="width: 337px;"></colgroup>
|
請(qǐng)求路徑
|
/content/category/delete
|
|
請(qǐng)求方式
|
POST
|
|
請(qǐng)求參數(shù)
|
id:node.id, parentId:node.parentId
|
|
響應(yīng)格式
|
{status:200,data:node} (EgoResult類(lèi)型)
|
3.2.3.6.3.第三步:修改ContentCategoryService及其實(shí)現(xiàn)類(lèi)挂绰,新增delete方法
@Transactional
@Override
public EgoResult deleteNode(Long id, Long parentId) {
// 第一步:判斷parent_id是否有值
if (parentId == null) {
parentId = contentCategoryMapper.selectById(id).getParentId();
}
// 第二步:判斷該節(jié)點(diǎn)是否是它的父節(jié)點(diǎn)的最后一個(gè)節(jié)點(diǎn)。如果是服赎。那么需要將它的父節(jié)點(diǎn)修改為葉節(jié)點(diǎn)
EntityWrapper<ContentCategory> wrapper = new EntityWrapper<>();
wrapper.eq("parent_id", parentId);
//過(guò)濾只查詢(xún)有效的狀態(tài)
wrapper.eq("status", 1);
List<ContentCategory> categories = contentCategoryMapper.selectList(wrapper);
if (categories.size() == 1) {
ContentCategory parentCategory = contentCategoryMapper.selectById(parentId);
// 父節(jié)點(diǎn)修改為葉節(jié)點(diǎn)
parentCategory.setIsParent((byte) 0);
parentCategory.setUpdated(new Date());
contentCategoryMapper.updateById(parentCategory);
}
// 第三步:修改當(dāng)前節(jié)點(diǎn)的狀態(tài)值葵蒂,修改為刪除狀態(tài)
ContentCategory category = contentCategoryMapper.selectById(id);
category.setStatus(2);
category.setUpdated(new Date());
contentCategoryMapper.updateById(category);
return EgoResult.ok();
}
3.2.3.6.4.第四步:修改ContentCategoryController類(lèi),定義delete接口
@RequestMapping(value="/delete",method=RequestMethod.POST)
@ResponseBody
public EgoResult deleteNode(Long id,Long parentId){
EgoResult result = catService.deleteNode(id, parentId);
return result;
}
3.2.4.內(nèi)容管理實(shí)現(xiàn)
3.2.4.1.需求
根據(jù)內(nèi)容分類(lèi)id重虑,查詢(xún)數(shù)據(jù)庫(kù)表tb_content践付,獲取內(nèi)容列表。
內(nèi)容分類(lèi)樹(shù)使用easyui-tree組件缺厉,內(nèi)容列表使用easyui-datagrid組件永高。
3.2.4.2.思路
(1)實(shí)現(xiàn)內(nèi)容列表查詢(xún)。
(2)在內(nèi)容分類(lèi)節(jié)點(diǎn)下提针,維護(hù)內(nèi)容列表命爬。
3.2.4.3.第一部分:內(nèi)容列表實(shí)現(xiàn)
3.2.4.3.1.第一步:加載easyui-datagrid插件
(1)初始化分類(lèi)導(dǎo)航樹(shù)(后臺(tái)java已實(shí)現(xiàn),見(jiàn)2.2.1.3.2章節(jié))
(2)選中內(nèi)容分類(lèi)節(jié)點(diǎn)
(3)查詢(xún)?cè)摴?jié)點(diǎn)下的內(nèi)容列表
3.2.4.3.2.第二步:確定代碼結(jié)構(gòu)
<colgroup><col style="width: 130px;"><col style="width: 130px;"></colgroup>
|
Controller
|
獲取分類(lèi)ID辐脖,分頁(yè)信息饲宛,響應(yīng)列表數(shù)據(jù)
|
|
Service
|
分頁(yè)查詢(xún)邏輯
|
|
Mapper
|
逆向工程生成,不需要開(kāi)發(fā)
|
3.2.4.3.3.第三步:確定請(qǐng)求響應(yīng)結(jié)構(gòu)
<colgroup><col style="width: 89px;"><col style="width: 534px;"></colgroup>
|
請(qǐng)求路徑
|
/content/query/list
|
|
請(qǐng)求方式
|
GET
|
|
請(qǐng)求參數(shù)
|
{categoryId:0 , page:1 , rows:20}
|
|
響應(yīng)格式
|
{total:20,rows:dataList} (參見(jiàn)ego-base中的EUDataGridRestult類(lèi))
|
3.2.4.3.4.第四步:創(chuàng)建Content類(lèi)
在ego-base工程中創(chuàng)建嗜价!
package cn.gzsxt.base.pojo;
import java.util.Date;
import com.baomidou.mybatisplus.annotations.TableField;
import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.annotations.TableName;
import com.baomidou.mybatisplus.enums.IdType;
@TableName(value="tb_content")
public class Content {
@TableId(value="id",type=IdType.AUTO)
private Long id;
@TableField(value="category_id")
private long categoryId;
private String title;
@TableField(value="sub_title")
private String subTitle;
@TableField(value="title_desc")
private String titleDesc;
private String url;
private String pic;
private String pic2;
private String content;
private Date created;
private Date updated;
public Content() {
super();
}
// 補(bǔ)全get艇抠、set方法
}
3.2.4.3.5.第五步:創(chuàng)建ContentMapper接口
在ego-base工程中創(chuàng)建!
package cn.gzsxt.base.mapper;
import com.baomidou.mybatisplus.mapper.BaseMapper;
import cn.gzsxt.base.pojo.Content;
public interface ContentMapper extends BaseMapper<Content>{
}
3.2.4.3.6.第六步:創(chuàng)建ContentService接口及其實(shí)現(xiàn)類(lèi)
package cn.gzsxt.manager.service.impl;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import cn.gzsxt.base.mapper.ContentMapper;
import cn.gzsxt.base.pojo.Content;
import cn.gzsxt.base.vo.EUDataGridResult;
import cn.gzsxt.base.vo.EgoResult;
import cn.gzsxt.manager.service.ContentService;
@Service
public class ContentServiceImpl implements ContentService{
@Autowired
private ContentMapper mapper;
@Override
public EUDataGridResult listByCatIdAndPage(Long categoryId, int page, int rows) {
EUDataGridResult result = new EUDataGridResult();
/*
* offset 偏移量 即limit函數(shù)中的start
* limit 容量
*/
RowBounds rowBounds = new RowBounds((page-1)*rows, rows);
EntityWrapper<Content> wrapper = new EntityWrapper<>();
wrapper.eq("category_id", categoryId);
List<Content> selectPage = mapper.selectPage(rowBounds, wrapper);
Integer count = mapper.selectCount(wrapper);
result.setTotal(count);
result.setRows(selectPage);
return result;
}
}
3.2.4.3.7.第七步:創(chuàng)建ContentController類(lèi)
package cn.gzsxt.manager.controller;
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.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import cn.gzsxt.base.pojo.Content;
import cn.gzsxt.base.vo.EUDataGridResult;
import cn.gzsxt.base.vo.EgoResult;
import cn.gzsxt.manager.service.ContentService;
@Controller
@RequestMapping("/content")
public class ContentController {
@Autowired
private ContentService service;
@RequestMapping(value="/query/list")
@ResponseBody
public EUDataGridResult selectByCatIdAndPage(Long categoryId,Integer page,Integer rows){
EUDataGridResult result = service.listByCatIdAndPage(categoryId, page, rows);
return result;
}
}
3.2.4.3.8.第八步:測(cè)試
(1)重新編譯ego-manager工程久锥。(clean家淤、install)
(2)重新啟動(dòng)ego-manager。
(3)查看內(nèi)容列表瑟由。成功C焦摹!!
3.2.4.4.第二部分:新增內(nèi)容
3.2.4.4.1.第一步:前端js實(shí)現(xiàn)
3.2.4.4.2.第二步:確定代碼結(jié)構(gòu)
<colgroup><col style="width: 130px;"><col style="width: 226px;"></colgroup>
|
Controller
|
接收表單數(shù)據(jù)绿鸣,響應(yīng)保存結(jié)果
|
|
Service
|
保存邏輯實(shí)現(xiàn)
|
|
Mapper
|
逆向工程生成
|
3.2.4.4.3.第三步:確定請(qǐng)求響應(yīng)格式
<colgroup><col style="width: 130px;"><col style="width: 250px;"></colgroup>
|
請(qǐng)求路徑
|
/content/save
|
|
請(qǐng)求方式
|
POST
|
|
請(qǐng)求參數(shù)
|
Content類(lèi)
|
|
響應(yīng)格式
|
{status:200} (EgoResult類(lèi)型)
|
3.2.4.4.4.第四步:修改ContentService接口及其實(shí)現(xiàn)類(lèi)疚沐,新增save方法
@Override
public EgoResult addContent(Content content) throws Exception {
//把圖片信息保存至數(shù)據(jù)庫(kù)
content.setCreated(new Date());
content.setUpdated(new Date());
//把內(nèi)容信息添加到數(shù)據(jù)庫(kù)
mapper.insert(content);
return EgoResult.ok();
}
3.2.4.4.5.第五步:修改ContentController類(lèi),定義save接口
@RequestMapping("/save")
@ResponseBody
public EgoResult addContent(Content content) throws Exception {
EgoResult result = service.addContent(content);
return result;
}
3.2.4.5.第三部分:更新內(nèi)容
3.2.4.5.1.第一步:前端js實(shí)現(xiàn)
3.2.4.5.2.第二步:確定請(qǐng)求響應(yīng)格式
<colgroup><col style="width: 130px;"><col style="width: 250px;"></colgroup>
|
請(qǐng)求路徑
|
/content/edit
|
|
請(qǐng)求方式
|
POST
|
|
請(qǐng)求參數(shù)
|
Content類(lèi)
|
|
響應(yīng)格式
|
{status:200} (EgoResult類(lèi)型)
|
3.2.4.5.3.第三步:修改ContentService接口及其實(shí)現(xiàn)類(lèi)潮模,新增update方法
@Override
public EgoResult update(Content content) {
mapper.updateById(content);
return EgoResult.ok();
}
3.2.4.5.4.第四步:修改ContentController類(lèi)亮蛔,新增update接口
@RequestMapping("/edit")
@ResponseBody
public EgoResult update(Content Content){
EgoResult result = service.update(Content);
return result;
}
3.2.4.6.第四部分:刪除內(nèi)容
3.2.4.6.1.第一步:前端js實(shí)現(xiàn)
獲取所有要?jiǎng)h除的內(nèi)容的id,封裝到數(shù)組中擎厢。
3.2.4.6.2.第二步:確定請(qǐng)求響應(yīng)格式
<colgroup><col style="width: 130px;"><col style="width: 250px;"></colgroup>
|
請(qǐng)求路徑
|
/content/delete
|
|
請(qǐng)求方式
|
POST
|
|
請(qǐng)求參數(shù)
|
Ids[]:{1,2,3} 數(shù)組類(lèi)型
|
|
響應(yīng)格式
|
{status:200} (EgoResult類(lèi)型)
|
3.2.4.6.3.第三步:修改ContentService接口及其實(shí)現(xiàn)類(lèi)究流,新增delete方法
@Override
public EgoResult delete(Integer[] ids) {
List<Integer> idss = Arrays.asList(ids);
mapper.deleteBatchIds(idss);
return EgoResult.ok();
}
3.2.4.6.4.第四步:修改ContentController類(lèi),新增delete接口
@RequestMapping("/delete")
@ResponseBody
public EgoResult delete(Integer[] ids){
EgoResult result = service.delete(ids);
return result;
}
4.首頁(yè)大廣告實(shí)現(xiàn)
4.1.需求
訪問(wèn)門(mén)戶(hù)系統(tǒng)首頁(yè)动遭,在大廣位區(qū)域展示大廣告位對(duì)應(yīng)的內(nèi)容芬探。
4.2.實(shí)現(xiàn)流程
(1)、在CMS系統(tǒng)中維護(hù)大廣告位的內(nèi)容厘惦。
(2)偷仿、在REST系統(tǒng)中查詢(xún)大廣告位的內(nèi)容列表,以接口的形式對(duì)外提供服務(wù)宵蕉。
(3)酝静、在portal門(mén)戶(hù)系統(tǒng)中遠(yuǎn)程訪問(wèn)REST系統(tǒng)。
11.第一部分:REST系統(tǒng)接口實(shí)現(xiàn)
需求:
根據(jù)內(nèi)容分類(lèi)id羡玛,查詢(xún)tb_content表别智,獲得大廣告位內(nèi)容列表。
4.3.1.第一步:確定代碼結(jié)構(gòu)
<colgroup><col style="width: 130px;"><col style="width: 418px;"></colgroup>
|
Controller
|
定義接口規(guī)則(請(qǐng)求路徑稼稿、請(qǐng)求方式薄榛、參數(shù)、響應(yīng)值類(lèi)型)
|
|
Service
|
定義查詢(xún)邏輯
|
|
Mapper
|
查詢(xún)數(shù)據(jù)庫(kù)
|
4.3.2.第二步:定義接口規(guī)則
<colgroup><col style="width: 130px;"><col style="width: 226px;"></colgroup>
|
請(qǐng)求路徑
|
/rest/content/category/{cid}
|
|
請(qǐng)求方式
|
GET
|
|
請(qǐng)求參數(shù)
|
/{cid} 路徑變量
|
|
響應(yīng)類(lèi)型
|
EgoResult
|
|
示例
|
demo
|
4.3.3.第三步:創(chuàng)建ContentService接口及其實(shí)現(xiàn)類(lèi)
package cn.gzsxt.rest.service.impl;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import cn.gzsxt.base.mapper.ContentMapper;
import cn.gzsxt.base.pojo.Content;
import cn.gzsxt.base.utils.JsonUtils;
import cn.gzsxt.rest.service.ContentService;
@Service
public class ContentServiceImpl implements ContentService{
@Autowired
private ContentMapper mapper;
@Override
public EgoResult getContentByCatId(Long catId) {
Map<String, Object> columnMap = new HashMap<>();
columnMap.put("category_id", catId);
List<Content> list = mapper.selectByMap(columnMap);
return EgoResult.ok(list);
}
}
4.3.4.第四步:創(chuàng)建ContentController類(lèi)
@RestController
@RequestMapping("/content")
public class ContentController {
@Autowired
private ContentService contentService;
@RequestMapping("/category/{cid}")
public EgoResult getContentList(@PathVariable Long cid) {
EgoResult result = contentService.getContentByCatId(cid);
return result;
}
}
4.4.第二部分:遠(yuǎn)程接口調(diào)用方式HttpClient
問(wèn)題:現(xiàn)在我們已經(jīng)開(kāi)發(fā)好了接口了让歼,那該如何調(diào)用這個(gè)接口呢敞恋?
答:使用Httpclient客戶(hù)端。
4.4.1.Httpclient簡(jiǎn)介
4.4.1.1.什么是httpclient
HttpClient 是 Apache Jakarta Common 下的子項(xiàng)目是越,用來(lái)提供高效的、最新的、功能豐富的支持 HTTP 協(xié)議的客戶(hù)端編程工具包,并且它支持 HTTP 協(xié)議最新的版本和建議敦捧。實(shí)現(xiàn)了所有 HTTP 的方法(GET,POST,PUT,HEAD 等)
4.4.1.2.httpclient作用
在java代碼中膘魄,發(fā)送Http請(qǐng)求。通常用來(lái)實(shí)現(xiàn)遠(yuǎn)程接口調(diào)用营密。
4.4.2.HttpClient測(cè)試
說(shuō)明:在ego-base中測(cè)試
在ego-base工程中添加httpclient的pom依賴(lài)。
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
4.4.2.1.執(zhí)行GET請(qǐng)求
public static void doGet(){
// 創(chuàng)建Httpclient對(duì)象
CloseableHttpClient httpclient = HttpClients.createDefault();
// 創(chuàng)建http GET請(qǐng)求
HttpGet httpGet = new HttpGet("http://www.oschina.net/");
CloseableHttpResponse response = null;
try {
// 執(zhí)行請(qǐng)求
response = httpclient.execute(httpGet);
System.out.println(response.getStatusLine());
// 判斷返回狀態(tài)是否為200
if (response.getStatusLine().getStatusCode() == 200) {
String content = EntityUtils.toString(response.getEntity(), "UTF-8");
System.out.println("內(nèi)容長(zhǎng)度:" + content.length());
}
}catch(Exception e){
e.printStackTrace();
} finally {
if (response != null) {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
httpclient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
4.4.2.2.執(zhí)行GET帶參數(shù)
public static void doGetParam(){
// 創(chuàng)建Httpclient對(duì)象
CloseableHttpClient httpclient = HttpClients.createDefault();
CloseableHttpResponse response = null;
try {
// 定義請(qǐng)求的參數(shù)
URI uri = new URIBuilder("http://www.baidu.com/s").setParameter("wd", "數(shù)據(jù)庫(kù)").build();
System.out.println(uri);
// 創(chuàng)建http GET請(qǐng)求
HttpGet httpGet = new HttpGet(uri);
// 執(zhí)行請(qǐng)求
response = httpclient.execute(httpGet);
// 判斷返回狀態(tài)是否為200
if (response.getStatusLine().getStatusCode() == 200) {
String content = EntityUtils.toString(response.getEntity(), "UTF-8");
System.out.println(content);
}
}catch(Exception e){
e.printStackTrace();
}finally {
if (response != null) {
try {
response.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
httpclient.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
4.4.2.3.執(zhí)行post請(qǐng)求
public static void doPost(){
// 創(chuàng)建Httpclient對(duì)象
CloseableHttpClient httpclient = HttpClientBuilder.create().setRedirectStrategy(new LaxRedirectStrategy()).build();
// 創(chuàng)建http POST請(qǐng)求
HttpPost httpPost = new HttpPost("http://www.oschina.net/");
CloseableHttpResponse response = null;
try {
// 執(zhí)行請(qǐng)求
response = httpclient.execute(httpPost);
System.out.println(response.getStatusLine());
// 判斷返回狀態(tài)是否為200
if (response.getStatusLine().getStatusCode() == 200) {
String content = EntityUtils.toString(response.getEntity(), "UTF-8");
System.out.println(content);
}
}catch(Exception e){
e.printStackTrace();
}finally {
if (response != null) {
try {
response.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
httpclient.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
4.4.2.4.執(zhí)行post帶參數(shù)
public static void doPostParam() throws Exception{
// 創(chuàng)建Httpclient對(duì)象
CloseableHttpClient httpclient = HttpClientBuilder.create().setRedirectStrategy(new LaxRedirectStrategy()).build();
// 創(chuàng)建http POST請(qǐng)求
HttpPost httpPost = new HttpPost("http://www.oschina.net/search");
// 設(shè)置2個(gè)post參數(shù),一個(gè)是scope呢岗、一個(gè)是q
List<NameValuePair> parameters = new ArrayList<NameValuePair>();
parameters.add(new BasicNameValuePair("scope", "project"));
parameters.add(new BasicNameValuePair("q", "java"));
// 構(gòu)造一個(gè)form表單式的實(shí)體
UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(parameters);
// 將請(qǐng)求實(shí)體設(shè)置到httpPost對(duì)象中
httpPost.setEntity(formEntity);
CloseableHttpResponse response = null;
try {
// 執(zhí)行請(qǐng)求
response = httpclient.execute(httpPost);
System.out.println(response.getStatusLine());
// 判斷返回狀態(tài)是否為200
if (response.getStatusLine().getStatusCode() == 200) {
String content = EntityUtils.toString(response.getEntity(), "UTF-8");
System.out.println(content);
}
} finally {
if (response != null) {
response.close();
}
httpclient.close();
}
}