1. DAO設(shè)計編碼
DAO層(數(shù)據(jù)訪問層)工作:接口設(shè)計+SQL編寫旬渠。
好處:代碼和收起來的分離邦马,方便review盗忱。
DAO拼接等邏輯在service層完成法竞。
數(shù)據(jù)庫的表設(shè)計、DAO的接口(執(zhí)行sql語句坐漏、獲取操作結(jié)果封裝信息苫幢、返回操作結(jié)果)、
Mybatis如何實現(xiàn)DAO
注:DAO層實現(xiàn)的關(guān)鍵在于得到能與數(shù)據(jù)庫交互图张、能執(zhí)行sql語句的對象锋拖,mybatis就是提供這樣一個對象:SqlSession
SqlSession(即一次與數(shù)據(jù)庫交互的會話)的作用:
1. 向sql語句傳入?yún)?shù)
2. 執(zhí)行sql語句
3. 獲取執(zhí)行sql語句的結(jié)果
4. 事務(wù)的控制
2. Service設(shè)計編碼
接口設(shè)計以及編碼實現(xiàn)诈悍、Spring管理Service、在Service方案去標注這個方法是一個事物操作
3. Web設(shè)計編碼
Restful接口及前端交互
簡單綁定是將一個用戶界面元素(控件)的屬性綁定到一個類型(對象)實例上的某個屬性的方法兽埃。
// http://localhost:8080/array.do?name=Tom&name=Lucy&name=Jim
//輸出:Tom Lucy Jim
@RequestMapping(value = "array.do")
@ResponseBody
public String array(String[] name) {
StringBuilder sbf = new StringBuilder ();
for(String item : name) {
sbf.append(item).append(" ");
}
return sbf.toString();
}
//綁定實體類對象
// http://localhost:8080/object.do?name=Tom&age=10
// 輸出:User{ name:'Tom', age:10}
@RequestMapping(value = "object.do")
@ResponseBody
public String object(User user) {
return user.toString();
}
//多層級的數(shù)據(jù)綁定
// http://localhost:8080/object.do?name=Tom&age=10&contactInfo.phone=10086
//輸出:User{name='Tom', age=10, contactInfo=ContactInfo{phone='10086', address='null'}}
//同屬性的多對象
// http://localhost:8080/object.do?user.name=Tom&admin.name=Lucy&age=10
//輸出:User{name='Tom', age=10, contactInfo=null} Admin{name='Lucy', age=10}
@RequestMapping(value = "object.do")
@ResponseBody
public String object(User user,Admin admin) {
return user.toString()+" "+admin.toString();
}
@InitBinder("user")
public void initUser(WebDataBinder binder) {
binder.setFieldDefaultPrefix("user.");
}
@InitBinder("admin")
public void initAdmin(WebDataBinder binder) {
binder.setFieldDefaultPrefix("admin.");
}
//Map的數(shù)據(jù)綁定
// http:localhost:8080/map.do?users[x].name=Tom$users[x].age=10
@RequestMapping(value = "map.do")
@ResponseBody
public String map(UserMapForm userMapForm) {
return userMapForm.toString();
}
//Json的數(shù)據(jù)綁定
{
"name": "jim",
"age": 16,
"userInfo": {
"address": "北京",
"phone": "1000"
}
}
@RequestMapping(value = "json.do")
@ResponseBody
public String json(@RequestBody User user) {
return user.toString();
}
springMVC的強大功能:
注解映射驅(qū)動:通過RequestMapping去映射URL侥钳,進而綁定到方法上,怎樣去傳遞數(shù)據(jù)柄错,
甚至是訪問cookie的數(shù)據(jù)舷夺,以及怎樣決定返回類型是json還是普通的jsp。
ec與idea區(qū)別
workspace - project
project - module
idea屬性配置:
resources文件下建application.yml
server:
port: 8080
context-path: /girl
cupSize: B
age: 18
//配置中套配置
content: "cupSize: ${cupSize}, age: ${age}"
// htttp:127.0.0.1:8080/girl/hello
@RestController
public class HelloController {
@Value("${cupSize}") // @Value配置內(nèi)容注入
private String cupSize;
@Value("${age}")
private Integer age;
@Value("${content}")
private String content;
@RequestMapping(value = "/hello", method = RequestmMethod.GET)
public String say() {
return content; 輸出: cupSize:B, age:18
//return cupSize + age; 輸出B18
//return "Hello Spring Boot!";
}
}
//上面一個一個獲取女生的屬性太麻煩售貌,需要一個一個的添加注解
application.yml配置:
server:
port给猾; 8080
girl:
cupSize: B
age: 18
//新建實體類GirlProperties
@Component
@ConfigurationProperties(prefix = "girl")
public class GirlProperties {
private String cupSize;
private Integer age;
public String getCupSize() {
return cupSize;
}
public void setCupSize(String cupSize) {
this.cupSize = cupSize;
}
}
//使用
@RestController
public class HelloController {
@Autowired
private GirlProperties girlProperties;
@RequestMapping(value = "/hello", method = RequestmMethod.GET)
//@RequestMapping(value = {"/hello", "/hi"}, method = RequestmMethod.GET) 這樣訪問/hello或/hi就一樣了
public String say() {
return girlProperties.getCupSize();
}
}
@Controller 處理http請求
@RestController Spring4之后新加的注解,原來返回json需要@ResponseBody配合@Controller
@RequestMapping 配置url映射
@PathVariable 獲取url中的數(shù)據(jù)
@RequestParam 獲取請求參數(shù)的值
@GetMapping 組合注解
例:
@RestController
@RequestMapping("/hello")
public class HelloController {
//@RequestMapping(value = "/say", method = RequestmMethod.GET) 這個太長趁矾,可以使用組合注解:@GetMapping
//@GetMapping(value = "/say')
@RequestMapping(value = "/say", method = RequestmMethod.GET)
// http://127.0.0.1:8080/hello/say?id=111
public String say(@RequestParam("id") Integer Id) {
return "id:" + Id;
}
// 可以設(shè)置默認值耙册,即使不傳參也不會報錯
public String say(@RequestParam(value = "id", required = false, defaultValue = "0") Integer Id) {
return "id:" + Id; //不穿參數(shù)默認會輸出0
}
@RequestMapping(value = "/say/{id}", method = RequestmMethod.GET)
// http://127.0.0.1:8080/hello/say/111
public String say(@PathVariable("id") Integer Id) {
return "id:" + Id;
}
}
數(shù)據(jù)庫操作
Spring-Data-Jpa(操作數(shù)據(jù)庫非常簡單,甚至不用寫sql語句)
JPA(Java Persistence API)定義了一系列對象持久化的標準毫捣,目前實現(xiàn)這一規(guī)范的產(chǎn)品有Hibernate详拙、TopLink等。
application.yml配置:
spring;
profiles:
active: dev
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/dbgirl
username: root
password: 123456
jpa:
hibernate:
ddl-auto: create // create如存在相同的表蔓同,會先刪掉再重新創(chuàng)建愛
show-sql: true
- AOP統(tǒng)一處理請求日志 Spring兩大核心原理(AOP饶辙、IOC)
AOP是一種編程范式,與語言無關(guān)斑粱,是一種程序設(shè)計思想
面向切面(AOP)Aspect Oriented Programming
面向?qū)ο螅∣OP)Object Oriented Programming
面向過程(POP)Procedure Oriented Programming
淺談面向過程和面向?qū)ο? 比如描述下雨了弃揽,我打開雨傘
面向過程(強調(diào)流程和規(guī)劃):假如下雨了,我打開了雨傘
面向?qū)ο螅簩嵗粋€天氣的對象则北,然后給這個對象賦予一個下雨的動作
實例一個我的對象矿微,然后賦予一個打傘的動作(這些動作可以稱之為方法)
其實就是換了個角度看世界,換個姿勢處理問題尚揣。
AOP 是將通用邏輯從業(yè)務(wù)邏輯中分離出來
使用AOP第一步:再pom.xml中添加注解:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
第二步往常的做法是在啟動類上添加一個注解涌矢,但是AOP就不用這樣做。
第三步創(chuàng)建處理文件Javaclass-HttpAspect快骗,要添加注解以引入到Spring容器中
@Aspect
@Component
public class HttpAspect {
//.. 表示只要是girlList這個方法里的任何參數(shù)娜庇,都會被攔截
// GirlController.*(..) 這樣會攔截所有的
//@Before注解會在方法執(zhí)行之前執(zhí)行
@Before("execution(public * com.imooc.controller.GirlController.girlList(..))")
public void log() {
System.out.println(11111);
}
@After("execution(public * com.imooc.controller.GirlController.girlList(..))")
public void doAfter() {
System.out.println(22222);
}
上面代碼等價于:
//spring下的日志框架
private final static Logger logger = LoggerFactory.getLogger(HttpAspect.class);
@Pointcut("execution(public * com.imooc.controller.GirlController.*(..))"")
public void log() {
}
@Before("log()")
public void doBefore() {
logger.info("11111");
}
@After("log()")
public void doAfter() {
logger.info("22222");
}
}
spring MVC 攔截器
什么是攔截器?
攔截器是指通過統(tǒng)一攔截從瀏覽器發(fā)往服務(wù)器的請求來完成功能的增強方篮。
在web.xml中配置過濾器filter:
<filter>
<filter-name>encoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param> // 啟動時的配置參數(shù)
<param-name>encoding</param-name>
<param-value>utf8</param-value>
</init-param>
</filter>
<filter-mapping>
<param-name>encoding</param-name>
<url-pattern>*</url-pattern> // 所有的請求都會經(jīng)過過濾器
</filter-mapping>
springMVC可以通過配置過濾器來解決亂碼問題名秀,攔截器的工作原理和過濾器非常相似。
攔截器的實現(xiàn):
1. 編寫攔截器類實現(xiàn)HandlerInterceptor接口
public class TestInterceptor implements HandlerInterceptor{
..默認實現(xiàn)的攔截器方法..
}
2. 將攔截器注冊到SpringMVC框架中
在springMVC默認的配置文件viewSpace-servlet.xml中注冊
<mvc:interceptors>
<bean class="com.imooc.test.interceptor.TestInterceptor"></bean>
</mvc:interceptors>
3. 配置攔截器的攔截規(guī)則
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path:"/viewAll.form"/>// 配置攔截的路徑(可通過*藕溅?正則來靈活配置路徑)
<bean class="com.imooc.test.interceptor.TestInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
攔截器方法介紹:
public void afterCompletion (...){
//請求結(jié)束后調(diào)用的方法匕得,用于資源的銷毀
}
public void postHandle (...){
//可以通過其中ModleAndView參數(shù)來改變顯示的視圖,或修改發(fā)往視圖的方法
arg3.setViewName("/hello2.jsp");
}
public boolean preHandle (HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
//返回值:表示我們是否需要將當(dāng)前的請求攔截下來
//false:請求將被終止 true:請求會被繼續(xù)運行
// Object arg2 表示的是被攔截的請求的目標對象
// 如不在web.xml中配置過濾器蜈垮,可以在此處用攔截器解決亂碼問題
arg0.setCharacterEncoding("utf-8");
// 對用戶是否登錄進行判斷
if (arg0.getSession().getAttribute("user") == null) {
//如果用戶沒有登錄耗跛,就終止請求裕照,并發(fā)送到登錄頁面
arg0.getRequestDispatcher("/login.jsp").forward(arg0, arg1);
return false;
}
retutn true;
}
攔截器的使用場景:
使用原則:處理所有請求的共同問題
1. 解決亂碼問題
2. 解決權(quán)限驗證問題
附注:
攔截器和過濾器:
① 攔截器是基于java的反射機制的,而過濾器是基于函數(shù)回調(diào)调塌。
② 攔截器不依賴與servlet容器晋南,過濾器依賴于servlet容器。
③ 攔截器只能對action請求起作用羔砾,而過濾器則可以對幾乎所有的請求起作用负间。
④ 攔截器可以訪問action上下文、值棧里的對象姜凄,而過濾器不能訪問政溃。
⑤ 在action的生命周期中,攔截器可以多次被調(diào)用态秧,而過濾器只能在容器初始化時被調(diào)用一次董虱。
⑥ 攔截器可以獲取IOC容器中的各個bean,而過濾器就不行申鱼,這點很重要愤诱,在攔截器里注入一個service,可以調(diào)用業(yè)務(wù)邏輯捐友。
Hibernate
什么是ORM淫半?
ORM(Object/Relationship Mapping):對象/關(guān)系映射
利用面向?qū)ο笏枷刖帉懙臄?shù)據(jù)庫應(yīng)用程序最終都是把對象信息報訊在關(guān)系型數(shù)據(jù)庫中,于是需要編寫很多和底層數(shù)據(jù)庫
相關(guān)的SQL語句匣砖。這與面向?qū)ο笏枷敫窀癫蝗耄?寫SQL語句有什么不好嗎科吭?
1. 不同的數(shù)據(jù)庫使用的SQL語法不同。比如:PL/SQL與T/SQL
2. 同樣的功能在不同的數(shù)據(jù)庫中有不同的實現(xiàn)方式猴鲫。比如分頁SQL
3. 程序過分依賴SQL對程序的移植及擴展对人,維護等帶來很大的麻煩。
需要一種可行的ORM框架技術(shù):Hibernate
Hibernate是Java領(lǐng)域的一款開源的ORM框架技術(shù)拂共,對JDBC進行了非常輕量級的對象封裝规伐。
閑話:其他主流的ORM框架技術(shù):
1. MyBatis:前身就是著名的iBatis
2. Toplink:后被Oracle收購,并重新包裝為Oracle AS TopLink
3. EJB:本身就是JAVAEE的規(guī)范匣缘,較笨重。
閑話2:JavaBeans實體類設(shè)計原則:
1. 公有的類
2. 提供公有的不帶參數(shù)的默認的構(gòu)造方法
3. 屬性私有
4. 屬性setter/getter封裝
------------------------------------------------------------------------------------
hibernate.cfg.xml常用配置:
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<property name="hbm2ddl.auto">create|update|....</property>//慎用O侍摹<〕!
hibernate.show_sql:是否把Hibernate運行時的SQL語句輸出到控制臺豁陆,編碼階段便于測試
hibernate.format_sql:輸出到控制臺的SQL語句是否進行排版柑爸,便于閱讀。建議設(shè)置為true
hbm2ddl.auto:可以幫助由java代碼生成數(shù)據(jù)庫腳本盒音,進而生成具體的表結(jié)構(gòu)表鳍。create|update|create-drop|validate
create:若表存在馅而,則先刪除表再重新創(chuàng)建
hibernate.default_schema:默認的數(shù)據(jù)庫
hibernate.dialect:配置Hibernate數(shù)據(jù)庫方言,Hibernate可針對特殊的數(shù)據(jù)庫進行優(yōu)化
注意:hibernate的前綴可省略譬圣,即hibernate.dialect等同于dialect瓮恭。
create table studenrs (
SID integer not null,
SNAME varchar(255),
GENDER varchar(255),
BIRTHDAY datetime,
ADDRESS varchar(255),
primary key (SID)
)
insert into studenrs (
(SNAME, GENDER, BIRTHDAY, ADDRESS, SID)
values(?, ?, ?, ?, ?)
)
編寫第一個Hibernate例子:
1. 創(chuàng)建hibernate的配置文件
2. 創(chuàng)建持久化類
3. 創(chuàng)建對象-關(guān)系映射文件
4. 通過hibernate API編寫訪問數(shù)據(jù)庫的代碼
附Hibernate的執(zhí)行流程:
創(chuàng)建配置文件Configuration -> Hibernate.cfg.xml
創(chuàng)建SessionFactory -> User.hbm.xml(創(chuàng)建和銷毀都相當(dāng)耗費資源,通常一個系統(tǒng)內(nèi)一個數(shù)據(jù)庫只創(chuàng)建一個)
Session -> 執(zhí)行save|delete|update|get
-> 開始事務(wù)Transation
-> tx.commit() session.close() 結(jié)束
transaction簡介:
Hibernate對數(shù)據(jù)的操作都是封裝在事務(wù)中厘熟,并且默認是非自動提交的方式屯蹦。所以用session保存對象時,如果不開啟事務(wù)绳姨,并且手工提交事務(wù)登澜,對象并不會真正保存在數(shù)據(jù)庫中
如果想讓Hibernate想jdbc那樣自動提交事務(wù),必須調(diào)用session對象的doWork()方法飘庄,獲得jdbc的connection后脑蠕,設(shè)置其為自動提交事務(wù)模式。(注意:通常不推薦這樣做)
1. 需要通過HttpServletResponse.setContentType方法設(shè)置Content-Type頭字段的值跪削,為瀏覽器無法使用某種方式或激活某個程序來處理的MIME類型谴仙,例如:"application/octet-stream"或"application/x-msdownload"等
2.需要通過HttpServletResponse.setHeader方法設(shè)置Content-Disposition頭的值為"attachment; filename=文件名"。
3.讀取下載文件切揭,調(diào)用HttpServletResponse.getOutputStream方法返回的ServletOutStream對象來向客戶端寫入附件文件內(nèi)容狞甚。
文件上傳后臺實現(xiàn)步驟
1. 獲取request當(dāng)中的流信息,保存到臨時文件
2. 從臨時文件當(dāng)中得到長傳的文件名廓旬,及文件內(nèi)容起止位置
3. 根據(jù)文件起止位置哼审,讀取上傳文件內(nèi)容,保存到本地