SpringMVC

1. B/S架构的MVC

MVC(Model View Controller):模型(model)、视图(view)、控制器(controller)是目前流行的一种开发模式。B/S架构的运行流程如下

Paste_Image.png
  • 用户(user)发起请求(request),控制器(controller)接收到用户请求,并将用户请求的数据委托给模型(model)
  • 控制器通过模型(model)进行一系列的业务逻辑处理后,将处理结果再返回给控制器
  • 控制器将模型返回的数据展示在视图(view)上
  • 控制器将处理完成的结果视图返回给用户(response)

2. SpringMVC

架构图

Paste_Image.png

-用户发送请求(request)至前端控制器DispatcherServlet

  • DispatcherServlet收到请求后调用HandlerMapping处理器映射器查找处理器
  • 处理器映射器找到具体的处理器后,生成处理器对象和处理器拦截器,并返回给DispatcherServlet
  • DispatcherServlet调用HandlerAdapter处理器适配器
  • HandlerAdapter经过适配调用具体的处理器(后端控制器)
  • 处理器执行完成后返回ModelAndView
  • HandlerAdapter将处理器的执行结果ModelAndView返回给DispatcherServlet
  • DispatcherServlet将ModelAndView传给ViewReslover视图解析器
  • ViewReslover解析后返回具体View
  • DispatcherServlet根据View进行数据渲染,将模型中的数据填充至视图中
  • DispatcherServlet将最后的视图返回给用户

3. 各个组件

  • HandlerMapping处理器映射器
    ①、BeanNameUrlHandlerMapping
    将后端控制器的beanName作为请求的url

<!—beanName Url映射器 -->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>

②、SimpleUrlHandlerMapping
通过后端控制器bean的id,可定义多个url映射至一个后端控制器,<prop></prop>中间的之为后端控制器bean的id
- ```
<!—简单url映射 -->
    <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="/hello1.action">hello_controller</prop>
                <prop key="/hello2.action">hello_controller</prop>
            </props>
        </property>
    </bean>
  • HandlerAdapter处理器适配器
    ①、SimpleControllerHandlerAdapter
    简单控制器器处理器适配器,所有实现了org.springframework.web.servlet.mvc.Controller 接口的Bean作为Springmvc的后端控制器。控制器返回ModelAndView

<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />

②、HttpRequestHandlerAdapter
HTTP请求处理器适配器,将http请求封装成HttpServletRequest和HttpServletResponse对象,和servlet接口类似,控制器通过response修改定义响应内容
- ```
<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"/>
  • 控制器
    实现Controller接口的bean,返回ModelAndView对象
<bean id="command_controller" name="/command.action" 
class="com.snakotech.springmvc.controller"/>

4. 注解开发

4.1 一个例子
  •   <!--注解映射器 -->   
      <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
      <!--注解适配器 -->
      <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
    
- Controller编写
- ```
@Controller
publicclass HelloWorldController {

    @RequestMapping(value="/hello")
    public String hello(Model model)throws Exception{
        model.addAttribute("message", "HelloWorld!");
        return"hello";
    }
}

@Controller:用于标识处理类
@RequestMapping:请求到处理器功能方法的映射规则
在xml中的配置


<bean class="com.snakotech.springmvc.controller.HelloWorldController"/>

组件扫描:如果使用了组件扫描则不需要在xml中配置Controller
可扫描@component、@controller、@service、@repository的注解

<context:component-scan base-package="com.snakotech.springmvc.controller" />


#####4.2 @Controller和@RequestMapping
- @Controller
标识该类为控制类,@Controller、@Service、@Repository分别对应web应用三层架构的组件,控制器、服务接口、数据访问接口
- @RequestMapping
- - URL路径映射
@RequestMapping(value="/user")或@RequestMapping("/user")
- - 根路径和子路径
根路径:@RequestMapping放在类名上边
- - ```
@Controller
@RequestMapping("/user")

子路径:@RequestMapping放在方法名上边

@RequestMapping("/user")
public String userAdd() {}

- - URL模板模式映射@RequestMapping(value="/useredit/{userId}"):{×××}占位符,请求的URL可以是“/useredit/001”或“/useredit/abc”,通过在方法中使用@PathVariable获取{×××}中的×××变量。
- - ```
      @RequestMapping("/useredit/{userid}")
    public String useredit(@PathVariable String userid,Model model) throws Exception{
        //方法中使用@PathVariable获取useried的值,使用model传回页面
        model.addAttribute("userid", userid);
        return"/user/useredit";
    }

多个占位符

@RequestMapping("/useredit/{groupid}/{userid}")
public String useredit(@PathVariable String groupid,@PathVariable String userid,Model model) throws Exception{
//方法中使用@PathVariable获取useried的值,使用model传回页面
model.addAttribute("groupid", groupid);
model.addAttribute("userid", userid);
return"/user/useredit";
}


#####4.3 请求方法限定
- 限定GET方法
- ```
@RequestMapping(method = RequestMethod.GET)

如果通过Post访问则报错:
HTTP Status 405 - Request method 'POST' not supported

@RequestMapping(value="/useredit/{userid}",method=RequestMethod.GET)

- 限定POST方法
- ```
@RequestMapping(method = RequestMethod.POST)

如果通过Post访问则报错:
HTTP Status 405 - Request method 'GET' not supported

@RequestMapping(value="/useredit/{userid}",method=RequestMethod.POST)

GET和POST都可以
- ```
@RequestMapping(method={RequestMethod.GET,RequestMethod.POST})
4.4 请求数据绑定

Controller方法通过形参接收页面传递的参数。

@RequestMapping("/userlist")
public String userlist(HttpServletRequest request,
HttpServletResponse response,
HttpSession session,
Model model
){
}


- 默认支持的参数类型
- - HttpServletRequest:通过request对象获取请求信息
- - HttpServletResponse:通过response处理响应信息
- - HttpSession:通过session对象得到session中存放的对象
- - Model:通过model向页面传递数据
- - ```
model.addAttribute("user", new User("李四"));

页面通过${user.XXXX}获取user对象的属性值。

  • 命令/表单对象:自动将请求参数绑定到功能处理方法的命令/表单对象上,Controller方法通过形参接收命令/表单对象。
    • Java基本数据类型
      • 布尔型:

<tr>
<td>用户状态:</td>
<td>
<inputtype="radio"name="userstate"value="true"/>
<inputtype="radio"name="userstate"value="false"/></td>
</tr>
<tr>

- - - 整型
- - - ```
<tr>
<td>用户状态:</td>
<td>
<inputtype="radio"name="userstate"value="1"/>
<inputtype="radio"name="userstate"value="2"/></td>
</tr>
<tr>
      • 单精度/双精度

<tr>
<td>用户状态:</td>
<td>
<inputtype="radio"name="userstate"value="1.2"/>
<inputtype="radio"name="userstate"value="1.22"/></td>
</tr>
<tr>

- - - 日期型需要添加属性编辑器:
- - - ```
@InitBinder
    public void initBinder(HttpServletRequest request,
            ServletRequestDataBinder binder) throws Exception {
        binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"),true));
    }
    • Pojo对象
页面上以pojo对象名点属性名命名:
如果采用类似struts中对象.属性的方式命名,需要将pojo对象作为一个包装对象的属性,action中以该包装对象作为形参。
包装对象定义如下:
- - ```
public class UserVo {
private User user;
public User getUser() {
        return user;
}
public void setUser(User user) {
        this.user = user;
}
}

页面定义:

<input type="text" name="user.age" />
<input type="text" name="user.birthday" />

Controller方法定义如下:
- - ```
public String useraddsubmit(Model model,UserVo userVo)throws Exception{
System.out.println(userVo.getUser());
}
    • 字符串数组
      页面定义如下:
      页面选中多个checkbox向controller方法传递

<input type="checkbox" name="deleteid" value="001"/>
<input type="checkbox" name="deleteid" value="002"/>
<input type="checkbox" name="deleteid" value="002"/>

传递到controller方法中的格式是:001,002,003
Controller方法中可以用String[]接收,定义如下:
- - ```
public String deletelist(String[] deleteid)throws Exception{
        System.out.println(deleteid);
}
    • List
      List中存放对象,并将定义的List放在包装类中,action使用包装对象接收。
      List中对象:

//成绩对象
public class StudentScore {
private String coursename;//课程名称
private Float score;//成绩
public String getCoursename() {
returncoursename;
}
public void setCoursename(String coursename) {
this.coursename = coursename;
}
public Float getScore() {
returnscore;
}
public void setScore(Float score) {
this.score = score;
}
}

包装类中定义List对象,并添加get/set方法如下:
- - ```
public class UserVo {
private List<StudentScore> scores;//成绩
  //get/set方法..
}

页面:

<tr>
<td>课程成绩:</td>
<td>
课程名:<input type="text"name="scores[0].coursename"/>成绩:<input type="text"name="scores[0].score"/>

课程名:<input type="text"name="scores[1].coursename"/>成绩:<input type="text"name="scores[1].score"/>

课程名:<input type="text"name="scores[2].coursename"/>成绩:<input type="text"name="scores[2].score"/>

</td>
</tr>

Contrller方法定义如下:
- - ```
public String useraddsubmit(Model model,UserVo userVo)throws Exception{
System.out.println(userVo.getScores ());
}
  • @RequestParam绑定单个请求参数
    value:参数名字,即入参的请求参数名字,如value=“studentid”表示请求的参数区中的名字为studentid的参数的值将传入;
    required:是否必须,默认是true,表示请求中一定要有相应的参数,否则将报400错误码;
    defaultValue:默认值,表示如果请求中没有同名参数时的默认值

public String userlist(@RequestParam(defaultValue="2",value="group",required=true) String groupid) {
}

形参名称为groupid,但是这里使用value="group"限定参数名为group,所以页面传递参数的名必须为group。
这里通过required=true限定groupid参数为必需传递,如果不传递则报400错误,由于使用了defaultvalue=”2”默认值即使不传group参数它的值为”2”,所以页面不传递group也不会报错,如果去掉defaultvalue=”2”且定义required=true则如果页面不传递group则会报错。
- @PathVariable 绑定URI 模板变量值
@PathVariable用于将请求URL中的模板变量映射到功能处理方法的参数上
- ```
@RequestMapping(value="/useredit/{groupid}/{userid}",method={RequestMethod.GET,RequestMethod.POST})
    public String useredit(@PathVariable String groupid,@PathVariable String userid,Model model) throws Exception{
        //方法中使用@PathVariable获取useried的值,使用model传回页面
        model.addAttribute("groupid", groupid);
        model.addAttribute("userid", userid);
        return"/user/useredit";
    }

如请求的URL 为“控制器URL/useredit/1/admin.action”,则自动将URL 中模板变量{groupid}和{userid}绑定到@PathVariable注解的同名参数上,即入参后groupid=“1”、userid=“admin”

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容