BeanUtils開發包的使用
- 2020 年 2 月 14 日
- 筆記
對內省技術有了一定的了解之後,我們就可以來學習一下BeanUtils開發包的使用了。
我們先假設一個情景,有一個JSP文件,如果要將該JSP文件中表單數據封裝到Servlet文件應該怎麼辦?此時<jsp:setProperty property="*"/>方法顯然就不奏效了,因為它是JSP文件特有的動作指令。當然,在ServletRqeuest接口中存在方法getParameterMap(),所以可以通過該方法得到表單數據的Map集合,然後利用內省技術將Map集合中的數據保存到bean對象對應的屬性中去。
顯然這是很麻煩的一件事情,但是也不用擔心,Apache組織開發了一套用於操作JavaBean的API,此時,就引出了我們今天的主題,BeanUtils開發包,它考慮到了很多實際開發中的應用場景,當然也就包括我上面提到的情景,那麼BeanUtils該如何使用呢?
首先要下載BeanUtils的jar包,Apache公司的很多項目都是有相互的依賴的,所以這時候需要下載兩個jar包,1、commons-beanutils 2、commons-logging beanutils依賴於logging的jar包。 大家可以下載我上傳的壓縮包,點擊下載,不過新版本的CSDN好像改不了下載積分了,本來是想免費分享的,系統默認設置為了5積分下載,沒有積分的小夥伴也可以自己去官網下載或者百度下載。 下載好了壓縮包後,解壓就會得到兩個壓縮包,分別解壓開。


將紅色方框內的兩個jar包複製到項目中去,接下來通過一個案例來入門使用一下BeanUtils開發包。 創建一個Person類
public class Person { private String name; private String city; private String hobby; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getHobby() { return hobby; } public void setHobby(String hobby) { this.hobby = hobby; } }
接下來新建demo.jsp文件
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <!-- 使用BeanUtils 將 form參數封裝到JavaBean 對象中 --> <form action="/demo/demoservlet" method="post"> 姓名:<input type="text" name="name"><br> 城市:<input type="text" name="city"><br> 愛好:<input type="text" name="hobby"><br> <input type="submit" value="提交"> </form> </body> </html>
然後創建DemoServlet.java文件
public class DemoServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8");//處理亂碼 //將form參數自動封裝到Person對象 Person person = new Person(); try { BeanUtils.populate(person, request.getParameterMap()); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } System.out.println(person.getName()); System.out.println(person.getCity()); System.out.println(person.getHobby()); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
運行一下該項目,對錶單進行如下輸入

點擊提交,控制台輸出如下信息

由此可以得知,表單中的數據被正確地保存到了bean對象中。該工具包的功能遠不止如此,我們改進一下該案例 將Person類作如下修改
public class Person { private String name; private String city; private String hobby; //添加age屬性 private int age; 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; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getHobby() { return hobby; } public void setHobby(String hobby) { this.hobby = hobby; } }
將demo.jsp作如下修改
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <!-- 使用BeanUtils 將 form參數封裝到JavaBean 對象中 --> <form action="/demo/demoservlet" method="post"> 姓名:<input type="text" name="name"><br> 城市:<input type="text" name="city"><br> 愛好:<input type="text" name="hobby"><br> <!-- 增加年齡輸入框 --> 年齡:<input type="text" name="age"><br> <input type="submit" value="提交"> </form> </body> </html>
對DemoServlet.java文件作如下修改
public class DemoServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8");//處理亂碼 //將form參數自動封裝到Person對象 Person person = new Person(); try { BeanUtils.populate(person, request.getParameterMap()); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } System.out.println(person.getName()); System.out.println(person.getCity()); System.out.println(person.getHobby()); //打印person對象的age屬性值 System.out.println(person.getAge()); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
重新運行一遍程序,對錶單進行輸入

控制台輸出信息為

會發現,即使Person類中存在數據類型不相同的屬性(即使在表單中輸入的年齡數據類型為String,卻依然可以存放入屬性類型為int的屬性age中),工具類仍然可以處理並且傳遞,是不是很good呢? 繼續升華一下我們的項目,在Person類中添加一個類型為Date的屬性birthday,並在demo.jsp文件中添加輸入生日的文本框,最後在DemoServlet.java文件中添加輸出birthday屬性的代碼。 對改進後的表單進行如下輸入

點擊提交按鈕後,網頁報錯了

報錯說明日期格式寫錯了,但是日期格式到底如何輸入呢?到這裡,就必須得明白封裝的原理,不然,接下來的代碼編寫將無法進行。 我們打開commons-beanutils文件夾,在apidocs目錄下有一個index.html文件,打開它,這就是工具包的文檔

點擊紅色方框進入查看,也許你一瞬間就明白了,裏面有各種數據格式的轉換器,所以為什麼String類型的age能夠轉換為int類型存入對象中,相信你一定明白了,它是通過IntegerConverter轉換器實現類型轉換的。 默認情況下,form表單中的String類型參數會封裝到JavaBean中的String類型屬性 當JavaBean中屬性類型與form表單提交的參數類型不一致時,就需要類型轉換器。 現在的目的就是將String類型的日期轉換為Date類型的日期。 會發現,在org.apache.commons.beanutils.converters包下雖然有DateConverter日期轉換器,但是文檔並沒有詳細說明它的用法和輸入日期的格式,既然如此,我們只能自定義一個日期轉換器來實現我們的目的。 通過文檔可以知道,所有的轉換器都實現了Converter接口,所以我們自定義轉換器也需要實現該接口。 編寫內部類MyDateConverter類並實現接口
class MyDateConverter implements Converter{ //需要將value數據轉換為c的類型 public Object convert(Class c, Object value) { String s = (String) value;//value代表的是用戶輸入的生日 DateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日"); try { Object result = dateFormat.parseObject(s);//將String解析為Date } catch (ParseException e) { e.printStackTrace(); } return null; } }
此時,自定義的日期轉換器就編寫完成了,然後,在調用populate方法前,應該註冊轉換器,所以整體DemoServlet.java文件作如下修改
public class DemoServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8");//處理亂碼 //將form參數自動封裝到Person對象 Person person = new Person(); //在封裝數據之前,註冊轉換器 ConvertUtils.register(new MyDateConverter(), Date.class);//第二個參數為想要轉換的數據類型 try { BeanUtils.populate(person, request.getParameterMap()); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } System.out.println(person.getName()); System.out.println(person.getCity()); System.out.println(person.getHobby()); System.out.println(person.getAge()); System.out.println(person.getBirtyday()); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } class MyDateConverter implements Converter{ //需要將value數據轉換為c的類型 public Object convert(Class c, Object value) { String s = (String) value;//value代表的是用戶輸入的生日 DateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日"); try { Object result = dateFormat.parseObject(s);//將String解析為Date return result; } catch (ParseException e) { e.printStackTrace(); } return null; } } }
對錶單進行輸入

控制台輸出如下

由此說明,自定義的日期轉換器實現了日期轉換,我們的目的已經達到。