MVC框架二

1趟大、IOC與DI

IOC和DI分別是控制反轉(zhuǎn)和依賴(lài)注入门粪。所謂的控制反轉(zhuǎn)就是將對(duì)象的創(chuàng)建權(quán)交給框架,而依賴(lài)注入則是利用框架設(shè)置屬性毛雇。在MCV框架中嫉称,有兩種方式進(jìn)行IOC和DI:

1、xml的bean配置

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/page"/>
    <property name="suffix" value=".jsp"/>
</bean>

bean在之前已經(jīng)解釋過(guò)灵疮,class后面是完整類(lèi)名织阅,name是屬性名,value是屬性值震捣。

2荔棉、包掃描和四類(lèi)注解

在開(kāi)始使用mvc框架的時(shí)候,我配置了包掃描路徑為controller包蒿赢,現(xiàn)在將這個(gè)掃描路徑擴(kuò)大

<!--包掃描-->
<context:component-scan base-package="com.fan.*"/>

在mvc中润樱,有四種注解可以幫助我們創(chuàng)建對(duì)象

//dao層用注解
@Repository
//service層注解
@Service
//controller層注解
@Controller
//不是經(jīng)典三層的其它類(lèi)注解
@Component

目前來(lái)說(shuō),這四種注解的作用是一樣的羡棵,但是不保證以后mvc框架針對(duì)不同注解有另外的優(yōu)化壹若,所以這里遵循約定,嚴(yán)格按照所屬層級(jí)使用注解晾腔。

3舌稀、使用框架創(chuàng)建的實(shí)例

為了驗(yàn)證1和2方法是否真的創(chuàng)建了一個(gè)實(shí)例,編寫(xiě)一個(gè)類(lèi):

package com.fan.dao;

import cn.hutool.db.Db;
import com.fan.entity.ForumUser;
import org.springframework.stereotype.Repository;

import java.sql.SQLException;
import java.util.List;

@Repository
public class UserDao {
    public UserService(){
        System.out.println("UserDao正在實(shí)例化灼擂!");
    }
    //根據(jù)賬戶(hù)和密碼獲取用戶(hù)(登錄驗(yàn)證)
    public ForumUser selectUserByAccountAndPassword(String account, String password) {
        String sql = "select * from forumUser where account= ?  and password=?;" ; 
        try {
            List<ForumUser> list = Db.use().query(sql, ForumUser.class,account,password);
            if (list.size() > 0) {
                return list.get(0);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

當(dāng)服務(wù)器啟動(dòng)用戶(hù)登錄時(shí)壁查,控制臺(tái)會(huì)輸出UserDao正在實(shí)例化!利用bean配置會(huì)得到同樣的結(jié)果剔应。那么如何將框架實(shí)例化出來(lái)的對(duì)象取出來(lái)使用呢睡腿?這里有一個(gè)注解@Autowiredprivate语御,將這個(gè)注解寫(xiě)在對(duì)象上,這個(gè)對(duì)象的引用就會(huì)指向框架創(chuàng)建出來(lái)的對(duì)象的引用席怪。

//此時(shí)应闯,這個(gè)userDao已經(jīng)不是空引用了,可以調(diào)用方法和屬性
@Autowired
private UserDao userDao;

2挂捻、經(jīng)典三層結(jié)構(gòu)

在mvc框架中碉纺,有一個(gè)經(jīng)典的三層結(jié)構(gòu):控制層->業(yè)務(wù)層->數(shù)據(jù)層,這三層結(jié)構(gòu)理論上是一層一層往下調(diào)用的刻撒,不允許跨層調(diào)用骨田。也就是說(shuō),控制層調(diào)用業(yè)務(wù)層的對(duì)象声怔,業(yè)務(wù)層調(diào)用數(shù)據(jù)層态贤,但是控制層不能夠直接調(diào)用數(shù)據(jù)層。而且控制層不能夠出現(xiàn)數(shù)據(jù)相關(guān)的操作醋火,這里主要是指與數(shù)據(jù)庫(kù)相關(guān)的語(yǔ)句悠汽,這些操作應(yīng)該被放在數(shù)據(jù)層。就拿用戶(hù)登錄驗(yàn)證舉例:

//dao層-數(shù)據(jù)層
package com.fan.dao;

import cn.hutool.db.Db;
import com.fan.entity.ForumUser;
import org.springframework.stereotype.Repository;

import java.sql.SQLException;
import java.util.List;

//IOC
@Repository
public class UserDao {
    //根據(jù)賬戶(hù)和密碼獲取用戶(hù)(登錄驗(yàn)證)
    public ForumUser selectUserByAccountAndPassword(String account, String password) {
        String sql = "select * from forumUser where account= ?  and password=?;" ; 
        try {
            List<ForumUser> list = Db.use().query(sql, ForumUser.class,account,password);
            if (list.size() > 0) {
                return list.get(0);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

//service層-服務(wù)層
package com.fan.service;

import com.fan.dao.UserDao;
import com.fan.entity.ForumUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

//IOC
@Service
public class UserService {
    //取出框架里的UserDao實(shí)例
    @Autowired
    private UserDao userDao;

    //根據(jù)賬戶(hù)和密碼獲取用戶(hù)(登錄驗(yàn)證)
    public ForumUser selectUserByAccountAndPassword(String account, String password) {
        //service層調(diào)用dao層方法
        return userDao.selectUserByAccountAndPassword(account, password);
    }
}

//控制層-controller層
package com.fan.controller;

import com.fan.entity.ForumUser;
import com.fan.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;

//IOC
@Controller
@RequestMapping("/login")
public class LoginController {
    //取出實(shí)例
    @Autowired
    private UserService userService;

    @RequestMapping("/verify")
    public ModelAndView login(String account, String password, HttpServletRequest req) {
        ModelAndView mav = new ModelAndView("/error");
        //調(diào)用service層方法
        ForumUser forumUser = userService.selectUserByAccountAndPassword(account, password);
        try {
            if (forumUser != null) {
                req.getSession().setAttribute("ForumUser", account);
                mav = new ModelAndView("/loginsuccess");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return mav;
    }
}

當(dāng)然芥驳,三層分層并不是必須遵守的柿冲,逐層調(diào)用也不是強(qiáng)制規(guī)范,一切設(shè)計(jì)都要根據(jù)實(shí)際情況來(lái)晚树。

3姻采、線(xiàn)程安全

關(guān)于多線(xiàn)程的安全問(wèn)題,之前已經(jīng)討論過(guò)爵憎,這里簡(jiǎn)單說(shuō)一下慨亲。在mvc框架中,IOC創(chuàng)建對(duì)象使用的是單例模式宝鼓,所以打上注解或者bean配置的類(lèi)刑棵,最終只會(huì)生成一個(gè)實(shí)例。對(duì)于非靜態(tài)的方法來(lái)說(shuō)愚铡,如果每個(gè)線(xiàn)程都能生成各自的實(shí)例蛉签,那么線(xiàn)程就是安全的,如果是共用一個(gè)實(shí)例沥寥,也就是框架生成的單例碍舍,那么就有可能出現(xiàn)線(xiàn)程安全問(wèn)題。對(duì)于這種情況可以使用棧封閉邑雅、鎖和ThreadLocale封閉片橡。靜態(tài)方法本身也是線(xiàn)程安全的,只要不去操作外部的靜態(tài)變量淮野,那么就可以在多線(xiàn)程中直接使用捧书。

4吹泡、Service層與Dao層的分工

現(xiàn)有一論壇,要求用戶(hù)可以刪除自己的帖子经瓷,并在刪除帖子時(shí)要將對(duì)應(yīng)跟帖一并刪除爆哑。帖子和跟帖分別在兩張表中,跟帖表中有用戶(hù)uid和帖子pid舆吮。在PostDao和CommentDao分別寫(xiě)根據(jù)帖子pid刪除內(nèi)容的方法

@Autowired
private JdbcTemplate jdbcTemplate;
//CommentDao層根據(jù)帖子id刪除對(duì)應(yīng)評(píng)論
    public void deleteCommentByPid(int pid) {
        String sql = "delete from cmt where pid=?";
        jdbcTemplate.update(sql, pid);
    }
//PostDao層根據(jù)帖子id刪除用戶(hù)帖子
    public void deletePostById(int id) {
        String sql="delete from post where id=?";
        jdbcTemplate.update(sql,id);
    }

刪除帖子并附帶刪除其回帖屬于帖子的業(yè)務(wù)揭朝,所以在PostService對(duì)這兩個(gè)Dao進(jìn)行調(diào)用

    @Autowired
    private PostDao postDao;
    @Autowired
    private CommentDao commentDao;
//事務(wù)管理
    @Autowired
    private TransactionTemplate trans;
//根據(jù)帖子pid刪除帖子和該帖子的評(píng)論
    public int deletePostById(int pid) {
        int success = 0;
        trans.execute(new TransactionCallback<>() {
            @Override
            public Object doInTransaction(TransactionStatus transactionStatus) {
                postDao.deletePostById(pid);
                commentDao.deleteCommentByPid(pid);
                return 1;
            }
        });
        success = 1;
        return success;
    }

在這里即體現(xiàn)出框架分層的作用,對(duì)于不同的數(shù)據(jù)操作色冀,只需要組合調(diào)用dao層方法就可以實(shí)現(xiàn)業(yè)務(wù)萝勤,業(yè)務(wù)越復(fù)雜就越能體現(xiàn)出分層的好處,與此同時(shí)在controller層呐伞,對(duì)service的調(diào)用還可以進(jìn)一步優(yōu)化

@Autowired private PostService postService;

@RequestMapping("/deletePost")
    public void deletePostById(int pid, int uid, HttpServletResponse resp, HttpSession session) throws IOException {
        //從session域中取出論壇用戶(hù)數(shù)據(jù),將登陸用戶(hù)id與發(fā)帖喲用戶(hù)id比對(duì)慎式,只有兩者一直才可以刪帖
        int aUid = session.getAttribute("ForumUser")).getId();
        int success = 0;
        if (aUid == uid) {
            success = postService.deletePostById(pid);
        }
        resp.getWriter().print(success);
    }
}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末伶氢,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子瘪吏,更是在濱河造成了極大的恐慌癣防,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,607評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件掌眠,死亡現(xiàn)場(chǎng)離奇詭異蕾盯,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)蓝丙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)级遭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人渺尘,你說(shuō)我怎么就攤上這事挫鸽。” “怎么了鸥跟?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,960評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵丢郊,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我医咨,道長(zhǎng)枫匾,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,750評(píng)論 1 294
  • 正文 為了忘掉前任拟淮,我火速辦了婚禮干茉,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘惩歉。我一直安慰自己等脂,他們只是感情好俏蛮,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,764評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著上遥,像睡著了一般搏屑。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上粉楚,一...
    開(kāi)封第一講書(shū)人閱讀 51,604評(píng)論 1 305
  • 那天辣恋,我揣著相機(jī)與錄音,去河邊找鬼模软。 笑死伟骨,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的燃异。 我是一名探鬼主播携狭,決...
    沈念sama閱讀 40,347評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼回俐!你這毒婦竟也來(lái)了逛腿?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,253評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤仅颇,失蹤者是張志新(化名)和其女友劉穎单默,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體忘瓦,經(jīng)...
    沈念sama閱讀 45,702評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡搁廓,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,893評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了耕皮。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片境蜕。...
    茶點(diǎn)故事閱讀 40,015評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖明场,靈堂內(nèi)的尸體忽然破棺而出汽摹,到底是詐尸還是另有隱情,我是刑警寧澤苦锨,帶...
    沈念sama閱讀 35,734評(píng)論 5 346
  • 正文 年R本政府宣布逼泣,位于F島的核電站,受9級(jí)特大地震影響舟舒,放射性物質(zhì)發(fā)生泄漏拉庶。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,352評(píng)論 3 330
  • 文/蒙蒙 一秃励、第九天 我趴在偏房一處隱蔽的房頂上張望氏仗。 院中可真熱鬧,春花似錦、人聲如沸皆尔。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,934評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)慷蠕。三九已至珊拼,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間流炕,已是汗流浹背澎现。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,052評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留每辟,地道東北人剑辫。 一個(gè)月前我還...
    沈念sama閱讀 48,216評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像渠欺,于是被迫代替她去往敵國(guó)和親妹蔽。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,969評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容