摘要:是使用攔截器來自動幫我們完成中文亂碼的問題的。這是我的首頁當然了,基于注解和基于來開發,都是通過映射器適配器和視圖解析器的。能夠控制請求路徑和請求方式一個控制器寫多個業務方法到目前為止,我們都是一個控制器寫一個業務方法,這肯定是不合理的。
前言
本文主要是講解在Controller中的開發,主要的知識點有如下:
編碼過濾器
使用注解開發
注解@RequestMapping詳解
業務方法接收參數
字符串轉日期
重定向和轉發
返回JSON
SpringMVC過濾編碼器在SpringMVC的控制器中,如果沒有對編碼進行任何的操作,那么獲取到的中文數據是亂碼!
即使我們在handle()方法中,使用request對象設置編碼也不行!原因也非常簡單,我們SpringMVC接收參數是通過控制器中的無參構造方法,再經過handle()方法的object對象來得到具體的參數類型的。
Struts2是使用攔截器來自動幫我們完成中文亂碼的問題的。那么SpringMVC作為一個更加強大的框架,肯定也有對應的方法來幫我們完成中文亂碼問題!
值得注意的是:該過濾編碼器只能解決POST的亂碼問題!
我們只需要在web.xml配置文件中設置過濾編碼器就行了!
注解開發SpringMVCCharacterEncodingFilter org.springframework.web.filter.CharacterEncodingFilter encoding UTF-8 CharacterEncodingFilter /*
我們在快速入門的例子中使用的是XML配置的方式來使用SpringMVC的,SpringMVC也能夠支持注解?!緜€人非常喜歡注解的方式】
我們在使用Action的時候,要么繼承著AbstractCommandController類,要么顯示使用注解Controller接口。當我們使用了注解以后就不用顯示地繼承或實現任何類了!
開發流程使用@Controller這個注解,就表明這是一個SpringMVC的控制器!
@Controller public class HelloAction { }
當然了,現在Spring是不知道有這么一個注解的,因此我們需要在配置文件中配置掃描注解
值得注意的是:在配置掃描路徑的時候,后面不要加.*
不然掃描不了,我不知道學Struts2還是其他的地方時候,習慣加了.*,于是就搞了很久!
在控制器中寫業務方法
@Controller public class HelloAction { /** * * @RequestMapping 表示只要是/hello.action的請求,就交由該方法處理。當然了.action可以去掉 * @param model 它和ModelAndView類似,它這個Model就是把數據封裝到request對象中,我們就可以獲取出來 * @return 返回跳轉的頁面【真實路徑,就不用配置視圖解析器了】 * @throws Exception */ @RequestMapping(value="/hello.action") public String hello(Model model) throws Exception{ System.out.println("HelloAction::hello()"); model.addAttribute("message","你好"); return "/index.jsp"; } }
跳轉到index頁面,首頁得到對應的值。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>$Title$ 這是我的首頁
${message}
當然了,基于注解和基于XML來開發SpringMVC,都是通過映射器、適配器和視圖解析器的。 只是映射器、適配器略有不同。但是都是可以省略的!
更新:上邊的適配器和映射器只是Spring3.1版本之前使用的、3.1版本之后現在一般用以下的兩個
映射器: org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping 適配器: org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
當然了,這上面兩個配置也可以使用
@RequestMapping能夠控制請求路徑和請求方式!
一個控制器寫多個業務方法到目前為止,我們都是一個控制器寫一個業務方法,這肯定是不合理的。我們在Struts2中一個Action就對應多個業務方法了。那么我們在SpringMVC中又怎么寫呢???
其實我們可以推理出來,@RequestMapping就是用于配置哪個請求對應哪個業務方法的!
public @interface RequestMapping { String[] value() default {}; RequestMethod[] method() default {}; String[] params() default {}; String[] headers() default {}; }
當我們請求hello.action的時候,處理的業務方法是hello().....當我們請求bye.action的時候,處理的業務方法是bye()
@Controller public class HelloAction { /** * * @RequestMapping 表示只要是/hello.action的請求,就交由該方法處理。當然了.action可以去掉 * @param model 它和ModelAndView類似,它這個Model就是把數據封裝到request對象中,我們就可以獲取出來 * @return 返回跳轉的頁面【真實路徑,就不用配置視圖解析器了】 * @throws Exception */ @RequestMapping(value="/hello.action") public String hello(Model model) throws Exception{ System.out.println("HelloAction::hello()"); model.addAttribute("message","你好"); return "/index.jsp"; } @RequestMapping(value = "/bye.action") public String bye(Model model) throws Exception { model.addAttribute("message","再見"); return "/index.jsp"; } }分模塊開發
當然了,我們在Struts2常常使用namespace來進行分模塊開發,在SpringMVC中我們也可以這樣干,并且我們又是使用的是@RequestMapping這個注解!
只要把@RequestMapping這個注解寫到類上面去,就代表了分模塊。
@Controller //我們知道,如果是value屬性上的注解,我們可以把value省略掉的 @RequestMapping("/zhongfucheng") public class HelloAction { /** * @param model 它和ModelAndView類似,它這個Model就是把數據封裝到request對象中,我們就可以獲取出來 * @return 返回跳轉的頁面【真實路徑,就不用配置視圖解析器了】 * @throws Exception * @RequestMapping 表示只要是/hello.action的請求,就交由該方法處理。當然了.action可以去掉 */ @RequestMapping(value = "/hello.action") public String hello(Model model) throws Exception { System.out.println("HelloAction::hello()"); model.addAttribute("message", "你好"); return "/index.jsp"; } @RequestMapping(value = "/bye.action") public String bye(Model model) throws Exception { model.addAttribute("message", "再見"); return "/index.jsp"; } }
那么我們想要HelloAction該控制器處理我們的請求,訪問的地址要么是:http://localhost:8080/zhongfucheng/hello.action,或者要么是http://localhost:8080/zhongfucheng/bye.action
限定某個業務控制方法,只允許GET或POST請求方式訪問我們如果想要限定某個業務控制方法,只允許GET或POST請求方式訪問。還是通過@RequestMapping來實現。只要設定它的method屬性就行了!
@RequestMapping(value = "/bye.action",method = RequestMethod.POST) public String bye(Model model) throws Exception { model.addAttribute("message", "再見"); return "/index.jsp"; }
當我把業務方法的請求設置為POST以后,我想要通過GET方式來訪問該業務方法。就行不通了!
業務方法寫入傳統web參數我們的業務方法除了可以寫Model這個參數以外,如果有需要我們還可以寫request,response等傳統Servlet的參數。這是一樣可以使用的....
但是呢,我們并不建議使用傳統的web參數,因為會耦合
@RequestMapping(method=RequestMethod.POST,value="/register") public String registerMethod(HttpServletRequest request,HttpServletResponse response) throws Exception{ //獲取用戶名和薪水 String username = request.getParameter("username"); String salary = request.getParameter("salary"); System.out.println("用戶注冊-->" + username + ":" + salary); //綁定到session域對象中 request.getSession().setAttribute("username",username); request.getSession().setAttribute("salary",salary); //重定向/jsp/success.jsp頁面 //response.sendRedirect(request.getContextPath()+"/jsp/success.jsp"); //轉發/jsp/ok.jsp頁面 request.getRequestDispatcher("/jsp/ok.jsp").forward(request,response); //轉發(提倡) return "/jsp/success.jsp"; }
小細節:如果我們的返回值是返回一個真實路徑,而我們在程序中又使用了轉發或重定向。。。那么具體跳轉的位置就是按我們程序中跳轉的路徑為準!
業務方法收集參數我們在Struts2中收集web端帶過來的參數是在控制器中定義成員變量,該成員變量的名字與web端帶過來的名稱是要一致的...并且,給出該成員變量的set方法,那么Struts2的攔截器就會幫我們自動把web端帶過來的參數賦值給我們的成員變量....
那么在SpringMVC中是怎么收集參數的呢????我們SpringMVC是不可能跟Struts2一樣定義成員變量的,因為SpringMVC是單例的,而Struts2是多例的。因此SpringMVC是這樣干的:
業務方法寫上參數
參數的名稱要和web端帶過來的數據名稱要一致
接收普通參數如果是普通參數的話,我們直接在方法上寫上與web端帶過來名稱相同的參數就行了!
@RequestMapping(value = "/hello.action") public String hello(Model model, String username, int id) throws Exception { System.out.println("用戶名是:" + username); System.out.println("編號是:" + id); model.addAttribute("message", "你好"); return "/index.jsp"; }
效果:
接收JavaBean我們處理表單的參數,如果表單帶過來的數據較多,我們都是用JavaBean對其進行封裝的。那么我們在SpringMVC也是可以這么做的。
創建Javabean
javaBean屬性與表單帶過來的名稱相同
在業務方法上寫上Javabean的名稱
創建JavaBean,javaBean屬性與表單帶過來的名稱相同
public class User { private String id; private String username; public User() { } public User(String id, String username) { this.id = id; this.username = username; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } @Override public String toString() { return "User{" + "id="" + id + """ + ", username="" + username + """ + "}"; } }
在業務方法參數上寫入Javabean
@RequestMapping(value = "/hello.action") public String hello(Model model,User user) throws Exception { System.out.println(user); model.addAttribute("message", "你好"); return "/index.jsp"; }收集數組
收集數組和收集普通的參數是類似的,看了以下的代碼就懂了。
業務方法獲取參數
@RequestMapping(value = "/hello.action") public String hello(Model model,int[] hobby) throws Exception { for (int i : hobby) { System.out.println("喜歡運動的編號是:" + i); } model.addAttribute("message", "你好"); return "/index.jsp"; }
效果:
收集List我們在Spring的業務方法中是不可以用List
我們使用一個JavaBean把集合封裝起來,給出對應的set和get方法。那么我們在接收參數的時候,接收的是JavaBean
/** * 封裝多個Emp的對象 * @author AdminTC */ public class Bean { private ListempList = new ArrayList (); public Bean(){} public List getEmpList() { return empList; } public void setEmpList(List empList) { this.empList = empList; } }
業務方法接收JavaBean對象
/** * 批量添加員工 */ @RequestMapping(value="/addAll",method=RequestMethod.POST) public String addAll(Model model,Bean bean) throws Exception{ for(Emp emp:bean.getEmpList()){ System.out.println(emp.getUsername()+":"+emp.getSalary()); } model.addAttribute("message","批量增加員工成功"); return "/jsp/ok.jsp"; }
在JSP頁面直接寫上empList[下表].
其實這種方法看起來也沒有那么難理解,我們就是向上封裝了一層【與接收普通的JavaBean類似的】。
收集多個模型我們有可能在JSP頁面上即有User模型的數據要收集,又有Emp模型的數據要收集....并且User模型的屬性和Emp模型的屬性一模一樣....此時我們該怎么辦呢???
我們也是可以在User模型和Emp模型上向上抽象出一個Bean,該Bean有Emp和User對象
/** * 封裝User和Admin的對象 * @author AdminTC */ public class Bean { private User user; private Admin admin; public Bean(){} public User getUser() { return user; } public void setUser(User user) { this.user = user; } public Admin getAdmin() { return admin; } public void setAdmin(Admin admin) { this.admin = admin; } }
在JSP頁面收集的時候,給出對應的類型就行了。
字符串轉日期類型
我們在Struts2中,如果web端傳過來的字符串類型是yyyy-mm-dd hh:MM:ss這種類型的話,那么Struts2默認是可以自動解析成日期的,如果是別的字符串類型的話,Struts2是不能自動解析的。要么使用自定義轉換器來解析,要么就自己使用Java程序來解析....
而在SpringMVC中,即使是yyyy-mm-dd hh:MM:ss這種類型SpringMVC也是不能自動幫我們解析的。我們看如下的例子:
JSP傳遞關于日期格式的字符串給控制器...
User對象定義Date成員變量接收
public Date getDate() { return date; } public void setDate(Date date) { this.date = date; }
業務方法獲取Date值
@RequestMapping(value = "/hello.action") public String hello(Model model, User user) throws Exception { System.out.println(user.getUsername() + "的出生日期是:" + user.getDate()); model.addAttribute("message", "你好"); return "/index.jsp"; }
結果出問題了,SpringMVC不支持這種類型的參數:
現在問題就拋出來了,那我們要怎么解決呢????
SpringMVC給出類似于Struts2類型轉換器這么一個方法給我們使用:如果我們使用的是繼承AbstractCommandController類來進行開發的話,我們就可以重寫initBinder()方法了....
具體的實現是這樣子的:
@Override protected void initBinder(HttpServletRequest request,ServletRequestDataBinder binder) throws Exception { binder.registerCustomEditor(Date.class,new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"),true)); }
那我們現在用的是注解的方式來進行開發,是沒有重寫方法的。因此我們需要用到的是一個注解,表明我要重寫該方法!
@InitBinder protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception { binder.registerCustomEditor( Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true)); }
再次訪問:
值得注意的是:如果我們使用的是Oracle插入時間的話,那么我們在SQL語句就要寫TimeStrap時間戳插入進去,否則就行不通!
結果重定向和轉發我們一般做開發的時候,經常編輯完數據就返回到顯示列表中。我們在Struts2是使用配置文件進行重定向或轉發的:
而我們的SpringMVC就非常簡單了,只要在跳轉前寫上關鍵字就行了!
public String hello(Model model, User user) throws Exception { System.out.println(user.getUsername() + "的出生日期是:" + user.getDate()); model.addAttribute("message", user.getDate()); return "redirect:/index.jsp"; }
以此類推,如果是想要再次請求的話,那么我們只要寫上對應的請求路徑就行了!
@RequestMapping(value = "/hello.action") public String hello(Model model, User user) throws Exception { return "redirect:/bye.action"; } @RequestMapping("/bye.action") public String bye() throws Exception { System.out.println("我進來了bye方法"); return "/index.jsp"; }返回JSON文本
回顧一下Struts2返回JSON文本是怎么操作的:
導入jar包
要返回JSON文本的對象給出get方法
在配置文件中繼承json-default包
result標簽的返回值類型是json
那么我們在SpringMVC又怎么操作呢???
導入兩個JSON開發包
jackson-core-asl-1.9.11.jar
jackson-mapper-asl-1.9.11.jar
在要返回JSON的業務方法上給上注解:
@RequestMapping(value = "/hello.action") public @ResponseBody User hello() throws Exception { User user = new User("1", "zhongfucheng"); return user; }
配置JSON適配器
測試的JSP
測試:
Map測試:
@RequestMapping(value = "/hello.action") public @ResponseBody Map hello() throws Exception { Map map = new HashMap(); User user = new User("1", "zhongfucheng"); User user2 = new User("12", "zhongfucheng2"); map.put("total", user); map.put("rows", user2); return map; }
更新------------------------------------------------------------------
如果傳遞進來的數據就是JSON格式的話,我們我們需要使用到另外一個注解@RequestBody,將請求的json數據轉成java對象
總結使用注解的開發避免了繼承多余的類,并且非常簡潔高效。
想要中文不亂碼,僅僅設置request的編碼格式是不行的。因為SpringMVC是通過無參的構造器將數據進行封裝的。我們可以使用SpringMVC提供的過濾器來解決中文亂碼問題。
RequestMapping可以設置我們具體的訪問路徑,還可以分模塊開發。基于這么兩個原因,我們就可以在一個Action中寫多個業務方法了。
RequestMapping還能夠限制該請求方法是GET還是POST。
在我們的業務方法中,還可以使用傳統的request和response等對象,只不過如果不是非要使用的話,最好就別使用了。
對于SpringMVC自己幫我們封裝參數,也是需要使用與request帶過來的名稱是相同的。如果不相同的話,我們需要使用注解來幫我們解決的。
如果是需要封裝成集合,或者封裝多個Bean的話,那么我們后臺的JavaBean就需要再向上一層封裝,在業務方法上寫上Bean進行了。當然了,在web頁面上要指定對應Bean屬性的屬性。
字符串轉日期對象用到 @InitBinder注解來重寫方法。
返回JSON對象,我們就需要用到@ResponseBody注解,如果接收JSON數據封裝成JavaBean的話,我們就需要用到@RequestBody注解。隨后在配置文件上創建對應的bean即可。
如果文章有錯的地方歡迎指正,大家互相交流。習慣在微信看技術文章,想要獲取更多的Java資源的同學,可以關注微信公眾號:Java3y
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/68798.html
摘要:分發處理器將會掃描使用了該注解的類的方法,并檢測該方法是否使用了注解。的作用相當于,只不過按照自動注入。作用該注解用于將的方法返回的對象,通過適當的轉換為指定格式后,寫入到對象的數據區。用于注解層,在類上面注解。 原文地址 Controller 在SpringMVC中,控制器Controller負責處理由DispatcherServlet分發的請求,它把用戶請求的數據經過業務處理層處理...
摘要:概述用久了,深受其約定大于配置的便利性毒害之后,我想回歸到時代,看看開發模式中用戶是如何參與的。備注當然本文所使用的全是非注解的配置方法,即需要在中進行配置并且需要遵循各種實現原則。而更加通用主流的基于注解的配置方法將在后續文章中詳述。 showImg(https://segmentfault.com/img/remote/1460000015244684); 概述 用久了Sprin...
摘要:處理器是繼前端控制器的后端控制器,在的控制下對具體的用戶請求進行處理。由于涉及到具體的用戶業務請求,所以一般情況需要程序員根據業務需求開發。 1、mcv整體架構和流程 showImg(https://segmentfault.com/img/bV55Qq?w=860&h=406); 用戶發送請求至前端控制器 DispatcherServlet DispatcherServlet 收到...
摘要:分發處理器將會掃描使用了該注解的類的方法,并檢測該方法是否使用了注解。作用該注解用于將的方法返回的對象,通過適當的轉換為指定格式后,寫入到對象的數據區。用于注解層,在類上面注解。使用標記的參數。 1、@Controller 在SpringMVC 中,控制器Controller 負責處理由DispatcherServlet 分發的請求,它把用戶請求的數據經過業務處理層處理之后封裝成一個M...
摘要:開啟自動配置功能后文詳解這個注解,學過的同學應該對它不會陌生,就是掃描注解,默認是掃描當前類下的。簡單來說,這個注解可以幫助我們自動載入應用程序所需要的所有默認配置。簡單理解這二者掃描的對象是不一樣的。 前言 只有光頭才能變強。 文本已收錄至我的GitHub倉庫,歡迎Star:https://github.com/ZhongFuCheng3y/3y 回顧前面Spring的文章(以學習...
閱讀 3717·2021-10-11 10:59
閱讀 1301·2019-08-30 15:44
閱讀 3479·2019-08-29 16:39
閱讀 2888·2019-08-29 16:29
閱讀 1800·2019-08-29 15:24
閱讀 808·2019-08-29 15:05
閱讀 1264·2019-08-29 12:34
閱讀 2302·2019-08-29 12:19