Controller接收各種形式的傳參:
RequestMapping()包含三部分信息:
表單傳參:
1、表單action請求
1:參數名稱和順序都要和表單字段名稱一致,直接接收(適合字段較少的)
<from id="viewForm" action="view/first"> <input id="roleName" type="text" name="roleName"/> <input id="roleNum" type="text" name="roleNum"/> <input type="submit" value="提交"/> </from> |
@RequestMapping("/first") public String findName(String roleName,String roleNum){ System.out.println(roleName); System.out.println(roleNum); return "index.jsp"; } |
2:表單中多個字段和一個POJO中屬性名稱完全對應,則可以對象入參,也不需要注解
@RequestMapping("/add") public String addUser(User user){ System.out.println(user.getName()); return "index.jsp"; } |
3:使用RequestParam注解,表單中的變量名和controller接收中的變量名不一致!
<from id="viewForm" action="view/first"> <input id="roleName" type="text" name="roleName"/> <input id="roleNum" type="text" name="roleNum"/> <input type="submit" value="提交"/> </from> |
@RequestMapping("/first") public String findName(@RequestParam("roleName")String roleName,String roleNum){ System.out.println(roleName); System.out.println(roleNum); return "index.jsp"; } |
或者寫成@RequestParam(value="roleName",required=false)
2、表單序列化ajax請求
JS代碼:
$("#commit").click(function(){ alert("jingru ajax2"); var param = $("#commit").serialize(); $.ajax({ url:"json", data:param, type:"post", dataType:"json", success:function(result){ alert(result.msg1); $("#josnview").text(result.msg1); }, error:function(){ alert("huidiao失敗"); } }); }); |
Html代碼:
<from id="viewForm"> <input id="roleName" type="text" name="roleName"/> <input id="roleNum" type="text" name="roleNum"/> <input id="commit" type="button" value="提交"/> </from> |
Controller代碼:
@RequestMapping("/json") @ResponseBody public String findJson(String roleName, String roleNum){ Map<String,Object> map = new HashMap<String,Object>(); String str1 = roleName; String str2 = roleNum; System.out.println("roleName="+roleName +"roleNum="+roleNum ); map.put("msg1", str1 + str2 +"你好"); return JSON.toJSONString(map); } |
此種方法驗證時候,序列化的data無法傳到controller中,待解決…
URL傳參
4:RESTFul風格,它將只支持http的GET請求。
$("#json").click(function(){ var param ={}; param.gname = "gname"; param.gid = "gid"; $.ajax({ url:"json/"+true, data:param, type:"GET", dataType:"json", success:function(result){ $("#josnview").text(result.msg1); }, error:function(){ alert("huidiao失敗"); } }); }); |
@RequestMapping(value="/json/{id}",method=RequestMethod.GET) @ResponseBody public String findJson(@RequestParam(value="gname")String name, @RequestParam(value="gid",required=false)String ps, @PathVariable(value="id")Boolean id){ Map<String,Object> map = new HashMap<String,Object>(); map.put("msg1", name+ps+"你好"+id); return JSON.toJSONString(map); } |
注意:一定要是GET請求。@PathVariable注解允許接收參數為String,Integer,Boolean等!
傳遞JSON參數
1:原生ajax
A: Javascript監聽瀏覽器網頁事件(點擊,提交,更改等)
B: 創建Ajax引擎對象
C: 配置請求對象的信息
Open()方法還可以設置是否異步req.open( "GET", url, true );
注意:如果是GET請求,則send(null); 如果使用POST請求,就一定要設置請求頭,並send(data):
xhr.setRequestHeader("Content-Type","application/x-www-form-u;rlencoded; charset=gb2312");
設置響應超時,在send()之前:
xhr.open(); xhr.ontimeout = function(){ alert('request timeout'); } |
overrideMimeType()方法。
用於重寫XHR響應的MIME類型。這對服務器與客戶端使用不同編碼類型時非常有用。例如在以前如果瀏覽器使用UTF-8而服務器返回了GBK格式的數據時可能會遇到亂碼。而現在就可以用overrideMimeType來解決。
2.$.ajax()方法
可以定義請求失敗時的回調函數。$.get() , $.post(),$.getJSON() 則不可以。
1、基本類型入參
Js代碼:
$("#json").click(function(){ alert("jingru ajax2"); var param = {}; param.name="1"; param.ps="2"; $.ajax({ url:"json", data:param, type:"post", async:true, dataType:"json", //一般都會預期返回JSON字符串 success:function(result){ alert(result); $("#josnview").text(result.msg); }, error:function(){ alert("回調失敗"); } }); }); |
Controller代碼
@RequestMapping("/json") @ResponseBody public String findJson(@RequestParam(value="name")String name, @RequestParam(value="ps",required=false)String ps){ Map<String,Object> map = new HashMap<String,Object>(); map.put("msg", name+ps+"你好"); return JSON.toJSONString(map); } |
@RequestMapping("/json") @ResponseBody public Map<String,Object> findJson( @RequestParam(value="name")String name, @RequestParam(value="ps",required=false)String ps){ Map<String,Object> map = new HashMap<String,Object>(); map.put("msg", name+ps+"你好"); return map; } |
2、基本類型的Bean入參
定義一個Bean
public class Goods implements Serializable {
//商品名稱 private String gname; private Integer gid; @DateTimeFormat(pattern="yyyy-MM-dd") private Date gtime; private BigDecimal[] nums; //省略get()/set()方法……
} |
Js代碼:
$("#json").click(function(){ alert("jingru ajax2"); var param = {}; param.gname = "gname"; param.gid = 2; $.ajax({ url:"json", data:param, type:"post", async:true, dataType:"json", success:function(result){ alert(result); $("#josnview").text(result.msg); }, error:function(){ alert("huidiao失敗"); } }); }); |
Controller代碼
@RequestMapping("/json") @ResponseBody public String findJson(Goods goods){ Map<String,Object> map = new HashMap<String,Object>(); map.put("msg", goods.getGname()+goods.getGid()+"你好"); System.out.println("name="+goods.getGname()+goods.getGid());
return JSON.toJSONString(map); } |
3、@requestBody 處理Bean中屬性有數組
@requestBody注解常用來處理contentType不是默認的application/x-www-form-urlcoded編碼的內容,比如說:application/json或者是application/xml等。一般情況下來說常用其來處理application/json類型。通過@requestBody可以將請求體中的JSON字符串綁定到相應的bean上,當然,也可以將其分別綁定到對應的字符串上。@requestBody User user 這種形式會將JSON字符串中的值賦予user中對應的屬性上需要注意的是,JSON字符串中的key必須對應user中的屬性名,否則是請求不過去的。
@RequestBody接收的是一個Json對象的字符串,而不是一個Json對象。然而在ajax請求往往傳的都是Json對象,后來發現用 JSON.stringify(data)的方式就能將對象變成字符串。同時ajax請求的時候也要指定dataType: "json",contentType:"application/json" 這樣就可以輕易的將一個對象或者List傳到Java端,使用@RequestBody即可綁定對象或者List.
JS代碼:
$("#json").click(function(){ alert("jingru ajax2"); var param = {}; param.gname = "gname"; param.gid = 2; param.nums = [2.12,3.54,3.67]; $.ajax({ url:"json", data:JSON.stringify(param), //json對象轉換為字符串 type:"post", async:true, contentType:"application/json;charset=utf-8", //必須 dataType:"json", success:function(result){ alert(result); $("#josnview").text(result.msg);
}, error:function(){ alert("huidiao失敗"); } }); }); |
Bean代碼不變:
public class Goods implements Serializable {
//商品名稱 private String gname; private Integer gid; @DateTimeFormat(pattern="yyyy-MM-dd") private Date gtime; private BigDecimal[] nums; //省略set()/get()方法 } |
Controller代碼: //contentType:"application/json",必須添加該注解
@RequestMapping("/json") @ResponseBody public String findJson(@RequestBody Goods goods){ //List list = new ArrayList(); Map<String,Object> map = new HashMap<String,Object>(); BigDecimal[] nums = goods.getNums(); if(nums.length>0){ map.put("msg", nums[0]+goods.getGname()+goods.getGid()+"你好"); }else{ System.out.println("nums.length==0"); } return JSON.toJSONString(map); } |
4、@requestBody 處理json格式的數組
傳遞JSON對象,controller用Bean接收!
傳遞JSON數組,controller用List<Object>接收!
傳遞JSON對象數組,controller用List<Bean>接收!
JS代碼:
$("#json").click(function(){ alert("jingru ajax2"); var param = ["nihao",3.54,true]; $.ajax({ url:"json", data:JSON.stringify(param), type:"post", async:true, contentType:"application/json;charset=utf-8", dataType:"json", success:function(result){ alert(result.msg1+ result.msg2+ result.msg3); $("#josnview").text(result.msg1); }, error:function(){ alert("huidiao失敗"); } }); });
|
Controller代碼:
@RequestMapping("/json") @ResponseBody public String findJson(@RequestBody List<Object> list){ //List list = new ArrayList(); Map<String,Object> map = new HashMap<String,Object>(); //BigDecimal[] nums = goods.getNums(); if(list.size()>0){ map.put("msg1", list.get(0)+"你好"); map.put("msg2", list.get(1)+"你好"); map.put("msg3", list.get(2)+"你好"); }else{ System.out.println("nums.length==0"); } return JSON.toJSONString(map); } |
保存並獲取屬性參數
@RequestAttribute/@SeesionAttribute
獲取http請求的屬性值,並傳遞給controller!(類似於@RequestParam)
JSP代碼:
<% request.setAttribute("id" , 1L); request.getRequestDispatcher("./attribute/request.do").forward(request,response); %> |
Conreoller代碼
@RequestMapping("/request") Public ModelAndView reqAttr(@RequestAttribute(name="id",required=false)Long id){ …..return mv; } |
@SeesionAttribute的用法一模一樣
@SessionAttributes
只能標注在類上面,不能標注在方法上。當執行完controller之后,響應的模型的屬性將會被保存在session中。這樣不需要侵入式的servletAPI來設置session屬性了!
URL請求:/attribute/sessionAttributes.do?user_id=1
Controller代碼:
@Controller @RequestMapping("/ attribute") @SessionAttributes( name={"user_id"} , type={User.class} ) public Class AttributeController{
@RequestMapping("/ sessionAttributes") Public ModelAndView sessionAttr(Long user_id){ ModelAndView mv = new ModelAndView(); User user = userService.getUser(user_id); mv.addObject("user",user); //根據類型名,session將保存User mv.addObject("user_id",user_id); //根據屬性名,session將保存user_id mv.setView("anotherJSP"); return mv; }} |
在下一個jsp頁面anotherJSP中可以直接從session中獲取user和user_id
@CookieValue的使用
注意客戶端禁用coookie的情況!
Js代碼:
//設置cookie function setCookie(c_name,value,expiredays) { var exdate=new Date() exdate.setDate(exdate.getDate()+expiredays) document.cookie=c_name+ "=" +escape(value)+ ((expiredays==null) ? "" : ";expires="+exdate.toGMTString()) }
$(function(){ setCookie("cookie_name1","cookiename1",null); setCookie("cookie_name2","cookiename2",null);
$("#json").click(function(){ var param ={}; param.gname = "gname"; param.gid = "gid"; $.ajax({ url:"json/"+true, data:param, type:"GET", dataType:"json", success:function(result){ alert(result.msg1); $("#josnview").text(result.msg1); }, error:function(){ alert("huidiao失敗"); } }); }); }); |
Controller代碼
@RequestMapping(value="/json/{id}",method=RequestMethod.GET) @ResponseBody public String findJson(@RequestParam(value="gname")String name, @RequestParam(value="gid",required=false)String ps, @PathVariable(value="id")Boolean id, @CookieValue(value="cookie_name1",required=true,defaultValue="mycookie")String cookie1, @CookieValue(value="cookie_name2",required=true,defaultValue="mycookie")String cookie2){ Map<String,Object> map = new HashMap<String,Object>(); map.put("msg1", name+ps+"你好"+id+cookie1+cookie2); return JSON.toJSONString(map); } |
注意:required屬性默認就是true,在客戶端禁用cookie或者找不到對應的cookie的時候:
會自動按照defaultValue輸出,此時如果沒喲定義defaultValue則請求會報錯。所以為了安全,最好定義defaultValue!
@RquestHeader
獲取請求頭的一些信息。請求頭的常見信息如下:
User-Agent
直接在方法里面使用注解獲取:
@RequestHeader(value="User-Agdddent",required=false,defaultValue="header")String aencoding |
Mybatis的SQL查詢
1 無參數
沒有入參,只能為查詢語句,並且是返回多條記錄!(可以用list集合和map集合接收)
多條記錄返回List<Bean>/嵌套Map集合
Dao接口代碼:
public List<User> queryUser(); |
Mapper.xml代碼:
<resultMap id="allUser" type="User"> <result property="userid" column="userID" /> <result property="userrole" column="userRole" /> <result property="username" column="userName" /> <result property="pwd" column="pwd" /> <result property="address" column="address" /> <result property="phone" column="phone" /> <result property="email" column="email" /> <result property="sex" column="sex" /> <result property="birthday" column="birthday" /> <result property="hdpicpath" column="hdpicpath" /> <result property="wkpicpath" column="wkpicpath" /> </resultMap>
<!-- 查詢所喲的用戶--> <select id="queryUser" resultMap="allUser" > |
@MapKey("id")
Map<Long, Map<String,Object>> getUserValueMap();
單條記錄返回Bean/Map
@MapKey("id")
Map<Long, UserInfo> getUserInfoMap();
2 單獨幾個參數
單獨幾個參數的時候,在接口方法處需要加注解@Param("參數名"),參數名以便在sql中按順序引用。一個參數時候,可以省略(最好加上)
返回影響行數int
增刪改語句默認返回影響的行數int,xml中可以不寫返回值類型。
多條記錄返回List<User>/嵌套的Map集合
注意:
1:多參數入參,所以不用在xml中寫入參類型,類型是不統一的。
2:Sql中參數引用的時候要和傳參的順序一致!
3:返回多條記錄卻制定resultType="Bean"是會報錯的!
必須用resultMap或者resultType="map集合"!
用list接收的情況:
/* * 查詢滿足條件的所有用戶 */ @MapKey("id") public List<User> queryUser(@Param("sex")String sex, @Param("userRole")Integer userRole, @Param("userName")String userName); |
<resultMap id="allUser" type="User"> <result property="userid" column="userID" /> <result property="userrole" column="userRole" /> <result property="username" column="userName" /> <result property="pwd" column="pwd" /> <result property="address" column="address" /> <result property="phone" column="phone" /> <result property="email" column="email" /> <result property="sex" column="sex" /> <result property="birthday" column="birthday" /> <result property="hdpicpath" column="hdpicpath" /> <result property="wkpicpath" column="wkpicpath" /> </resultMap>
<!-- 查詢所喲的用戶--> <select id="queryUser" resultMap="allUser" > select * from `user` where sex = #{sex} and userRole = #{userRole} and userName = #{userName} </select> |
單條記錄返回Bean或者Map集合
3 Bean入參
一個Bean入參
一個Bean入參的時候需要指定parametersType(類的完全限定名,或者配置別名)(經過驗證,不指定parametersType也是可以的)。
sql語句獲取參數的時候直接用#{屬性名}即可。參數之間沒有順序要求。
復合Bean入參
多個Bean的入參必須加上@Param("類名稱"),在sql中用各自的類名稱.屬性引用,多個Bean沒法定義parametersType,顧省略。(這個可以用於連表查詢的情況!)
4 Map入參
1:單Map入參和單Bean入參一樣的,在接口方法處不用@Param注解,則在sql語句里面直接用#{key}獲取value。parametersType="Map"可以指定(代碼可讀性高),也可以不指定。
2:如果是多個Map一起入參,在接口方法處必須加@Param("別名"),在sql語句中用
#{別名.key}獲取value
5 List入參
List入參常常和動態sql《foreach》組合用。因為list中的個數未知!
<!--List:forech中的collection屬性類型是List,collection的值必須是:list,item的值可以隨意,Dao接口中參數名字隨意 --> |
占位符#和$的區別
動態SQL
什么是動態SQL? |
foreach
使用場景:
-
相同的參數用在in()的括號里面。
-
相同的幾個對象用於批量插入或者更新。
foreach標簽 |
1: 數組入參
2:List入參
A:list里面的參數是一個字段
DAO接口:
public List<User> queryUser(List<String> pwd); |
Mapper.xml
<resultMap id="allUser" type="User"> <result property="userid" column="userID" /> <result property="userrole" column="userRole" /> <result property="username" column="userName" /> <result property="pwd" column="pwd" /> <result property="address" column="address" /> <result property="phone" column="phone" /> <result property="email" column="email" /> <result property="sex" column="sex" /> <result property="birthday" column="birthday" /> <result property="hdpicpath" column="hdpicpath" /> <result property="wkpicpath" column="wkpicpath" /> </resultMap>
<!-- 查詢所喲的用戶--> <select id="queryUser" resultMap="allUser" > select * from `user` where pwd in <foreach collection="list" item="pwd" open="(" separator="," close=")"> #{pwd} </foreach> </select> |
Controller代碼:
List<User> list = new ArrayList<User>(); List<String> pwd = new ArrayList<>(); pwd.add("123"); pwd.add("456"); pwd.add("134"); pwd.add("135"); pwd.add("111"); list = userService.queryUser(pwd); |
B:list里面的參數是一個對象(批量插入數據)
插入之后返回主鍵
接口代碼:
/* * 批量插入用戶 */ public int queryUser(List<User> user); |
Mapper.xml文件:
<!-- 插入幾個用戶,並返回各自的主鍵--> <insert id="queryUser" useGeneratedKeys="true" keyProperty="userid"> insert into `user`(userName,pwd,address,phone,email,sex,userRole)values <foreach collection="list" item="user" open="(" separator="),(" close=")"> #{user.username},#{user.pwd},#{user.address},#{user.phone},#{user.email},#{user.sex},#{user.userrole} </foreach> </insert> |
Controller代碼:
User u1 = new User(); u1.setAddress("成都市后山區"); u1.setEmail("ndihao@qq.com"); u1.setPhone("8765421"); u1.setPwd("987"); u1.setSex("女"); u1.setUserrole(0); u1.setUsername("zhs"); //同理new u2,u3 userInput.add(u1); userInput.add(u2); userInput.add(u3);
int a = userService.queryUser(userInput); //返回影響的行數 int b1 = u1.getUserid();//插入成功后主鍵回填到指定的userid字段 int b2 = u2.getUserid(); int b3 = u3.getUserid(); |
useGeneratedKeys="true"是用JDBC的statement對象的getGeneratedKeys()獲取主鍵。
keyProperty:僅在insert、update才使用,定義主鍵回填到哪個字段,復合主鍵用(,)隔開,不能和keyColumn同時使用
keyColumn: 僅在insert、update才使用.(在postgreSQL中是必須的),不能和keyProperty同時使用
statementType: STATEMENT / PREPARED / CALLABLE 分別使用Statement,PreparedStatement,CallableStatement
批量更新
Dao接口文件:經過測試,批量修改成功,但是主鍵返回失敗
/* * 批量修改用戶 */ public int queryUser(List<User> user); |
Mapper.xml文件:
<!-- 插入幾個用戶,並返回各自的主鍵--> <update id="queryUser" useGeneratedKeys="true" keyProperty="userid"> UPDATE `user` SET pwd = CASE userName <foreach collection="list" item="user" open="" separator="" close=""> WHEN #{user.username} THEN #{user.pwd} </foreach> END WHERE userName IN <foreach collection="list" item="user" open="(" separator="," close=")"> #{user.username} </foreach> </update> |
Controller代碼:
User u1 = new User(); u1.setPwd("2090"); u1.setUsername("56789");
User u2 = new User(); u2.setPwd("2091"); u2.setUsername("11111"); //將username=11111的人的pwd修改為2091
User u3 = new User(); u3.setPwd("2092"); u3.setUsername("8888"); //將username=8888的人的pwd修改為2092
userInput.add(u1); userInput.add(u2); userInput.add(u3);
int a = userService.queryUser(userInput); int b1 = u1.getUserid(); int b2 = u2.getUserid(); int b3 = u3.getUserid(); |
If (test)
常用於判斷
choose/when/otherwise
存在 1=1的弊端!
<select id="getEmpByChoose" resultType="Emp" parameterType="Emp"> select * from emp where 1 = 1 <choose> <when test="job != null"> and job = #{job} </when> <when test="deptno != null"> and deptno = #{deptno} </when> <otherwise> and mgr = #{mgr} </otherwise> </choose> </select> |
trim/where/set
where + if 可以解決 where 1=1的弊端
<select id="getMaxDepartId" parameterType="java.lang.String" resultType="java.lang.String"> SELECT MAX(DEPART_ID) FROM T_P_DEPART <where> <if test="_parameter!=null and _parameter!=''"> AND DEPART_PID = #{departId,jdbcType=VARCHAR} </if> <if test="_parameter==null or _parameter==''"> AND DEPART_PID IS NULL </if> </where> </select> |
trim+ if 標簽也可以解決 where 1=1 的弊端
Set的使用:
<update id="updateEmpBySet" parameterType="Emp"> update emp <set> <if test="ename != null and ename != ''"> ename = #{ename}, </if> <if test="job != null and job != ''"> job = #{job}, </if> </set> where empno = #{empno} </update> |
bing
主要用於字符串拼接!
Mysql用concat()拼接,oracle用"||"拼接。所以不能共用同一sql語句。
Bing標簽可以將傳入的變量先拼接好,這樣就可以在sql其它位置引用。
<selet resultType="" > <bing name="pattern_username" value=" '%' + username + '%' " /> Select * from tablename where username like #{ pattern_username } </select> |
<ResulMap /> 、 連表查詢
resultMap標簽:
resultMap的基本配置項 |
resultMap的屬性: |
Ident表和user表聯查:
存在外鍵關聯的(需要作為查詢結果返回的)pojo定義:
public class Indent implements Serializable { private Integer indentid;//訂單編號 private String userid;//用戶編號 private String indentime;//下單時間 private String indentstatu;//訂單狀態 private List<User> userlist; //存在外鍵關聯 private List<T_status> statuslist; //存在外鍵關聯 |
mapper文件resultMap編寫:
<resultMap type="Indent" id="indentlist"> <id property="indentid" column="indentId"/> <result property="userid" column="userId"/> <result property="indentstatu" column="indentStatu"/> <result property="indenttime" column="indentTime"/> <collection property="userlist" ofType="User"> <id property="userid" column="userId"/> 填寫外鍵 <result property="address" column="address"/> <result property="username" column="userName"/> <result property="phone" column="phone"/> </collection> <collection property="statuslist" ofType="T_status" resultMap="statuslist"/> </resultMap>
<!-- 分頁顯示訂單記錄 --> <select id="getAllIndent" resultMap="indentlist"> SELECT i.indentId,u.userName,u.phone,u.address,s.statusName FROM `user` u INNER JOIN indent i ON u.userId=i.userId INNER JOIN t_status s ON s.indentStatu=i.indentStatu LIMIT #{usecurrentPage},3 </select> |