SSM專題複習 day01
1 課程回顧
必做
-
新建項目或者是git上拉取的老項目檢查Maven環境、JDK版本 、項目的編碼UTF-8
-
搭建項目工程
-
理清項目的結構和每一個模塊的功能打包方式 (common、dao、pojo 等對內服務的模塊打jar包 web、service等對外提供服務的打war包)
-
理解Java開發的數據流轉流程
前端傳參數 —> 後端 —> Controller(SpringMvc、Struts2[淘汰]) —> Service(Spring) —> Dao (Mybatis|Hibernate、JPA、MP) —> 數據庫(MySQL)
映射關係:數據庫中的表的字段 和 Java中實體類中的 成員屬性的對應關係
-
Lombok的插件回顧
-
@Data // get/set/無參構造/
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true) // 鏈式調用 可連續調用.set()方法
public class CheckItem implements Serializable {
private Integer id;//主鍵
private String code;//項目編碼
private String name;//項目名稱
private String sex;//適用性別
private String age;//適用年齡(範圍),例如:20-50
private Float price;//價格
private String type;//檢查項類型,分爲檢查和檢驗兩種類型
private String remark;//項目說明
private String attention;//注意事項
}
-
搭建細節
- POM依賴座標
- 對應的配置文件加入對應的模塊中
- 實現代碼編寫
2 項目的搭建
總體概覽:
依次創建:
1、創建父工程
Fuxi_SSM 打包方式pom
<packaging>pom</packaging>
<!-- 集中定義依賴版本號 -->
<properties>
<junit.version>4.12</junit.version>
</properties>
<!-- 依賴管理標籤 必須加 此時並不加載這些座標 -->
<dependencyManagement>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
父工程的主要作用是:
統一管理依賴 聚合其他子模塊
2、pojo模塊
打包方式jar包
主要作用: 根據數據庫創建對應的JavaBean 供其他模塊使用
3、common模塊
打包方式jar包
主要作用:存放工具類、實體類等組件、引入公共座標
4、dao模塊
需要注意: mapper代理規範 5個要點
- 1、mapper 接口 和 mapper.xml 配置文件 的包路徑要一致
- 2、mapper接口名 要和 mapper.xml文件名要相同
- 3、xml文件內的 namespace屬性要寫 mapper 接口的全限定名 < mapper namespace=“cn.ssm.fuxi.mapper.CheckItemMapper”>
- 4、SQL標籤 的id 屬性 要和 mapper接口內的方法名 對應 < select id=“findAll” resultType=“CheckItem”>
- 5、mapper接口方法內的參數 要和 SQL標籤內的 resultType屬性 對應
非常重要 注意類上要使用@Mapper註解
打包方式:jar包 供service調用
主要用於操作數據庫
需要數據庫配置文件
- 加載屬性配置文件(xxx.properties)
- 配置數據源
- spring和mybatis整合的工廠bean org.mybatis.spring.SqlSessionFactoryBean
- < !–包掃描-- > 掃描實體類所在包
- < !–3、批量掃描接口生成代理對象–> 掃描dao 或mapper 接口所在包
SqlMapConfig.xml 可用於配置mybatis別名 和 Mybatis插件
5、interface接口模塊
基於接口編程 擴大了程序的可擴展性
打包方式爲jar 存放服務接口
6、service模塊 發佈到dubbo 對外提供服務
非常重要:打包方式爲war 服務提供者 基於dubbo和zookeeper對外提供服務
注意類上使用註解: 特別注意是 dubbo包下的 @Service註解
import com.alibaba.dubbo.config.annotation.Service;
@Service(interfaceClass = CheckItemService.class)
需要配置文件
- dubbo.properties 存儲dubbo的連接信息
- applicationContext-tx.xml 事務管理 < !-- 注入事務管理器 提供數據源–> transactionManager
<!-- 事務管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--
開啓事務控制的註解支持
注意:此處必須加入proxy-target-class="true",
需要進行事務控制,會由Spring框架產生代理對象,
Dubbo需要將Service發佈爲服務,要求必須使用cglib創建代理對象。
-->
<tx:annotation-driven transaction-manager="transactionManager"
proxy-target-class="true"/>
- applicationContext-service.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:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--
classpath 和 classpath* 的區別
classpath 只會加載當前模塊中的配置文件
classpath* 不但會加載當前模塊的配置文件, 還可以加載 依賴的jar包中的同類型的配置文件
-->
<context:property-placeholder location="classpath*:*.properties"/>
<!--
1、開啓註解:配置掃描包,掃描帶註解的類
2、事務:事務管理羣、事務通知、切入點表達式
3、配置dubbo相關的信息
-->
<!-- 指定應用名稱 -->
<dubbo:application name="health_service_provider"/>
<!--指定暴露服務的端口,如果不指定默認爲20880-->
<dubbo:protocol name="dubbo" port="${dubbo.port}"/>
<!--指定服務註冊中心地址-->
<dubbo:registry address="${dubbo.zk.address}"/>
<!--批量掃描,發佈服務 掃描cn.ssm.fuxi.service包及其子包下的服務實現類-->
<dubbo:annotation package="cn.ssm.fuxi.service"/>
</beans>
- 還需要配置web.xml 注意路徑爲 webapp/WEB-INF/web.xml
服務提供者模塊 的web.xml主要配置的是 加載Spring容器
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!-- SSM + dubbo
服務的提供方:web.xml
1、創建listener :ContextLoaderListener Spring監聽器並加載配置文件
2、配置文件的位置和名稱
按照層來劃分配置文件作用:
dao: applicationContext-dao.xml
service: applicationContext-service.xml
-->
<!-- 加載spring容器 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:spring/applicationContext*.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
7、web dubbo服務的消費者
web模塊 dubbo服務的消費者 也還很重要
需要注意:使用 @Reference註解 注入 dubbo 服務 注意是alibaba包下的Reference
import com.alibaba.dubbo.config.annotation.Reference;
@Reference
private CheckItemService checkItemService;
- 需要dubbo.properties 配置文件 日誌文件
- 需要配置springmvc.xml文件 配置使用fastjson解析數據 解決post亂碼 指定dubbo地址 還可配置文件上傳組件
- 注意:批量掃描 controller包下的類
- 還需要配置web.xml 主要配置servlet SpringMVC的 DispatcherServlet
- 以及 < url-pattern>/</ url-pattern> 統一的訪問路徑
2.1 添加配置文件
-
DAO層配置文件配置詳情
-
Mybatis相關的配置文件
- 映射文件(Mapper代理規則) XXXMapper.xml
- 核心的配置文件(SqlMapConfig.xml Mybatis3之後此配置文件可以省略)
-
數據庫的配置信息(四大屬性) db.properties
-
Spring整合Mybatis的配置文件
-
名稱:application-XX.xml,applicationContext-XX.xml,spring-XX.xml
-
哪些配置?
-
加載數據庫的配置文件
-
數據源 DataSource,Spring IOC容器
-
Spring整合Mybatis, SqlSeessionFactory創建權交給Spring,是以單例的形式存在。
在整合包中,SqlSeessionFactoryBean 是Spring幫助我們創建的,需要注入的屬性:DataSource、加載核心配置文件、別名掃描、插件配置
-
Mapper 代理的包掃描 MapperScannerConfigurer
- Mapper代理
-
-
-
日誌 log4j.properties
-
-
Service配置文件 — 發佈服務
-
事務 application-XX.xml,applicationContext-tx.xml
-
包掃描 Spring相關注解(可省略)
-
Spring整合dubbo
- 服務的名稱(唯一)
- dubbo通訊協議 默認就是 dubbo協議,端口:20880
- 連接註冊中心的地址 Zookeeper,端口:2181
- @Service,掃描dubbo註解
-
日誌
-
web.xml
- 加載spring的配置文件
- 創建一個 ContextLoadListener 監聽容器
-
-
webmvc 配置文件
- SpringMVC 遠程掉用 service
- dubbo通訊協議 默認就是 dubbo協議,端口:20880
- 連接註冊中心的地址 Zookeeper,端口:2181
- 掃描包
- 視圖解析器(JSON) —> fastJson
- 文件上傳… 和mvc相關的一些功能的配置
- web.xml
- 配置前端控制器(DispatchServlet)
- 加載SpringMvc的配置文件
- SpringMVC 遠程掉用 service
-
打包爲war的工程模塊,添加 tomcat運行插件
<build> <plugins> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <configuration> <!-- 指定端口 --> <port>81</port> <!-- 請求路徑 --> <path>/</path> </configuration> </plugin> </plugins> </build>
2.2 代碼實現
2.2.1 服務提供方
需求:完成檢查項的CRUD操作
查詢所有
Mapper代理規範:
1) 接口所在的路徑和映射文件的路徑要完全一致
2) 接口的全類名和映射文件的名稱保持一致
3) 接口的方法名稱和映射文件的 statementID 保持一致
4) 接口的方法返回值類型和映射文件的 resultType 保持一致(resultMap) 【可選】
5) 接口的方法參數類型和映射文件的 paramType 保持一致 【可選】
根據ID查詢
/**
* 根據ID查詢
* @return
*/
@GetMapping("/{id}")
public Result findAll(@PathVariable("id") Integer id){
CheckItem checkItem = checkItemService.findOne(id);
return new Result(true,"查詢成功",checkItem);
}
新增
/**
* 增
* @param checkItem
* @return
*/
@PostMapping
public Result add(@RequestBody CheckItem checkItem){
checkItemService.add(checkItem);
return new Result(true,"添加成功");
}
修改
/**
* 修改
* @param id
* @param checkItem
* @return
*/
@PutMapping("/{id}")
public Result update(@PathVariable("id") Integer id,@RequestBody CheckItem checkItem){
checkItemService.update(id,checkItem);
return new Result(true,"更新成功");
}
刪除
/**
* 根據id刪除
* @param id
* @return
*/
@DeleteMapping("/{id}")
public Result delete(@PathVariable("id") Integer id){
checkItemService.delete(id);
return new Result(true,"刪除成功");
}
2.2.2 服務消費方
Controller永遠三件事
- 接收前端傳遞參數(對象、數組、Map、文件對象Multipartfile、包裝POJO) 【前端給我什麼我就要什麼】
- k=v&k=v form表單提交|地址欄get
- json
- /{id} restful風格API
- 調用Service,返回調用的結果
- 對結果再次封裝,並且響應給前端【前端要啥我給啥】
Linux 不要關閉防火牆,端口的放行
firewall-cmd --zone=public --add-port=2181/tcp --permanent 端口放行 2181
firewall-cmd --reload 立即生效
寫業務代碼的注意事項
Mybatis 新增數據返回id
兩種方式
- 1、第一種:
其中 keyProperty 表示 對象中的id屬性字段 keyColumn 表示表中列名 resultType結果類型 int order=“AFTER” 表示在SQl語句執行後執行
<selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER">
select last_insert_id();
</selectKey>
- 2、第二種:(推薦使用)
useGeneratedKeys 設置爲true 表示將新增的id 字段 自動賦值給對象即開始主鍵回寫 keyProperty 表示java對象屬性名 爲id keyColumn=“id” 表示表中列名 爲id
<insert id="add" parameterType="CheckItem" useGeneratedKeys="true" keyProperty="id" keyColumn="id">
</insert>
Mybatis # 與 $ 的區別
- 使用 $方式獲取值 (不推薦使用)
最終生成的SQL語句,查看控制檯,顯示如下:
Preparing: select * from user where username like '%王%'
我們不難發現, 該方式是通過拼接SQL字符串方式實現, 無法避免SQL注入的問題.
- 使用 # 方式獲取值
最終生成的SQL語句,查看控制檯,顯示如下:
Preparing: select * from user where username like ?
Parameters: %王%
該方式會對SQL語句進行預處理,從而防止SQL注入問題. 因此開發中使用 # 獲取比 $獲取要更加安全.
總結
1. #{} 是佔位符, 而${}是拼接SQL
# 方式:
reparing: select * from user where username like ?
Mybatis 會將 sql 中的#{}替換爲?號,在 sql 執行前會使用 PreparedStatement 的參數設置方法,按序給 sql 的?號佔位符設置參數值,比如 ps.setInt(0, parameterValue),#{item.name} 的取值方式爲使用反射從參數對象中獲取 item 對象的 name 屬性值,相當於 param.getItem().getName()。 注意 如果是取對象中的屬性值 直接用 #{屬性值即可} , #{item.name}這樣是 對象內部屬性是一個對象 取這個內部item對象的屬性值 再這樣寫。
$ 方式:
select * from user where username like '%王%'
2. ${} 存在SQL注入的風險
3. 當輸入參數類型爲普通數據類型(包含基本數據類型和string.)
#{} 變量名可以隨意寫
${} 變量名只能爲value
4. 當輸入參數爲POJO實體類型時.
#{} 是對象中的屬性名
${} 也是對象中的屬性名
5. ${}是 Properties 文件中的變量佔位符,它可以用於標籤屬性值和 sql 內部,屬於靜態文本替換,比如${driver}會被靜態替換爲com.mysql.jdbc.Driver。
Mybatis的< if></ if> 標籤內 關鍵字 and or 區分大小寫 不能寫大寫 且字段要判空還要同時判斷是否是空串
<if test="name != null and name !=''">
name = #{name},
</if>
使用Dubbo需要注意 所有需要走網絡的數據 都要實現序列化接口 serializable
使用PageHelper分頁插件 注意事項
在結果返回給前端之前 進行統一的封裝
Result類
/**
* 封裝返回結果
*/
public class Result implements Serializable{
private boolean flag;//執行結果,true爲執行成功 false爲執行失敗
private String message;//返回結果信息,主要用於頁面提示信息
private Object data;//返回數據
public Result() {
}
public Result(boolean flag, String message) {
super();
this.flag = flag;
this.message = message;
}
public Result(boolean flag, String message, Object data) {
this.flag = flag;
this.message = message;
this.data = data;
}
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
PageResult類 封裝分頁結果數據
/**
* 分頁結果封裝對象
*/
public class PageResult<T> implements Serializable{
private Long total;//總記錄數
private List rows;//當前頁結果
private Integer totalPage; //總頁數
public PageResult() {
}
public PageResult(Long total, List rows, Integer totalPage) {
this.total = total;
this.rows = rows;
this.totalPage = totalPage;
}
public Long getTotal() {
return total;
}
public void setTotal(Long total) {
this.total = total;
}
public List getRows() {
return rows;
}
public void setRows(List rows) {
this.rows = rows;
}
public Integer getTotalPage() {
return totalPage;
}
public void setTotalPage(Integer totalPage) {
this.totalPage = totalPage;
}
}
log4j日誌的使用
- 首先IDEA需要安裝 lombok 插件
- 需要引入依賴
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
- 在impl類上加註解 @Slf4j
使用
例:
if(id==null){
log.error("CheckItemServiceImpl update is error checkItem={} id is NULL",checkItem);
throw new RuntimeException("ID不能爲空");
}