Spring Boot/MVC

  • 代碼開發(fā)階段
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接口及前端交互
  • springMVC數(shù)據(jù)綁定
簡單綁定是將一個用戶界面元素(控件)的屬性綁定到一個類型(對象)實例上的某個屬性的方法兽埃。
// 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。
  • Spring Boot
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 的使用
@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ù)模式。(注意:通常不推薦這樣做)
  • Java中文件上傳下載
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)容,保存到本地
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末孕豹,一起剝皮案震驚了整個濱河市涩盾,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌励背,老刑警劉巖春霍,帶你破解...
    沈念sama閱讀 218,451評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異叶眉,居然都是意外死亡址儒,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評論 3 394
  • 文/潘曉璐 我一進店門衅疙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來莲趣,“玉大人,你說我怎么就攤上這事饱溢⌒。” “怎么了?”我有些...
    開封第一講書人閱讀 164,782評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長潘鲫。 經(jīng)常有香客問我翁逞,道長,這世上最難降的妖魔是什么溉仑? 我笑而不...
    開封第一講書人閱讀 58,709評論 1 294
  • 正文 為了忘掉前任挖函,我火速辦了婚禮,結(jié)果婚禮上彼念,老公的妹妹穿的比我還像新娘挪圾。我一直安慰自己,他們只是感情好逐沙,可當(dāng)我...
    茶點故事閱讀 67,733評論 6 392
  • 文/花漫 我一把揭開白布哲思。 她就那樣靜靜地躺著,像睡著了一般吩案。 火紅的嫁衣襯著肌膚如雪棚赔。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,578評論 1 305
  • 那天徘郭,我揣著相機與錄音靠益,去河邊找鬼。 笑死残揉,一個胖子當(dāng)著我的面吹牛胧后,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播抱环,決...
    沈念sama閱讀 40,320評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼壳快,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了镇草?” 一聲冷哼從身側(cè)響起眶痰,我...
    開封第一講書人閱讀 39,241評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎梯啤,沒想到半個月后竖伯,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,686評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡因宇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,878評論 3 336
  • 正文 我和宋清朗相戀三年七婴,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片察滑。...
    茶點故事閱讀 39,992評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡本姥,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出杭棵,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 35,715評論 5 346
  • 正文 年R本政府宣布魂爪,位于F島的核電站先舷,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏滓侍。R本人自食惡果不足惜蒋川,卻給世界環(huán)境...
    茶點故事閱讀 41,336評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望撩笆。 院中可真熱鬧捺球,春花似錦、人聲如沸夕冲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽歹鱼。三九已至泣栈,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間弥姻,已是汗流浹背南片。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留庭敦,地道東北人疼进。 一個月前我還...
    沈念sama閱讀 48,173評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像秧廉,于是被迫代替她去往敵國和親伞广。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,947評論 2 355