SpringMVC
Spring集成web環境
集成步驟
-
匯入相關的坐標,spring的和web的
<dependencies> <!-- spring--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.3.6</version> </dependency> <dependency> <!-- mysql--> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.32</version> </dependency> <!-- 資料源一:c3p0--> <dependency> <groupId>c3p0</groupId> <artifactId>c3p0</artifactId> <version>0.9.1.2</version> </dependency> <!-- 資料源二:druid--> <dependency> <groupId>cn.6tail</groupId> <artifactId>nlf-mini-plugin-druid</artifactId> <version>1.0.0</version> </dependency> <!-- junit--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!-- spring集成junit坐標:--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.3.6</version> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter</artifactId> <version>RELEASE</version> <scope>compile</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>RELEASE</version> <scope>compile</scope> </dependency> <!-- servlet--> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> </dependency> <!-- jsp--> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>2.3.3</version> </dependency> </dependencies>
-
spring相關配置
-
添加一個web包,用來寫javaweb
-
在web.xml配置相關類
-
配置tomcat,部署專案運行
ApplicationContext應用背景關系的獲取方式
之前每次我們都是通過new的方式創建的應用背景關系,這樣的弊端是在大專案中組態檔會加載多次,應用背景關系被創建多次,繁瑣且不節省資源
所以我們運用監聽器來只創建一次,所有的用這一個容器,所以:
創建一個實作ServletContext監聽器的類:
public class ContextLoader implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
//將這個應用背景關系物件存盤在servletContext域中
ServletContext servletContext = sce.getServletContext();
servletContext.setAttribute("app",app);
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
}
web層中:
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = req.getServletContext();
ApplicationContext app = (ApplicationContext) servletContext.getAttribute("app");
UserService userService= app.getBean(UserService.class);
userService.save();
}
web.xml:
<!--配置監聽器-->
<listener>
<listener-class>com.myspring.listener.ContextLoader</listener-class>
</listener>
<!--配置全域引數-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
Spring提供的獲得應用背景關系的工具
沒錯,上面又白寫了,,,
上面的不用手動實作,Spring提供了一個監聽器ContextLoaderListener就是對該功能的封裝
我們只需要做兩件事:
-
在web.xml中配置ContextLoaderListener監聽器(需要先匯入spring-web坐標)
pom.xml:
<!-- spring-web--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>5.3.6</version> </dependency>
web.xml:
<!--配置監聽器--> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
-
通過WebApplicationCintextUtils(一個客戶端工具)獲得應用背景關系物件ApplicationContext
web層中:
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ServletContext servletContext = req.getServletContext(); //關鍵 WebApplicationContext app = WebApplicationContextUtils.getWebApplicationContext(servletContext); UserService userService= app.getBean(UserService.class); userService.save(); }
SpringMVC簡介
-
SpringMVC 是一種基于 Java 的實作 MVC 設計模型的請求驅動型別的輕量級 Web 框架,屬于SpringFrameWork的后續產品,已經融合在 Spring Web Flow 中, SpringMVC已經成為目前最主流的MVC框架之一,
-
SpringMVC的作用:作為前端控制器,控制請求的共有行為,在傳統的JavaEE技術中,只使用Servlet作為控制器,當每個功能都需要一個servlet程式相似功能也無法分開封裝,另外,傳統的開發模式也存在其它使用不便利的做法,
SpringMVC解決了V-C互動的問題,即V(View:視圖)和C(Controller:控制器)之間的互動問題,具體表現在:用戶可以通過視圖將請求資料提交給服務器端的控制器,而控制器可以接收到相關資料后進行處理,最終,給予客戶端某個視圖,使得客戶端得到回應結果,當然springMVC作為控制器還是需要servlet
SpringMVC開發步驟
-
匯入SpringMVC
<!-- spring-mvc--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.3.6</version> </dependency>
-
配置servlet在web.xml
<servlet> <servlet-name>DispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 告訴控制層組態檔位置--> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-mvc.xml</param-value> </init-param> <!-- 服務器加載時就啟動本servlet--> <!-- 當值為0或者大于0時,表示容器在應用啟動時就加載這個servlet;--> <!-- 當是一個負數時或者沒有指定時,則指示容器在該servlet被選擇時才加載,--> <!-- 正數的值越小,啟動該servlet的優先級越高,--> <load-on-startup></load-on-startup> </servlet> <servlet-mapping> <servlet-name>DispatcherServlet</servlet-name> <!-- 所有請求都會經過servlet--> <url-pattern>/</url-pattern> </servlet-mapping>
-
撰寫pojo(controller)
-
將controller使用注解(@Controller)配置到Spring容器中
//表明是一個控制類bean實體 @Controller public class UserController { //地址映射,當跳轉/quick,訪問此方法 @RequestMapping("/quick") public String save(){ System.out.println("Controller save running"); // 要跳轉的視圖 return "success.jsp"; } }
-
配置組件掃描(配置到Spring-mvc.xml:springmvc的組態檔,需要自己在resources創建)
<!-- 組件掃描:掃描controller--> <context:component-scan base-package="com.myspring.controller"/>
-
發送請求測驗
流程:
SpringMVC的組件決議
SpringMVC內部執行流程
SpringMVC注解決議
@RequestMapping(""):地址映射
常用引數:value:就是路徑
? method:可以指定請求方式,值為列舉方式在RequestMethod
? params:指定請求引數條件,例如:
?
@Controller
@RequestMapping("/user")
public class UserController {
//當地址為localhost:8080/user/quick時訪問該方法
@RequestMapping("/quick")
public String save(){
System.out.println("Controller save running");
// 要跳轉的視圖:localhost:8080/user/success.jsp,當前的前一級目錄下的該資源(/success.jsp.就代表當前web應用下,即webapp目錄下)
return "success.jsp";
}
}
SpringMVC配置決議
在上面的代碼中,最后我們renturn了jsp頁面
return "success.jsp";
//實際上本句為
return "forword:success.jsp";
//forword在本處意思為轉發(不改變url地址訪問資源),默認為forword
return "redirect:/success.jsp"
//redirect:代表重定向
我們還可以在springmvc中配置視圖決議器,來避免寫前綴后綴
<!-- 配置視圖決議器-->
<bean id="viewResolver" >
<!-- 前綴-->
<property name="prefix" value="https://www.cnblogs.com/jsp/"></property>
<!-- 后綴-->
<property name="suffix" value="https://www.cnblogs.com/rainaftersummert/archive/2023/07/12/.jsp"></property>
</bean>
這樣一來我們可以這樣寫:
return "/success"
代表:/jsp/success.jsp
總結:
SpringMVC的資料回應
SpringMVC的資料回應方式:
- 頁面跳轉
- 直接回傳字串
- 通過ModelAndView物件回傳
- 回寫資料
- 直接回傳字串
- 回傳物件或集合
頁面跳轉
-
直接回傳字串:此種方式會將回傳的字串與視圖決議器的前后綴拼接后跳轉:不多說,上面例子就是用的這種
-
通過ModelAndView物件回傳
@RequestMapping("/quick2") public ModelAndView save2(){ ModelAndView modelAndView = new ModelAndView(); // 設定模型資料:可以在jsp中通過el運算式獲得 modelAndView.addObject("username","lihua"); // 設定視圖名稱 modelAndView.setViewName("index.jsp"); return modelAndView; } //這種也可以,和上面一樣只不過是springmvc為你注入了一個bean實體 @RequestMapping("/quick2") public ModelAndView save2(ModelAndView modelAndView){ // 設定模型資料 modelAndView.addObject("username","lihua"); // 設定視圖名稱 modelAndView.setViewName("index"); return modelAndView; }
? 回傳字串的形式也可以傳遞引數:
@RequestMapping("/quick")
public String save(Model model){
model.addAttribute("username","lihua");
// 要跳轉的視圖
return "success";
}
//另外代替Model,還可以傳HttpServletRequest等作為引數
? 在index.jsp中
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
這個isELIgnored="false"表示el運算式可用
<html>
<body>
<h2>Hello World!${username}</h2>
</body>
</html>
回寫資料
-
直接回傳字串
在web階段我們需要回寫字串直接response.getWriter().print("hello world"),在Controller直接通過引數注入response物件,但是還有更加簡單的方法:回傳字串
@RequestMapping("/quick") //告知springmvc回傳的用于回寫資料的字串,不要進行頁面跳轉 @ResponseBody public String save(HttpServletResponse response){ return "helloworld"; }
-
回傳物件或集合
當我們需要傳遞一個物件或者集合時,可以先轉成json格式字串再return
@RequestMapping("/quick") // 還是要寫這個注解,因為還是回傳的字串資料 @ResponseBody public String save(HttpServletResponse response) throws IOException { UserServiceImpl userService = new UserServiceImpl(); userService.setAge(10); userService.setName("lihua"); // 使用json轉換工具將物件轉換為json格式字串再回傳 ObjectMapper objectMapper = new ObjectMapper(); String string = objectMapper.writeValueAsString(userService); return string;
需要匯入的json轉換工具坐標:
<!-- json工具核心--> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.11.4</version> </dependency> <!-- json資料系結--> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.11.4</version> </dependency> <!-- json和注解相關--> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.11.4</version> </dependency>
? springmvc不需要我們自己來轉json字串,有更加簡便的方式:
? 回傳物件和集合,
? 首先需要我們在spring組態檔中進行一些配置(配置處理器映射器):
<!-- 配置處理器映射器-->
<bean >
<property name="messageConverters">
<list>
<bean >
</bean>
</list>
</property>
</bean>
? 控制類中:
@RequestMapping("/quick")
// 還是要寫這個注解,因為還是回傳的字串資料
@ResponseBody
public UserServiceImpl save(HttpServletResponse response) throws IOException {
UserServiceImpl userService = new UserServiceImpl();
userService.setAge(10);
userService.setName("lihua");
return userService;
}
配置太麻煩了,可以通過mvc的注解驅動代替上述配置,沒錯,又又又有更加簡便的操作:
在springmvc的組態檔中:
<!-- mvc注解驅動-->
<mvc:annotation-driven/>
注意:注解驅動對應的命名空間必須是
xmlns:mvc="http://www.springframework.org/schema/mvc"
其他兩個不行
SpringMVC獲取請求資料
獲取請求引數
-
獲取基本型別引數:直接通過引數獲得:
@RequestMapping("/quick") @ResponseBody public void save(String username,int age) throws IOException { System.out.println(username); System.out.println(age); }
url:
結果:
-
獲得pojo型別引數:pojo引數的屬性名和請求引數的name一致,引數值會自動映射匹配
@Controller public class UserController { private int age; private String name; // 還需要getter和setter public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } @RequestMapping("/quick") @ResponseBody public void save(UserController userController) throws IOException { System.out.println(userController.getAge()); System.out.println(userController.getName()); } }
輸入與結果:
- 獲得陣列型別引數:和基本資料型別完全一致,函式引數和請求的引數一致就可以
-
獲得集合型別引數:需要被包裝到一個pojo類中才可以
public class VO { public List<String> getStringList() { return stringList; } public void setStringList(List<String> stringList) { this.stringList = stringList; } private List<String> stringList; }
@RequestMapping("/quick")
@ResponseBody
public void save(VO vo) throws IOException {
System.out.println(vo.getStringList());
}
當請求為Ajax可以通過指定contenttype為json格式,通過注解直接獲取集合資料:
ajax:
@RequestMapping("/quick")
@ResponseBody
public void save(@RequestBody List<String> userList) throws IOException {
System.out.println(userList);
}
開放靜態資源;
無法訪問的js檔案等靜態資源是配置
<!-- 開放資源的訪問權限:請求為mapping時開放location的靜態資源-->
<mvc:resources mapping="js/**" location="/js/"></mvc:resources>
這樣也可以:在springmvc找不到資源是交給tomcat處理
<mvc:default-servlet-handler/>
解決低版本tomcat請求資料為中文亂碼問題
如果tomcat版本較低,當配置post請求時,資料為中文會出現亂碼,所以我們通過配置過濾器來解決
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
引數系結注解@requestParam
當請求的引數名稱和controller方法引數不一致時,就需要通過@requestParam注解顯示
@RequestMapping("/quick")
@ResponseBody
//當我在url中輸入的是name
public void save(@RequestParam("name") String username) throws IOException {
System.out.println(username);
}
@requestParam注解的引數:
獲得Restful風格的引數
Restful是一種軟體架構風格、設計風格,而不是標準,只是提供一組設計原則和約束條件,主要用于客戶端和服務器互動類的軟體,基于這個風格設計的軟體可以更加簡潔,更有層次等
HTTP協議中四個表示操作方式的動詞:
具體實體:
自定義型別轉換器
SpringMVC實際上已經具備了一些常用的型別轉換器,例如客戶端提交的字串被轉換成int型進行引數設定
但是可能并不完全滿足我們的需求,所以我可以自定義型別轉換器:
開發步驟:
-
定義轉換器實作Converter介面
public class DataConverter implements Converter<String,Date> { public Date convert(String dateStr) { //將日期字串轉換為日期物件 SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); Date date = null; try { date = format.parse(dateStr); } catch (ParseException e) { e.printStackTrace(); } return date; } }
-
在組態檔中宣告轉換器
<!-- 宣告這個轉換器--> <bean id="ConversionService" > <property name="converters"> <list> <bean ></bean> </list> </property> </bean>
-
在中參考轉換器
<!-- 配置處理器映射器--> <mvc:annotation-driven conversion-service="ConversionService"/>
結果:
獲得Servlet的相關API
前面說過,直接在相關方法引數位置注入,就不在贅述
獲取請求頭
-
使用@RequestHeader
@RequestMapping("/quick") @ResponseBody // 將請求頭的user-agent一行賦值給引數 public void save(@RequestHeader(value = "https://www.cnblogs.com/rainaftersummert/archive/2023/07/12/User-Agent") String userAgent) throws IOException { System.out.println(userAgent); }
-
@CookieValue獲得Cookie的值:
@RequestMapping("/quick")
@ResponseBody
// 通過cookie的id獲得cookie的值
public void save(@CookieValue(value = "https://www.cnblogs.com/rainaftersummert/archive/2023/07/12/JSESSIONID") String cookie) throws IOException {
System.out.println(cookie);
}
檔案上傳
檔案上傳客戶端要求:
單檔案上傳步驟:
-
匯入fileupload和io坐標
<!-- fileupload--> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.1</version> </dependency> <!-- commons-io--> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.5</version> </dependency>
-
組態檔上傳決議器
<bean id="multipartResolver" > <!-- 上傳檔案總大小最大--> <property name="maxUploadSize" value="https://www.cnblogs.com/rainaftersummert/archive/2023/07/12/5242800"/> <!-- 上傳單個檔案大小最大--> <property name="maxUploadSizePerFile" value="https://www.cnblogs.com/rainaftersummert/archive/2023/07/12/5242800"/> <!-- 生成檔案編碼型別--> <property name="defaultEncoding" value="https://www.cnblogs.com/rainaftersummert/archive/2023/07/12/UTF-8"/> </bean>
-
撰寫檔案上傳代碼
@RequestMapping("/quick") @ResponseBody //引數名必須與上傳檔案表單的各項name相同 public void save(String username, MultipartFile uploadFile) throws IOException { // 獲得檔案名稱 String originalFilename = uploadFile.getOriginalFilename(); // 保存檔案到 uploadFile.transferTo(new File("D:\\"+originalFilename));
我在創建multipartResolver
多檔案上傳同理:
@RequestMapping("/quick")
@ResponseBody
//引數名必須與上傳檔案表單的各項name相同
public void save(String username, MultipartFile uploadFile1,MultipartFile uploadFile2) throws IOException {
// 獲得檔案名稱
String originalFilename = uploadFile1.getOriginalFilename();
String originalFilename2 = uploadFile2.getOriginalFilename();
// 保存檔案到
uploadFile2.transferTo(new File("D:\\"+originalFilename));
uploadFile1.transferTo(new File("D:\\"+originalFilename));
}
當然也可以把引數換成一個陣列
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/557103.html
標籤:其他
上一篇:用Python撰寫網頁自動答題工具,滿分輕松到手,你就是全班最靚的仔!
下一篇:返回列表