java mvc框架入门,Spring MVC 框架入门学习

深碍√TFBOYSˉ_ 2023-01-13 09:16 319阅读 0赞

1.Spring web mvc介绍

Spring web mvc和Struts2都属于表现层的框架,它是Spring框架的一部分,我们可以从Spring的整体结构中看得出来:

0b157b3e110b

2.Web mvc

用户发起request请求至控制器(Controller)

控制接收用户请求的数据,委托给模型进行处理

控制器通过模型(Model)处理数据并得到处理结果

模型通常是指业务逻辑

控制器将模型数据在视图(View)中展示

web中模型无法将数据直接在视图上显示,需要通过控制器完成。如果在C/S应用中模型是可以将数据在视图中展示的。

控制器将视图response响应给用户

通过视图展示给用户要的数据或处理结果。

0b157b3e110b

3.Spring web mvc 架构

架构图

0b157b3e110b

流程

用户发送请求至前端控制器DispatcherServlet.

DispatcherServlet收到请求调用HandlerMapping处理器映射器.

处理器映射器找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet.

DispatcherServlet调用HandlerAdapter处理器适配器.

HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器).

Controller执行完成返回ModelAndView.

HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet.

DispatcherServlet将ModelAndView传给ViewReslover视图解析器.

ViewReslover解析后返回具体View.

DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。

DispatcherServlet响应用户

组件说明:

++以下组件通常使用框架提供实现:++

DispatcherServlet:作为前端控制器,整个流程控制的中心,控制其它组件执行,统一调度,降低组件之间的耦合性,提高每个组件的扩展性。

HandlerMapping:通过扩展处理器映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。

HandlAdapter:通过扩展处理器适配器,支持更多类型的处理器。

ViewResolver:通过扩展视图解析器,支持更多类型的视图解析,例如:jsp、freemarker、pdf、excel等。

++下边两个组件通常情况下需要开发++:

Handler:处理器,即后端控制器用controller表示。

View:视图,即展示给用户的界面,视图中通常需要标签语言展示模型数据。

4.开发环境准备

本教程使用Eclipse+tomcat7开发

详细参考“Eclipse开发环境配置-indigo.docx”文档

5.第一个springmvc工程

第一步:建立一个Web项目

在eclipse下创建动态web工程springmvc_01。

第二步:导入spring3.1.4的jar包

0b157b3e110b

第三步:前端控制器配置

在WEB-INF\web.xml中配置前端控制器,

springmvc

org.springframework.web.servlet.DispatcherServlet

contextConfigLocation

classpath:springmvc-servlet.xml

// 表示servlet随服务启动

1

springmvc

// 以.action结尾的请求交给DispatcherServlet处理

*.action

load-on-startup:表示servlet随服务启动;

url-pattern:*.action的请交给DispatcherServlet处理。

contextConfigLocation:指定springmvc配置的加载位置,如果不指定则默认加载WEB-INF/[DispatcherServlet 的Servlet 名字]-servlet.xml。

第四步:springmvc配置文件

Springmvc默认加载WEB-INF/[前端控制器的名字]-servlet.xml,也可以在前端控制器定义处指定加载的配置文件,如下:

contextConfigLocation

classpath:springmvc-servlet.xml

如上代码,通过contextConfigLocation加载classpath下的springmvc-servlet.xml配置文件,配置文件名称可以不限定[前端控制器的名字]-servlet.xml。

第五步:配置处理器映射器

在springmvc-servlet.xml文件配置如下:

xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance“ xmlns:mvc=”http://www.springframework.org/schema/mvc“

xmlns:context=”http://www.springframework.org/schema/context“

xmlns:aop=”http://www.springframework.org/schema/aop“ xmlns:tx=”http://www.springframework.org/schema/tx“

xsi:schemaLocation=”http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-3.1.xsd

http://www.springframework.org/schema/mvc

http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context-3.1.xsd

http://www.springframework.org/schema/aop

http://www.springframework.org/schema/aop/spring-aop-3.1.xsd

http://www.springframework.org/schema/tx

http://www.springframework.org/schema/tx/spring-tx-3.1.xsd “>

BeanNameUrlHandlerMapping:表示将定义的Bean名字作为请求的url,需要将编写的controller在spring容器中进行配置,且指定bean的name为请求的url,且必须以.action结尾。

第六步:配置处理器适配器

在springmvc-servlet.xml文件配置如下:

SimpleControllerHandlerAdapter:即简单控制器处理适配器,所有实现了org.springframework.web.servlet.mvc.Controller 接口的Bean作为Springmvc的后端控制器。

第七步:配置视图解析器

在springmvc-servlet.xml文件配置如下:

InternalResourceViewResolver:支持JSP视图解析.

viewClass:JstlView表示JSP模板页面需要使用JSTL标签库,所以classpath必须包含jstl的相关jar包;

prefix 和suffix:查找视图页面的前缀和后缀,最终视图的址为:前缀+逻辑视图名+后缀,逻辑视图名需要在controller中返回ModelAndView指定,比如逻辑视图名为hello,则最终返回的jsp视图地址“WEB-INF/jsp/hello.jsp”

第八步:后端控制器开发

后端控制器即controller,也有称为action。

importjavax.servlet.http.HttpServletRequest;

importjavax.servlet.http.HttpServletResponse;

importorg.springframework.web.servlet.ModelAndView;

importorg.springframework.web.servlet.mvc.Controller;

public class HelloWorldController implements Controller {

@Override

Public ModelAndView handleRequest(HttpServletRequest req, HttpServletResponse resp) throws Exception {

ModelAndView mv = new ModelAndView();

// 添加模型数据

mv.addObject(“message”, “Hello World!”);

// 设置逻辑视图名,最终视图地址=前缀+逻辑视图名+后缀

mv.setViewName(“hello”);

return mv;

}

}

org.springframework.web.servlet.mvc.Controller:处理器必须实现Controller 接口。

ModelAndView:包含了模型数据及逻辑视图名

第九步:后端控制器配置

在springmvc-servlet.xml文件配置如下:

name=”/hello.action” :前边配置的BeanNameUrlHandlerMapping,表示如过请求的URL为“上下文/hello.action”,则将会交给该Bean进行处理。

第十步:视图开发

创建/WEB-INF/jsp/hello.jsp视图页面:

pageEncoding=”UTF-8”%>

第一个程序

${message}

${message}:表示显示由HelloWorldController处理器传过来的模型数据。

第十一步:部署在tomcat测试

总结:

主要进行如下操作:

前端控制器DispatcherServlet配置

加载springmvc的配置文件

HandlerMapping配置

HandlerAdapter配置

ViewResolver配置

前缀和后缀

后端控制器编写

后端控制器配置

视图编写

从上边的步骤可以看出,通常情况下我们只需要编写后端控制器和视图。

6.HandlerMapping处理器映射器

HandlerMapping 给前端控制器返回一个HandlerExecutionChain 对象(包含一个Handler (后端控制器)对象、多个HandlerInterceptor 拦截器)对象。

BeanNameUrlHandlerMapping

beanName Url映射器

将后端控制器的bean name作为请求的url。

SimpleUrlHandlerMapping

hello_controller

hello_controller

可定义多个url映射至一个后端控制器,hello_controller为后端控制器bean的id。

7.HandlerAdapter处理器适配器

HandlerAdapter会把后端控制器包装为一个适配器,支持多种类型的控制器开发,这里使用了适配器设计模式。

SimpleControllerHandlerAdapter

简单控制器处理器适配器.

所有实现了org.springframework.web.servlet.mvc.Controller接口的Bean作为Springmvc的后端控制器。

适配器配置如下:

HttpRequestHandlerAdapter

HTTP请求处理器适配器.

HTTP请求处理器适配器将http请求封装成HttpServletResquest和HttpServletResponse对象,和servlet接口类似。

适配器配置如下:

Controller实现如下:

publicclass HelloWorldController2 implements HttpRequestHandler {

@Override

publicvoid handleRequest(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {

request.setAttribute(“message”, “HelloWorld!”);

request.getRequestDispatcher(“/WEB-INF/jsp/hello.jsp”).forward(request, response);

// 也可以自定义响应内容

//response.setCharacterEncoding(“utf-8”);

//response.getWriter().write(“HelloWorld!”);

}

}

从上边可以看出此适配器器的controller方法没有返回ModelAndView,可通过response修改定义响应内容。

8.Controller控制器

AbstractCommandController(命令控制器)

该控制器能把请求参数封装到一个命令对象(模型对象)中。

public class MyCommandController extends AbstractCommandController {

/**

* 通过构造函数设置命令对象

*/

public MyCommandController(){

this.setCommandClass(Student.class);

this.setCommandName(“student”);//不是必须设置

}

@Override

protected ModelAndView handle(HttpServletRequest request,

HttpServletResponse response, Object command, BindException errors)

throws Exception {

Student student = (Student)command;

System.out.println(student);

Return null;

}

/**

* 字符串转换为日期属性编辑器

*/

@Override

Protected void initBinder(HttpServletRequest request,

ServletRequestDataBinder binder) throws Exception {

binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat(“yyyy-MM-dd”),true));

}

}

publicclass Student {

public Student() {

}

public Student(String name) {

this.name = name;

}

private String name;//姓名

private Integer age;//年龄

private Date birthday;//生日

private String address;//地址

….get/set方法省略

Controller配置;

使用命令控制器完成查询列表及表单提交

代码略

9.问题解决

日期格式化

在controller注册属性编辑器:

/**

* 注册属性编辑器(字符串转换为日期)

*/

@InitBinder

public void initBinder(HttpServletRequest request,ServletRequestDataBinder binder) throws Exception {

binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat(“yyyy-MM-dd”),true));

}

Post时中文乱码

在web.xml中加入:

CharacterEncodingFilter

org.springframework.web.filter.CharacterEncodingFilter

encoding

utf-8

CharacterEncodingFilter

/*

以上可以解决post请求乱码问题。

对于get请求中文参数出现乱码解决方法有两个:

修改tomcat配置文件添加编码与工程编码一致,如下:

另外一种方法对参数进行重新编码:

String userName new String(request.getParamter(“userName”).getBytes(“ISO8859-1”),”utf-8”)

ISO8859-1是tomcat默认编码,需要将tomcat编码后的内容按utf-8编码

10.注解开发

第一个例子

创建工程的步骤同第一个springmvc工程,注解开发需要修改handlermapper和handlMapperAdapter,如下:

在springmvc-servlet.xml中配置:

注解映射器和注解适配器可以使用 代替。

默认注册了注解映射器和注解适配器等bean。

HelloWorldController编写:

@Controller

publicclass HelloWorldController {

@RequestMapping(value=”/hello”)

public String hello(Model model)throws Exception{

model.addAttribute(“message”, “HelloWorld!”);

return”hello”;

}

}

注解描述:

@Controller:用于标识是处理器类

@RequestMapping:请求到处理器功能方法的映射规则

Controller配置

在springmvc-servlet.xml中配置定义的controller:

组件扫描

扫描 @component 、@controller、@service、@repository 的注解

注意:如果使用组件扫描则controller不需要在springmvc-servlet.xml中配置

11.与struts2不同

springmvc的入口是一个servlet即前端控制器,而struts2入口是一个filter过虑器。

springmvc是基于方法开发,请求参数传递到方法的形参,可以设计为单例或多例(建议单例),struts2是基于类开发,传递参数是通过类的属性,只能设计为多例。

Struts采用值栈存储请求和响应的数据,通过OGNL存取数据, springmvc通过参数解析器是将request请求内容解析,并给方法形参赋值,将数据和视图封装成ModelAndView对象,最后又将ModelAndView中的模型数据通过reques域传输到页面。Jsp视图解析器默认使用jstl。

注意:

不要在action类中定义方法所用到的变量,变量要定义到方法体中。因为方法是在栈内存中,不会导致线程问题。

12.@Controller

标识该类为控制器类,@controller、@service、@repository 分别对应了web应用三层架构的组件即控制器、服务接口、数据访问接口。

13.@RequestMapping

URL路径映射

@RequestMapping(value=”/user”)或@RequestMapping(“/user”)

根路径+子路径

根路径:

@RequestMapping 放在类名上边,如下:

@Controller

@RequestMapping(“/user”)

子路径:

@RequestMapping 放在方法名上边,如下:

@RequestMapping(“/useradd”)

public String useradd(….

URI 模板模式映射

@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”;

}

实现restFul,所有的url都是一个资源的链接,有利于搜索引擎对网址收录。

多个占位符:

@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”;

}

页面:

修改

请求方法限定

限定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

GET和POST都可以

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

14.请求数据绑定(重点)

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

如下:

@RequestMapping(“/userlist”)

public String userlist(

HttpServletRequest request,

HttpServletResponse response,

HttpSession session,

Model model

)

默认支持的参数类型

HttpServletRequest

通过request对象获取请求信息

HttpServletResponse

通过response处理响应信息

HttpSession

通过session对象得到session中存放的对象

session.setAttribute(“userinfo”, student);

session.invalidate(); // 使session失效

Model

通过model向页面传递数据,如下:

model.addAttribute(“user”, new User(“李四”));

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

命令/表单对象

自动将请求参数绑定到功能处理方法的命令/表单对象上。

Controller方法通过形参接收命令/表单对象。

Java基本数据类型

布尔型:

页面如下:

用户状态:

整型

例子略

单精度/双精度

例子略

日期型需要添加属性编辑器:

@InitBinder

Public void initBinder(HttpServletRequest request,ServletRequestDataBinder binder) throws Exception {

binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat(“yyyy-MM-dd”),true));

例子略

Pojo对象

页面上以pojo对象中属性名称命名:

将pojo对象中的属性名于传递进来的属性名对应,如果传进来的参数名称和对象中的属性名称一致则将参数值设置在pojo对象中

页面定义如下;

Contrller方法定义如下:

public String useraddsubmit(Model model,User user)throws Exception{

System.out.println(user);

}

页面上以pojo对象名点属性名命名:

如果采用类似struts中对象.属性的方式命名,需要将pojo对象作为一个包装对象的属性,action中以该包装对象作为形参。

包装对象定义如下:

Public class UserVo {

private User user;

public User getUser() {

return user;

}

Public void setUser(User user) {

this.user = user;

}

}

页面定义:

Controller方法定义如下:

public String useraddsubmit(Model model,UserVo userVo)throws Exception{

System.out.println(userVo.getUser());

}

字符串数组

使用情景:页面提交批量数据以数组接受

页面定义如下:

页面选中多个checkbox向controller方法传递

${student.id}${student.name}

传递到controller方法中的格式是:001,002,003

Controller方法中可以用String[]接收,定义如下:

@RequestMapping(“/deleteStudent”)

public String deleteStudent(String[] deleteids)throws Exception {

return “editStudentSubmit”;

}

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;

}

}

Public class UserVo {

Private List scores;//成绩

//get/set方法..

}

包装类中定义List对象,并添加get/set方法如下:

private List scores;//成绩

页面:

课程成绩:

课程名:成绩:

课程名:成绩:

课程名:成绩:

Contrller方法定义如下:

public String useraddsubmit(Model model,UserVo userVo)throws Exception{

System.out.println(userVo.getScores ());

}

Map

在包装类中定义Map对象,并添加get/set方法,action使用包装对象接收。

包装类中定义Map对象如下:

Public class UserVo {

private Mapstudentinfo = new HashMap();

//get/set方法..

}

页面定义如下:

学生信息:

姓名:

年龄:

.. .. ..

15.拦截器

定义

Spring Web MVC 的处理器拦截器类似于Servlet 开发中的过滤器Filter,用于对处理器进行预处理和后处理。

SpringMVC拦截器是针对mapping配置的拦截器

拦截器定义

实现HandlerInterceptor接口,如下:

Public class HandlerInterceptor1 implements HandlerInterceptor{

/**

* controller执行前调用此方法

* 返回true表示继续执行,返回false中止执行

* 这里可以加入登录校验、权限拦截等

*/

@Override

Public boolean preHandle(HttpServletRequest request,

HttpServletResponse response, Object handler) throws Exception {

Return false;

}

/**

* controller执行后但未返回视图前调用此方法

* 这里可在返回用户前对模型数据进行加工处理,比如这里加入公用信息以便页面显示

*/

@Override

Public void postHandle(HttpServletRequest request,

HttpServletResponse response, Object handler,

ModelAndView modelAndView) throws Exception {

}

/**

* controller执行后且视图返回后调用此方法

* 这里可得到执行controller时的异常信息

* 这里可记录操作日志,资源清理等

*/

@Override

Public void afterCompletion(HttpServletRequest request,

HttpServletResponse response, Object handler, Exception ex)

throws Exception {

}

}

拦截器配置

针对某种mapping配置拦截器

class=”org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping”>

针对所有mapping配置全局拦截器

正常流程测试

代码:

0b157b3e110b

定义两个拦截器分别为:HandlerInterceptor1和HandlerInteptor2,每个拦截器的preHandler方法都返回true。

运行流程

HandlerInterceptor1..preHandle..

HandlerInterceptor2..preHandle..

HandlerInterceptor2..postHandle..

HandlerInterceptor1..postHandle..

HandlerInterceptor2..afterCompletion..

HandlerInterceptor1..afterCompletion..

中断流程测试

代码:

定义两个拦截器分别为:HandlerInterceptor1和HandlerInteptor2。

运行流程

HandlerInterceptor1的preHandler方法返回false,HandlerInterceptor2返回true,运行流程如下:

HandlerInterceptor1..preHandle..

从日志看出第一个拦截器的preHandler方法返回false后第一个拦截器只执行了preHandler方法,其它两个方法没有执行,第二个拦截器的所有方法不执行,且controller也不执行了。

HandlerInterceptor1的preHandler方法返回true,HandlerInterceptor2返回false,运行流程如下:

HandlerInterceptor1..preHandle..

HandlerInterceptor2..preHandle..

HandlerInterceptor1..afterCompletion..

从日志看出第二个拦截器的preHandler方法返回false后第一个拦截器的ostHandler没有执行,第二个拦截器的postHandler和afterCompletion没有执行,且controller也不执行了。

总结:

preHandle按拦截器定义顺序调用

postHandler按拦截器定义逆序调用

afterCompletion按拦截器定义逆序调用

postHandler在拦截器链内所有拦截器返成功调用

afterCompletion只有preHandle返回true才调用

拦截器应用

用户身份认证

Public class LoginInterceptor implements HandlerInterceptor{

@Override

Public boolean preHandle(HttpServletRequest request,

HttpServletResponse response, Object handler) throws Exception {

//如果是登录页面则放行

if(request.getRequestURI().indexOf(“login.action”)>=0){

return true;

}

HttpSession session = request.getSession();

//如果用户已登录也放行

if(session.getAttribute(“user”)!=null){

return true;

}

//用户没有登录挑战到登录页面

request.getRequestDispatcher(“/WEB-INF/jsp/login.jsp”).forward(request, response);

return false;

}

}

发表评论

表情:
评论列表 (有 0 条评论,319人围观)

还没有评论,来说两句吧...

相关阅读

    相关 spring MVC入门

    2.1、Spring Web MVC是什么 Spring Web MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架