基于注解的Spring mvc 简单了解

通过一个实例的方式来写这篇博客吧,
假设我现在要创建一个 User

public class User {
    private String userName;
    private String userPassword;
    private Keshi keshi;
    /*setter,getter方法*/
    }

Keshi(音译:科室)也是一个类

public class Keshi {

    private String keshiId;
    private String keshiName;
    }

现在我想创建一个 User ,创建以前 ,让我们来想想Keshi这个类

Keshi肯定是要从数据库中取出来的,然后在页面给用户选择,不是User自己填写的 。

所以可以把显示填写的用户信息的控制器这样写

@Controller
public class KeshiController{

    /*@Autowired(required=false)  
    private KeShiManager keshiService;*/

    @RequestMapping(value = {"/keshilist.do"})
    public String list(ModelMap model) {

            List<Keshi> list=new ArrayList<>();

            Keshi keshi1 = new Keshi();
            Keshi keshi2 = new Keshi();
            keshi1.setKeshiId("1");
            keshi1.setKeshiName("测试1");
            keshi2.setKeshiId("2");
            keshi2.setKeshiName("测试2");
            list.add(keshi1);
            list.add(keshi2); 
            model.addAttribute("keshilist",list);
            return "userAdd";
    }
}

当我们不用基于注解的时候,我们需要给我们的Controller直接或者间接实现Controller,并且在xml中配置HandMapping,这样我们的DispatcherServlet才能找出这个Controller,并让他”干活”
说一说这个类:
@Controller
这个注解 是表明这个类可以作为一个Controller类用,当你在webapplicationContext.xml中配置

 <!-- 配置扫描路径,base-package包中的@Controller会被全部扫面, -->
        <context:component-scan 
        base-package="com.annotationController,com.wl.assertManagment.web"/>

如上所示,base-package可以配置你要扫描的包,如果有多个包,框架都会扫描,你也可以配置成base-package =“com”这样com中的所有类和com的子包,都会被扫描.

@RequestMapping(value = {“/keshilist.do”})
@RequeatMapping注解可以用于类上面,也可以用于方法面,表示这个类可以处理“keshilist.do”这个请求。
除此之外,在使用@RequestMapping时,你也可以指定,RequestMethod这个属性
例如:
@RequestMapping(value=”/b.do”, method={RequestMethod.POST,RequestMethod.GET})
POST表明这个方法只处理POST提交的请求,GET不处理,反过来也是一样的。当然这些你可以放在类上面声明,也可以放在方法上声明(方法声明上必须放一个@RequestMapping,这样框架才知道你要调用哪一个方法去处理这个请求)。如果类上加了方法上也加了,那么就是类上的加上方法上的url
比如:类上的是@RequestMapping(value=”/test”),方法上的是@RequestMapping(value=”/index.do”)那么这个类的这个方法对应的请求的路径就是“test/index.do”;

@RequestMapping还有一个params属性,这个属性可以让使用这个属性的Controller获得和MultiController同样的效果,
params要请求指定请求中的参数,例如:

@RequestMapping(method={RequestMethod.GET},params="params=values")

这个标记在某个方法上,表示这个方法处理的请求必须数GET得到的请求,并且请求中必须包含“params=values”这个参数,不仅要求参数的名字是”params”而且要求值必须是“values”,至于这个参数的位置则没有要求,有无其他参数也没有要求,只要有这个参数,并且值符合要求,则就框架就能让这个方法处理。post也一样,
上面的用法难免有点强人所难的嫌疑,所有框架也允许只使用参数名

@RequestMapping(method={RequestMethod.GET},params="params")

这时候,只要你的请求中包含参数名为“params”就行,至于其他的值,位置,有无其他的参数都不重要,框架只认”params”。这时候就能在一个类里面CRUD操作了。(目前我用的最多的就是引导页面。。)
除此之外还有就是params=”!params”同理这是不要出现参数名为“params”的请求。

之后就是方法的参数:
原则上你可以使用普通java的方法所有可以使用的参数,不过使用以下的这些方法,可以更方便:
1.request/response/session
2.org.springframework.web.context.request.WebRequest
3.java.io.InputStream/java.io.Reqder
4.java.io.OutputStream/java.io.Writer
5.java.util.Locale
6.java.util.Map/org.sparingframework.ui.ModelMap
以上这些类,只要你在参数中声明了。框架就能保证你能拿到这些东西,

/*原理是,框架在调用你定义的处理方法前会先拿到这些方法,之后根据你的方法声明,把相应的对象传递进去。*/
MaodelAndView mav = ...
ModelMap modelMap = new ModelMap();

/*调用方法*/
processMethod(modelMap)

mav.addAllObject(modelMap)
return mav;

返回类型
1.ModelAndView(典型的返回类型)
2.String(逻辑视图名字,模型数据根据需要,通过其他途径获取)
3.ModelMap(模型数据,采用默认的规则获取逻辑视图)

<!-- 配置viewResolver -->
        <bean id="viewResolver"
            class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/" />
            <property name="suffix" value=".jsp" />
        </bean> 
//方法  
        @RequestMapping(value="/test.do",method={RequestMethod.GET,RequestMethod.POST},params="a")
    public void mya1() {
        System.out.println("may1");
    }
    /*以上方法将根据请求名:/test.do  到webContext下去找“test.jsp”*/

4.void(结合String和ModelMap处理)

在返回到我们的例子看一下,定义了一个KeshiController,并模拟产生了keshi的数据,并放到ModelMap中,
这样在页面上就能拿到模型数据中的数据了

 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title></title>
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>

  <body>
   <form action="addUser.do" method="post" name="myform">
      <input type="text" name="userName" /><br/>
      <input type="password" name="userPassword" /><br/>

      <select name="keshi.keshiId" class="form-control" id="sel">

        <c:forEach var="keshi" items="${keshilist}">  
          <option value="${keshi.keshiId}">${keshi.keshiName}</option>
        </c:forEach> 

      </select>

      <!--jsp只能传递字符串,不能传递对象,所以不能直接将用户选中keshi类
                传给后台,
        隐藏域,传递 user.keshi.keshiName-->
      <input type="hidden" name="keshi.keshiName" value="${keshilist[0].keshiName}" id="keshiName"/>   

      <input type="submit" value="提交" />
    </form>    
  </body>

  <script>
  /*通过js来解决用户选择后,keshiId与keshiName不一致的问题*/
    var sel=document.getElementById("sel");

    sel.onchange= function(){

            document.getElementById("keshiName").value = 
                sel.options[sel.selectedIndex].text;

            alert(document.getElementById("keshiName").value);
        }
   </script>

</html>

UserController

@Controller
public class UserController {

    @RequestMapping("/addUser.do")
    public String addUser(User user) {  
        return "success";
    }
}

请求参数到方法参数的绑定
如果你的请求包含参数名,与参数包含的参数名一致,框架就能保证相应的参数能对号入座。
例如:

///mya.do?str=asdasdasd&a=1
@RequestMapping(method={RequestMethod.GET,RequestMethod.POST},params="a")
    public void mya1(String a, String str) {
        ...
    //参数的顺序不影响,关键是名字一定要一样
    //如果名字不一样,就有可能出问题,
    /*如果请求中有一个 ..&age=20,而参数中没有这个名字,或者名字不一样如:'ages',这时框架不能找到名为‘ages’的请求参数,所有会给ages赋一个null,而int是无法接受这个事实的,所有会报错,如果是String或其他应用类型,则就纯粹是一个null*/
    }

以上,如果非要用请求参数ages,则可以使用@RequestParam(“name”)

@RequestParam(“name”)
这个注释可以绑定请求参数到方法参数的对应关系
例如:

@RequestMapping(method={RequestMethod.GET,RequestMethod.POST},params="a")
    public void mya1(@RequestParam("age") int ages, String str) {
        /*这样请求参数的age,就可以绑定到ages上了*/

    }
    /*如果@RequestParam(“name”)标明的请求参数不存在,程序会抛出异常,@RequestParam的required属性,默认是‘true’,所有会抛出异常,可以改成‘false’*/

    @RequestMapping(method={RequestMethod.GET,RequestMethod.POST},params="a")
    public void mya1(@RequestParam(value="age",required=false) int ages, String str) {
        /*这样即使请求参数不包含age,也不会抛出异常*/

    }

指定javaBean对象应用
如上面我们的例子,方法参数可以使用对象,只要给javaBean提供setter方法,并且请求参数名称与javaBean对应的属性名称一样就,框架就能保证数据绑定正确。
如果你想传一个对象过去是不行的,因为,请求参数的传递只能是传字符,jsp会把你的keshi对象换成toString()得到的字符串

这里写图片描述
或者
这里写图片描述
(看你有没有重写keshi的toString()方法)
jsp会把字符“com.wl.assertManagment.web.Keshi@1519077”传递给UserController进行数据绑定,你试图将一个String赋值给一个类。肯定不行,所有会抛出异常
这里写图片描述
所有你要么在传递keshiId然后在UserController中调用方法查找出对应的keshi对象,赋值,要么,想我这样通过一个隐藏域将name传递过去,这里是keshi的属性不多,如果属性很多,推荐在后台赋值。也可以写一个自己的“ editors or conversion strategy ”
太麻烦了,(中间有一次手残,写好了,没发表,点了关机,辛辛苦苦写的全没了,内心几乎是崩溃的。)以后还是要分开写。。。有时间更新

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章