Spring MVC 簡明教程

簡介

Spring MVC 屬於Spring Framework項目中的一部分。主要用於組建MVC結構的項目。比較相似於Struts的功能。並且Spring MVC對於目前比較流行的RESTful架構風格支持的也是比較好的。html

官方網站:http://projects.spring.io/spring-framework/前端

 

原理

DispatcherServlet類是spring mvc的核心控制器,負責分發和響應用戶請求。java

DispatcherServlet請求處理工做流程以下圖所示:web

一、用戶將request請求發送至前端控制器(Front controller)ajax

二、前端控制器將請求轉發至具體的業務控制器(Controller)spring

三、業務控制器建立業務邏輯實現(Service)和數據數據庫

四、業務控制器(Controller)將結果返回給前端控制器(Front controller)json

五、前端控制器(Front controller)選擇展現模板(View template)瀏覽器

六、最後將結果經過前端控制器(Front controller)返回給客戶安全

DispatcherServlet繼承於HttpServlet,因此它擁有HttpServlet全部特徵。

 

加載依賴

因爲本人慣用spring boot進行項目構建,因此配置默認都是spring boot的方式

只要在項目中依賴springframework的包就可使用Spring MVC

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.3.9.RELEASE</version>
    </dependency>
</dependencies>

若是你使用spring boot來搭建項目,那麼是不須要以上依賴的,由於springboot的依賴已經包含他了

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-autoconfigure</artifactId>
    <version>1.3.5.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>

 

DispatcherServlet攔截配置

DispatcherServlet的url-pattern默認狀況下爲「/」根路徑,全部的url請求都會被DispatcherServlet處理。可是咱們能夠對url-pattern進行配置。

在spring boot的配置文件application.properties中進行配置

#攔截全部以.do結尾的路徑
server.servlet-path=*.do

#攔截全部springmvc目錄下的路徑
server.servlet-path=/springmvc/*

這裏須要注意,項目中的RequestMapping請求路徑不能包含攔截內容。好比 攔截路徑爲「server.servlet-path=/springmvc/*「,RequestMapping爲「/index」,那麼請求路徑爲http://localhost:8090/springmvc/index

 

 

註解

 

@Controller

此註解聲明瞭一個Controller層的類,使用此註解的類會被識別爲一個控制器。

@Controller
public class StartController {

}

在此例子中咱們不用將類聲明爲一個bean,由於spring boot在初始化時使用了@ComponentScan註解進行自動掃描並注入。

 

@RestController

此註解聲明一個類爲Restful風格的控制器。其實就是@Controller和@ResponseBody兩個註解疊加的效果。

@RestController
public class StartController {

    @PostMapping(value = "/login1")
    public User login1(@RequestBody User user1) {
        User user = new User();
        user.setUsername(user1.getUsername());
        user.setPassword(user1.getPassword());
        return user;
    }

}
  • @RestController註釋的類中,全部的方法默認添加@ResponseBody,會將內容放在http主體中返回。

 

@RequestMapping

此註解聲明瞭一個可訪問的資源映射,url能夠經過RequestMapping配置的映射路徑來訪問這個方法。

參數:

value(默認)

訪問該資源的URI路徑。資源路徑支持通配符訪問。(如例5)

此參數能夠不寫則爲默認訪問。(如例1)

該參數能夠設置URI形式的入參,入參使用{}進行表示。在方法參數中使用@PathVariable能夠將URI參數映射給一個方法入參。(如例4)

method

指定http的提交類型。通常使用RequestMethod類來指定類型。

經常使用的基本上就是RequestMethod.GET和RequestMethod.POST。(如例二、3)

consumes

指定處理請求的提交內容類型(Content-Type),例如application/json, text/html;
produces

指定返回的內容類型,僅當request請求頭中的(Accept)類型中包含該指定類型才返回;(如例6)

在作接口時每每使用此參數指定接口出參數據結構類型。

params 指定request中必須包含某些參數值是,才讓該方法處理。
headers 指定request中必須包含某些指定的header值,才能讓該方法處理請求。

括號內只寫參數值,則表明此參數是默認參數的值。

例子: 

@RequestMapping("/home")
public class StartController {

    @RequestMapping
    public String index(Model model) {
        return "index";
    }

    @RequestMapping(value = "/login",method = RequestMethod.GET)
    public String login(Model model) {
        return "login";
    }

    @RequestMapping(value = "/login",method = RequestMethod.POST)
    public String loginPost(Model model) {
        return "login";
    }

    @RequestMapping(value = "/{parameter}",method = RequestMethod.GET)
    public String parameter(@PathVariable("parameter") String urlParameter, Model model) {
        return "login";
    }

    @RequestMapping(value = "/*/login",method = RequestMethod.GET)
    public String login(Model model) {
        return "login";
    }

    @RequestMapping(value = "/login1", method = RequestMethod.POST, produces = MediaTypes.JSON_UTF_8)
    public String login1(Model model) {
        return "login";
    }
}

 

  • RequestMapping能夠標識一個類或一個方法,在類上時表明這個類內全部資源都在該路徑下。在方法上時表明該方法的訪問路徑。如例2的路徑爲「/home/login」
  • RequestMapping有一些變種註解,如@GetMapping、@PostMapping等。此類註解省去了method參數。@GetMapping至關於@RequestMapping(method = RequestMethod.GET)

 

@PathVariable 

此註解用於獲取URI形式的參數,參數做爲路徑的一部分被傳遞過來。

參數:

value(默認)

URI形式參數的名稱。也就是@RequestMapping註解使用「{}」來標註的參數名稱。

此參數不寫,則要求方法入參名稱與URI參數名稱一致。(如例3)

括號內只寫參數值,則表明此參數是默認參數的值。(如例二)

例子: 

@RequestMapping(value = "/{parameter}")
 public String parameter(@PathVariable(value = "parameter") String urlParameter, Model model) {
     return "login";
 }

 @RequestMapping(value = "/{parameter}")
 public String parameter(@PathVariable("parameter") String urlParameter, Model model) {
     return "login";
 }

 @RequestMapping(value = "/{parameter}")
 public String parameter(@PathVariable String parameter, Model model) {
     return "login";
 }

 

@RequestParam

得到request請求參數並綁定到方法參數上,get請求時使用此註解獲取參數。

參數:

value(默認)

請求參數名稱。

此參數不寫,則要求方法入參名稱與請求參數名稱一致。(如例2)

required 是否必輸。默認狀況下是true必輸,若是但願那個參數爲非必輸就設置成false(如例3)

括號內只寫參數值,則表明此參數是默認參數的值。(如例1)

例子: 

//如下例子的url參數爲?username=andy&password=111111

    @GetMapping(value = "/login1")
    public String login1(@RequestParam("username") String username ,@RequestParam("password") String password) {
        return "login";
    }

    @GetMapping(value = "/login2")
    public String login2(@RequestParam String username ,@RequestParam String password) {
        return "login";
    }

    @GetMapping(value = "/login3")
    public String login3(@RequestParam String username ,@RequestParam(required=false) String password) {
        return "login";
    }

    @GetMapping(value = "/login4")
    public String login4(@RequestParam Map user) {
        return "login";
    }
  • @RequestParam的參數可使用map接收,url的入參名和值,會以鍵值對的形式存儲在map中(如例4)

 

@RequestHeader

獲取request頭信息。

參數:

value(默認)

請求頭參數名稱。

此參數不寫,則要求方法入參名稱與請求頭參數名稱一致。(如例2)

required 是否必輸。默認狀況下是true必輸,若是但願那個參數爲非必輸就設置成false(如例5)

括號內只寫參數值,則表明此參數是默認參數的值。(如例1)

例子: 

@GetMapping(value = "/login1")
    public String login1(@RequestHeader("Host") String host) {
        return "login";
    }

    @GetMapping(value = "/login2")
    public String login2(@RequestHeader String Host) {
        return "login";
    }

    @GetMapping(value = "/login3")
    public String login3(@RequestHeader("Accept-Encoding") List<String> encoding ) {
        return "login";
    }

    @GetMapping(value = "/login4")
    public String login4(@RequestHeader Map<String,String> header) {
        return "login";
    }

    @GetMapping(value = "/login5")
    public String login5(@RequestHeader(value = "Host",required=false) String host) {
        return "login";
    }
  • @RequestHeader可使用list接收一組用逗號分割的值(如例3)。如「gzip,deflate」 就會被list拆分接收。
  • @RequestHeader可使用Map來接收全部的頭信息,頭信息會以鍵值對的形式存儲在map中(如例4)。

 

@RequestBody

獲取request請求,http主體內的參數,post請求時使用此註解獲取參數。

參數:

required 是否必輸。默認狀況下是true必輸,若是但願那個參數爲非必輸就設置成false(如例2)

例子: 

@PostMapping(value = "/login1")
    public String login1(@RequestBody User user) {
        return "login";
    }

    @PostMapping(value = "/login2")
    public String login2(@RequestBody(required=false) User user) {
        return "login";
    }
  • @RequestBody將http主體中的數據轉換到入參對象中(如例1)。
  • http主體的形式由http Content Type定義。通常爲application/json或application/xml
  • @RequestBody入參接收對象中的屬性名要求與http主體中的變量名一致。如:User類定義了usernam和password兩個屬性,那麼json 形式的http body就應該寫成{"username":"myuser","password":"111111"}

 

@ResponseBody

將響應內容直接放在http主體中返回。一般的@Controller方法返回的是視圖名稱,並跳轉到這個視圖。

@PostMapping(value = "/login1")
    @ResponseBody
    public User login1(@RequestBody User user1) {
        User user = new User();
        user.setUsername(user1.getUsername());
        user.setPassword(user1.getPassword());
        return user;
    }
  • @ResponseBody常常用於ajax請求和接口方法。由於ajax請求和接口方法要求直接返回內容而不是跳轉到某一視圖。

 

@SessionAttributes(不經常使用)

用於獲取session中的參數。

@SessionAttributes做用於類的時候,會在方法執行結束時將對應名字的model內容存儲到session中。(如例1)

@SessionAttributes做用於參數的時候,會取出session中對應名字的內容,賦值給當前的參數。(如例2)

參數:

value(默認)

session中的參數名稱。

此參數不寫,則要求方法入參名稱與請求參數名稱一致。(如例3)

括號內只寫參數值,則表明此參數是默認參數的值。(如例2)

例子: 

@Controller
@RequestMapping(value = "/home")
@SessionAttributes("username")
public class StartController {
    @PostMapping(value = "/login1")
    public String login1(HttpSession httpSession,Model model) {
        model.addAttribute("username","woshicanshu");
        return "login";
    }

    @PostMapping(value = "/login2")
    public String login2(@SessionAttribute("user") User user, HttpSession httpSession) {
        return "login";
    }

    @PostMapping(value = "/login3")
    public String login3(@SessionAttribute User user, HttpSession httpSession) {
        return "login";
    }
}

 

@RequestAttribute(不經常使用)

獲取request的參數。@RequestAttribute做用於參數的時候,會取出request中對應名字的內容,賦值給當前的方法入參。

參數:

value(默認)

request中的參數名稱。

此參數不寫,則要求方法入參名稱與請求參數名稱一致。(如例2)

括號內只寫參數值,則表明此參數是默認參數的值。(如例1)

例子: 

@PostMapping(value = "/login1")
    public String login1(@RequestAttribute("username") String username,HttpRequest request) {
        return "login";
    }

    @PostMapping(value = "/login2")
    public String login2(@RequestAttribute String username,HttpRequest request) {
        return "login";
    }

 

@ModelAttribute(不經常使用)

將參數保存到Model模型中,供視圖頁面使用。

  • 做用於參數時表示這個參數保存到model中。(如例1)
  • 做用於方法時表示將這個方法的出參保存到model中,此方法會在執行任意一個@RequestMapping以前執行一次。(如例2)

參數:

value(默認)

model中的參數名稱。

括號內只寫參數值,則表明此參數是默認參數的值。(如例1)

例子: 

//本例請求參數爲 ?username=pltx

    @GetMapping(value = "/login1")
    public String login1(@ModelAttribute("username") String username,Model model) {
        return "login";
    }

    @ModelAttribute("password")
    public String login2(String username) {
        return "000000";
    }

 

@RequestPart(不經常使用)

用於獲取使用multipart/form-data格式傳遞的http請求的請求體,一般用於獲取上傳文件。

 

@Autowired

用於在類中注入bean。

@Autowired
private Activity2CompanyDao activity2CompanyDao;

 

@Repository

用於聲明此類爲一個數據庫持久化類(DAO層)。

@Repository
public class Activity2ConsumerCouponDaoImpl implements Activity2ConsumerCouponDaoCustom{

}

 

@Service

用於聲明一個業務層的類。

@Service
public class Activity2ConsumerService {

}

 

 

Controller層

Controller層是項目的轉向控制層,主要負責接收請求、轉發請求到業務層(service)進行處理、將處理結果進行響應、控制頁面跳轉等職責。

須要注意涉及到業務邏輯的代碼儘可能不要在Controller進行編寫,將業務邏輯合理的封裝在service層對項目的結構和複用性都是很是有益的。

Controller層主要經常使用的註解有@Controller、@RequestMapping、@Autowired、@RequestParam、@RequestHeader、@RequestBody、@ResponseBody等。

 

默認綁定的參數

Controller層的方法入參能夠得到默認綁定的類的實例,這實例咱們能夠經過形參的聲明直接使用。其中主要包括HttpServletRequest、HttpservletResponse、HTTPSession、Model、ModelMap以及他們的衍生類。

HttpServletRequest

此參數能夠得到一個HttpServletRequest實例。

@RequestMapping("/unauthorized")
public String unauthorized(HttpServletRequest request, HttpServletResponse response) {

}

 

HttpServletResponse

此參數能夠得到一個HttpservletResponse實例。

@RequestMapping("/unauthorized")
public String unauthorized(HttpServletRequest request, HttpServletResponse response) {

}

 

HTTPSession

此參數能夠得到一個HTTPSession實例。

@RequestMapping("/unauthorized")
public String unauthorized(HTTPSession session) {

}

 

Model/ModelMap

Model用於將模型數據傳遞到展現層,保存在Model中的數據能夠直接在頁面使用獲取。

@RequestMapping(value = "/list", method = RequestMethod.GET)
public String list(String name, Integer openType, Model model) {

    model.addAttribute("name", name);
    model.addAttribute("openType", openType);

    return "/activity2_company/list";
}

 

RedirectAttributes

model的Attribute參數傳遞的聲明週期爲一次請求。因此若是方法採用重定向到其餘資源則Attribute保存的參數將會丟失,在頁面是沒法獲取的。若是想要在重定向後在頁面獲取參數則須要使用  RedirectAttributes進行保存。

下面的例子在login頁面仍然能夠拿到message參數值。

@RequestMapping(value = "/logout", method = RequestMethod.GET)
public String logout(RedirectAttributes redirectAttributes) {
    redirectAttributes.addFlashAttribute("message", "您已安全退出");
    return "redirect:login"; 
}

@RequestMapping(value = "/login", method = RequestMethod.GET)
public String loginInput() {
   
    return "login";
}

RedirectAttributes中有兩個添加參數的方法addAttribute和addFlashAttribute ,addAttribute參數會被放在url中進行傳遞,因此長度和類型會受到限制。而addFlashAttribute 參數放在flashmap內部對象中傳遞,對於長度和類型沒有限制。

 

在重定向的方法中若是想要拿到,前面方法存入的addAttribute參數,只要在重定向方法入參加入這個參數便可

@GetMapping(value = "/login")
    public String login(RedirectAttributes redirectAttributes) {
        redirectAttributes.addAttribute("username","andy");
        return "redirect:login1";
    }

    @GetMapping(value = "/login1")
    public String login1(String username) {
        System.out.println(username);
        return "login";
    }

在重定向的方法中若是想要拿到,前面方法存入的addFlashAttribute參數,則須要使用@ModelAttribute註解

@GetMapping(value = "/login")
    public String login(RedirectAttributes redirectAttributes) {
        redirectAttributes.addFlashAttribute("username","andy");
        return "redirect:login1";
    }

    @GetMapping(value = "/login1")
    public String login1(@ModelAttribute("username") String username) {
        System.out.println(username);
        return "login";
    }

 

響應方式

返回到頁面

Controller方法的出參直接寫視圖名稱,則表明執行結束後調轉到此視圖。(加ResponseBody不行)

以下例將訪問login頁面

@GetMapping(value = "/login")
public String login() {
    return "login";
}

 

跳轉到其餘Controller

Controller方法的出參能夠經過增長forward和redirect前綴的方式進行轉發或重定向到,其餘Controller。

@GetMapping(value = "/login")
    public String login() {
        return "login";
    }

    @GetMapping(value = "/login1")
    public String login1() {
        return "redirect:login";
    }

    @GetMapping(value = "/login2")
    public String login2() {
        return "forward:login";
    }

強調一下forward和redirect區別。forward是服務器轉發,瀏覽器地址不變,服務器將請求的新地址內容返回給劉藍鰭。redirect是瀏覽器重定向,瀏覽器地址改變,服務器告訴瀏覽器要訪問新的地址後瀏覽器從新訪問新地址。

 

輸出到頁面

咱們可使用HttpServletResponse對象將內容直接輸出到頁面

@GetMapping(value = "/login")
    public void login(HttpServletResponse response) {
        try {
            response.setHeader("Content-type", "text/html;charset=UTF-8");
            response.getWriter().println("<h1>我是標題</h1>");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
相關文章
相關標籤/搜索