SSM三层模型之间的参数传递
Controller接收各种形式的传参:
RequestMapping()包含三部分信息:
表单传参:
1、表单action请求
1:参数名称和顺序都要和表单字段名称⼀致,直接接收(适合字段较少的)
@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接收中的变量名不⼀致!
@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\
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代码:
Controller代码:
@RequestMapping(\"/json\") @ResponseBody
public String findJson(String roleName, String roleNum){
public String findJson(String roleName, String roleNum){ Map map = new HashMap(); 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 map = new HashMap();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\
注意:如果是GET请求,则send(null); 如果使⽤POST请求,就⼀定要设置请求头,并send(data):
xhr.setRequestHeader(\"Content-Type\
设置响应超时,在send()之前:
xhr.open();
xhr.timeout = 1000;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 map = new HashMap(); map.put(\"msg\", name+ps+\"你好\"); return JSON.toJSONString(map);}@RequestMapping(\"/json\") @ResponseBody
public Map findJson(@RequestParam(value=\"name\")String name,@RequestParam(value=\"ps\",required=false)String ps){Map map = new HashMap(); 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 map = new HashMap(); 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上,当然,也可以将其分别绑定到对应的字符串上。@requestBodyUser user 这种形式会将JSON字符串中的值赋予user中对应的属性上需要注意的是,JSON字符串中的key必须对应user中的属性名,否则是请求不过去的。
@RequestBody接收的是⼀个Json对象的字符串,⽽不是⼀个Json对象。然⽽在ajax请求往往传的都是Json对象,后来发现⽤ JSON.stringify(data)的⽅式就能将对象变成字符串。同时ajax请求的时候也要指定dataType: \"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 map = new HashMap(); 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接收!传递JSON对象数组,controller⽤List接收!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\") @ResponseBodypublic String findJson(@RequestBody List list){//List list = new ArrayList(); Map map = new HashMap(); //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\…..return mv;}
@SeesionAttribute的⽤法⼀模⼀样
@SessionAttributes
只能标注在类上⾯,不能标注在⽅法上。当执⾏完controller之后,响应的模型的属性将会被保存在session中。这样不需要侵⼊式的servletAPI来设置session属性了!
URL请求:/attribute/sessionAttributes.do?user_id=1
Controller代码:
@Controller
@RequestMapping(\"/ attribute\")
@SessionAttributes( name={\"user_id\public Class AttributeController{
@RequestMapping(\"/ sessionAttributes\")Public ModelAndView sessionAttr(Long user_id){ModelAndView mv = new ModelAndView();User user = userService.getUser(user_id);
mv.addObject(\"user\根据类型名,session将保存Usermv.addObject(\"user_id\根据属性名,session将保存user_idmv.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 map = new HashMap();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\
Mybatis的SQL查询
1 ⽆参数
没有⼊参,只能为查询语句,并且是返回多条记录!(可以⽤list集合和map集合接收)
多条记录返回List/嵌套Map集合Dao接⼝代码:
public List queryUser();Mapper.xml代码:
@MapKey(\"id\")
Map> getUserValueMap();单条记录返回Bean/Map
@MapKey(\"id\")
Map getUserInfoMap();2 单独⼏个参数
单独⼏个参数的时候,在接⼝⽅法处需要加注解@Param(\"参数名\"),参数名以便在sql中按顺序引⽤。⼀个参数时候,可以省略(最好加上)
返回影响⾏数int
增删改语句默认返回影响的⾏数int,xml中可以不写返回值类型。
多条记录返回List/嵌套的Map集合注意:
1:多参数⼊参,所以不⽤在xml中写⼊参类型,类型是不统⼀的。2:Sql中参数引⽤的时候要和传参的顺序⼀致!3:返回多条记录却制定resultType=\"Bean\"是会报错的!必须⽤resultMap或者resultType=\"map集合\"!
⽤list接收的情况:
/*
* 查询满⾜条件的所有⽤户 */
@MapKey(\"id\")
public List queryUser(@Param(\"sex\")String sex, @Param(\"userRole\")Integer userRole, @Param(\"userName\")String userName);
select * from `user` where sex = #{sex} and userRole = #{userRole} anduserName = #{userName}
单条记录返回Bean或者Map集合
3 Bean⼊参
⼀个Bean⼊参
⼀个Bean⼊参的时候需要指定parametersType(类的完全限定名,或者配置别名)(经过验证,不指定sql语句获取参数的时候直接⽤#{属性名}即可。参数之间没有顺序要求。
parametersType也是可以的)。
复合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中的个数未知!
select *from EMPLOYEES e
where e.EMPLOYEE_ID in
select *from EMPLOYEES e
where e.EMPLOYEE_ID in
占位符#和$的区别
动态SQL
什么是动态SQL?1.基于OGNL表达式
2.完成多条件查询的逻辑3.动态SQL的主要元素
(if,trim,where,set,choose,foreach)
foreach
使⽤场景:
1. 相同的参数⽤在in()的括号⾥⾯。
2. 相同的⼏个对象⽤于批量插⼊或者更新。
foreach标签1:基本属性
1:item:表⽰集合中每⼀个元素进⾏迭代时的别名2:index:指定⼀个名称,在迭代过程中,每次迭代到的位置
3:open:表⽰该语句以什么开始4:separator:每次迭代之间的分隔符5:close:表⽰该SQL语句以什么结尾6:collection:属性值有三种情况:
a:若⼊参为单参,是⼀个List时,collection值为listb:若⼊参为单参,是⼀个数组时,collection值为arrayc:多参数⼊参,封装为⼀个Map。collection值为Map的key值 单参和多参其实都是封装成Map集合的形式⼊参的
1: 数组⼊参
2:List⼊参
A:list⾥⾯的参数是⼀个字段
DAO接⼝:
public List queryUser(List pwd);Mapper.xml
select * from `user` where pwd in#{pwd}
Controller代码:
List list = new ArrayList();List 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);Mapper.xml⽂件:
insert into `user`(userName,pwd,address,phone,email,sex,userRole)values #{user.username},#{user.pwd},#{user.address},#{user.phone},#{user.email},#{user.sex},#{user.userrole}
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,u3userInput.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);Mapper.xml⽂件:
UPDATE `user` SET pwd = CASE userNameWHEN #{user.username} THEN #{user.pwd}
END WHERE userName IN
#{user.username}
Controller代码:
User u1 = new User();u1.setPwd(\"2090\");u1.setUsername(\"567\");
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 * from emp where 1 = 1and job = #{job}
and deptno = #{deptno} and mgr = #{mgr}
trim/where/set
where + if 可以解决 where 1=1的弊端
SELECT MAX(DEPART_ID) FROM T_P_DEPARTAND DEPART_PID = #{departId,jdbcType=VARCHAR}
AND DEPART_PID IS NULL
trim+ if 标签也可以解决 where 1=1 的弊端
Set的使⽤:
update empename = #{ename},
job = #{job},
where empno = #{empno}
bing
主要⽤于字符串拼接!
Mysql⽤concat()拼接,oracle⽤\"||\"拼接。所以不能共⽤同⼀sql语句。Bing标签可以将传⼊的变量先拼接好,这样就可以在sql其它位置引⽤。
Select * from tablename where username like #{ pattern_username }
、 连表查询
resultMap标签:
resultMap的基本配置项resultMap的属性:
id:它是resultMap的唯⼀标识type:java实体类resultMap的⼦元素
id:对应数据库中该⾏的主键id,设置此项可提⾼MyBatis的性能
result:映射到javaBean的某个简单类型属性property: 映射数据库列的实体对象的属性column:数据库列名或者别名
association:映射到javaBean的某个复杂类型属性如javaBean
1: 复杂的类型关联,⼀对⼀(⼀个实体类嵌套另⼀个实体类属性)
2:内部嵌套:映射⼀个嵌套javaBean属性3:属性:
a:property: 映射数据库列的实体对象的属性b:javaType:完整java类名或者别名c:resultMap:应⽤外部的resultMap4:⼦元素
id:同resultMap的id⼀样对应该javaBean表的主键result:
property: 映射数据库列的实体对象的属性column:数据库列名或者别名
collection:映射到javaBean的某个复杂类型属性,例如集合1:复杂类型集合,⼀对多(⼀个实体类嵌套另⼀个实体类集合)
2:内部嵌套:映射⼀个嵌套结果集到⼀个列表
3:属性
property:映射数据库列的实体对象的属性
ofType:完整的java类名或者别名(集合所包含的类型)resultMap: 应⽤外部的resultMap,代码重⽤4:⼦元素
id:同resultMap的id⼀样对应该javaBean表的主键result:
property: 映射数据库列的实体对象的属性column:数据库列名或者别名
Ident表和user表联查:
存在外键关联的(需要作为查询结果返回的)pojo定义:
public class Indent implements Serializable { private Integer indentid;//订单编号 private String userid;//⽤户编号 private String indentime;//下单时间 private String indentstatu;//订单状态 private List userlist; //存在外键关联 private List statuslist; //存在外键关联mapper⽂件resultMap编写:
填写外键
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 ONs.indentStatu=i.indentStatuLIMIT #{usecurrentPage},3