day60_springMVC
来源:互联网 发布:名片app软件 编辑:程序博客网 时间:2024/06/05 15:17
Springmvc课堂笔记
课程安排:
一天课程内容较多 学习springmvc的框架原理(掌握) 包括哪些组件: 前端控制器(中心) 处理器映射器(三大组件) 处理器适配器(三大组件) 视图解析器(三大组件)第一个springmvc程序强化三大组件学习: 两个处理器映射器 两个处理器适配器 一个视图解析器(jsp+jstl)命令控制器(过期的,了解)Springmvc注解开发(重点) 学习springmvc常用的注解 Json数据转换(掌握) 拦截器(了解)
1 springmvc的框架原理
1.1 b/s系统mvc原理
mvc是什么?mvc是设计模式。
1.2springmvc是什么?
Mvc的框架,是spring框架的一个模块。
1.3springmvc框架原理
1、用户发起请求,请求到DispatcherServlet前端控制器DispatcherServlet(中央调度),负责request和response,负责调用处理器映射器查找Handler,负责调用处理器适配器执行Handler,有了前端控制器降低了各各组件之间的耦合性,系统扩展性提高。2、DispatcherServlet前端控制器请求处理器映射器HandlerMapping查找Handler根据用户请求的url,根据一定的规则去查找(比如:xml配置,注解)3、HandlerMapping处理器映射器将Handler返回给前端控制器4、DispatcherServlet前端控制器调用HandlerAdapter处理器适配器执行Handler程序员编写的Handler是按照适配器要求的规则去执行Handler5、HandlerAdapter处理器适配器执行Handler适配器按照一定规则去执行Handler6、Handler执行完成,返回ModelAndViewModelAndView是springmvc的封装对象,将model和view封装在一起。7、HandlerAdapter处理器适配器将ModelAndView返回给前端 控制器8、前端控制器调用视图解析器,进行视图解析,解析完成给前端控制器返回ViewView是springmvc的封装对象,是一个接口,实现类包括jspview,pdfview。。。。9、前端控制器调用view进行视图渲染将模型数据填充到view(将model数据填充到request)响应给用户10、前端控制器响应给用户。
小结:
一个中心:(不需要开发)
DispatcherServlet前端控制器
三个组件:(不需要开发)
处理器映射器
处理器适配器
视图解析器
Handler:(需要开发)
处理器,理解成action
View:
需要开发页面:jsp
2 Springmvc第一个程序
2.1 统一开发环境
使用eclipse-3.7-indigo 32位
Jdk:1.7.72版本(32位)
Tomcat:apache-tomcat-7.0.53
参考 :Eclipse开发环境配置-indigo.docx
2.2第一程序开发
2.2.1 创建一个web 工程
2.2.2加入 springmvc的jar包
Spring的版本:3.1.4
2.2.3配置前端控制器
在web.xml中配置servlet。
指定 contextConfigLocation让前端控制器找到springmvc的全局配置文件。
2.2.4 配置三大组件
在springmvc.xml中配置:
处理器映射器:
BeanNameUrlHandlerMapping
处理器适配器:
视图解析器:
2.2.5 编写Handler
由于使用SimpleControllerHandlerAdapter适配器,要求编写的Handler实现Controller接口。
需求:向页面显示一行信息“helloworld”
2.2.6 编写jsp
2.2.7 配置Handler
由于使用处理器映射器BeanNameUrlHandlerMapping,要求在spring的容器配置Handler,Handler的name就是url。
在springmvc.xml中配置:
2.2.8 部署tomcat,启动
以debug方式运行。
访问路径:http://localhost:8080/springmvc1215_1/helloworld.action
2.3逻辑视图名
调用:modelAndView.setViewName指定逻辑视图名,如果这里指定jsp的完整路径也支持。
在springmvc.xml中修改视图解析器:
修改action:
3 强化三大组件学习
3.1处理器映射器
作用:根据url找到Handler.
BeanNameUrlHandlerMapping:根据url匹配bean的name 处理器映射器实现了HandlerMapping接口
SimpleUrlHandlerMapping:将url进行集中配置。
<!-- 简单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>
hello_controller是action这个bean的id。
总结:
多个处理器映射器可以共存
3.2处理器适配器
作用:按照一定规则去执行Handler
SimpleControllerHandlerAdapter:规则是Handler要实现Controller接口
HttpRequestHandlerAdapter:规则是Handler要实现HttpRequestHandler接口。
总结:
多个适配器可以共存!
4 命令表单控制器
编写action,继承AbstractCommandController。
运行方式类似struts的modelDriven。
将页面提交的参数封装在一个pojo对象(命令对象)中。
4.1 需求
学生信息修改、提交功能。
进入学生信息修改页面,输入信息,提交,将学生的信息提交到action中。
将页面的参数封装到一个pojo对象(命令对象)中。
4.2 开发
编写两个action类:
修改学生信息页面
修改学生信息提交
注意:
//设置命令对象
this.setCommandClass(Student.class);
4.3 Post乱码
在web.xml中加入:
<filter><filter-name>CharacterEncodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><init-param><param-name>encoding</param-name><param-value>utf-8</param-value></init-param></filter><filter-mapping><filter-name>CharacterEncodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping>
对get乱码处理:
对于get请求中文参数出现乱码解决方法有两个:
修改tomcat配置文件添加编码与工程编码一致,如下:
<Connector URIEncoding="utf-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
另外一种方法对参数进行重新编码:
String userName new String(request.getParamter("userName").getBytes("ISO8859-1"),"utf-8")
ISO8859-1是tomcat默认编码,需要将tomcat编码后的内容按utf-8编码
日期型转换
//注册一个属性编辑器 @Override protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception { //将student类中的birthday属性进行日期转换,类型和birthday一致 binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true)); }
小结
使用命令表单控制器也可以开发增、删、改、查。
使用命令表单控制器一定要指定命令对象,但是只能指定一个命令对象。
5 上午课程小结
开发springmvc程序:
第一步:配置前端控制器
在web.xml配置DispathcherServlet前端控制器
第二步:配置springmvc的全局配置文件
配置三大组件:
处理器映射器:
根据url查找 Handler
处理器适配器:
执行Handler
视图解析器:
解析出视图View,根据逻辑视图名解析出真正的视图。
第三步:按照处理器适配器规则开发Handler(action)
第四步:将Handler配置在spring容器中。
第五步:编写视图(jsp+jstl)
6 学生信息修改注解开发
6.1创建一个web 工程
6.2加入 jar包
6.3配置前端控制器
6.4全局配置文件springmvc.xml
配置注解处理器映射器和适配器:
6.5编写Handler(Action)
// 修改学生信息页面 // @RequestMapping指定url @RequestMapping("/editstudent") public String editstudent(Model model) throws Exception { // 将学生信息的显示在页面 // 使用静态数据 Student student = new Student(); student.setName("张三"); student.setAge(32); student.setBirthday(new Date()); // 需要将学生信息传到页面 model.addAttribute("student", student); // 返回逻辑视图名 return "student/editstudent"; } // 学生信息修改提交 @RequestMapping("/editstudentsubmit") public String editstudentsubmit(Student student)throws Exception{ System.out.println(student); return "success"; }
注意:
一个url对应action的一个方法。
6.6在spring的容器中配置action
使用@Controller注解:
与@Controller注解同类型还有:@Service、@Repository、@Component
@Controller注解作用:
使用spring的组件扫描,自动扫描到action在spring容器中注册。
在springmvc.xml中配置组件扫描:
只扫描action:
6.7部署tomcat运行
运行地址:
学生信息修改:http://localhost:8080/springmvc1215_2/editstudent.action
学生信息修改提交 :http://localhost:8080/springmvc1215_2/editstudentsubmit.action
6.8日期型转换
在action类中添加方法:
建议将此方法定义在父类中,让action类继承此父类。
7 与struts的不同
1、springmvc的入口是servlet,struts是filter2、springmvc是基于方法开发,struts是基于类开发action类中,一个url对应一个方法,对Handler对象,springmvc框架将一个方法封装到Handler中(只有一个method)。Struts对action类进行实例化。Springmvc中的action可以使用单例也可以使用多例,建议使用单例(对相同的方法只new一个)。Struts不能用单例,因为struts传递参数是通过成员变量。Springmvc通过形参接收参数好处:更符合软件开发的思想,和service接口类似。3、Struts采用值栈存储请求和响应的数据,通过OGNL存取数据, springmvc通过参数解析器是将request请求内容解析,并给方法形参赋值,将数据和视图封装成ModelAndView对象,最后又将ModelAndView中的模型数据通过reques域传输到页面。Jsp视图解析器默认使用jstl。
参数解析过程:
7.1 前端控制器代码跟踪
1、前端控制器调用处理器映射器找Handler
2、调用处理器适配器执行Handler
3、视图解析,最终解析出view
4、视图渲染
将model的数据放到request域
8 常用注解
8.1 @controller
标识该类为控制器类,@controller、@service、@repository分别对应了web应用三层架构的组件即控制器、服务接口、数据访问接口
8.2 @RequestMapping
进行url映射,一个方法对应一个url,定义方法:在action方法上定义requestMapping
根路径+子路径
需求:为了很好的管理url,为了避免url的冲突,使用根路径+子路径
定义方法:
根路径:
在类名上边定义requestMapping
子路径:
在方法上边定义requestMapping
最终访问路径:根路径+子路径:/stu/editstudent.action
URI 模板模式映射
将参数在url中传递。
定义方法:
修改学生信息列表页面,将修改链接改为:
URI 模板模式映射好处:方便实现restful。
详细参考 :
请求方法限定
测试,限定为post,
如果不是post请求:
可以限定为get、post、或两者都可以
限定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})
9 请求参数绑定(重点)
Springmvc通过参数解析器,将客户端请求的key/value解析成方法形参数,过程:
参数解析过程:
掌握不同参数类型的解析方方法。
9.1 默认支持的参数类型
HttpServletRequest
通过request对象获取请求信息
HttpServletResponse
通过response处理响应信息
HttpSession
通过session对象得到session中存放的对象
Model
通过model向页面传递数据,如下:
model.addAttribute(“user”, new User(“李四”));
model也可以通过modelMap或map将数据传到页面。
9.2 表单对象-简单类型
Action方法的形参数默认支持:string、int、double等简单类型,建议使用包装类型(可以设置null)。
注意:对于date类型的参数需要注册属性编辑器。
使用方法:
直接在形参上定义
也可以在pojo中通过属性传递简单类型
9.3 表单对象-pojo
9.3.1 使用pojo属性名传递
页面定义:
Action方法的定义:
在形参使用pojo接收上边的参数。
9.3.2 使用pojo点属性名传递
页面定义:
Action方法的定义:
在形参不能直接使用pojo接收上边的参数。
应该使用包装对象接收上边的参数。
Action形参的定义:
9.4 字符串数组绑定
需求:在学生列表上多选,删除学生信息。
页面定义:
Action方法定义:
使用字符串数组接收。
批量删除学生信息方法,接收页面复选框的值(学生id)
9.5 List绑定
页面向action传递复杂的批量数据,比如学生的成绩信息(课程名称、成绩)
页面定义:
Scores:包装对象中list属性的名称
Coursename:包装对象中list中pojo的属性名称。
Score:包装对象中list中pojo的属性名称。
如果上边下标相同的Coursename和Score设置在一个pojo中。
Action方法定义:
使用List接收上边的接收,pojo中包括上边课程名称(coursename)和成绩(score)
List通过包装对象接收。
在UserVo包装中定义属性:List<>
Action方法形参使用包装对象接收list
9.6 @RequestParam绑定单个请求参数
value:参数名字,即入参的请求参数名字,如value=“studentid”表示请求的参数区中的名字为studentid的参数的值将传入;
required:是否必须,默认是true,表示请求中一定要有相应的参数,否则将报400错误码;
defaultValue:默认值,表示如果请求中没有同名参数时的默认值
需求 :
学生查询方法中必须要有一个参数group(学生分组)
实现:
10 结果转发
Redirect:请求重定向
浏览器中地址栏的url通过Redirect变了,重新定义了一个request。
Action方法通过Redirect重定向到另一个方法,方法形参无法带到另一个方法。
定义方法:
Forward:页面转发
浏览器中地址栏的url通过Forward不变,没有重新定义了一个request。
Action方法通过Forward转发到另一个方法,方法形参可以带到另一个方法。
定义方法:
11 @RequestBody @ResponseBody实现json数据交互
Json数据在企业中使用好处:
Json在企业开发中已经作为通用的接口参数类型。
Json数据在页面(客户端)解析很方便。
Json定义:
var obj={”name”:”张三”,”age”:12}//key/value格式
Json数据解析:
obj.name
11.1需求1:
请求json响应json
实现方案:
页面提交数据时,需要将提交的数据传成json进行提交。
Action方法中将json串转成java对象赋值形参
可以使用@RequestBody将请求的json串转成java对象。
11.2需求2
请求的key/value,响应json
实现方案:
Action方法返回的java对象转成 json串。
使用@ResponseBody将action方法返回java对象转成json输出。
11.3实现
Json转换器配置:
1、将json转换的jar包加入工程
2、在处理器适配器上配置Json转换器
编写需求1的代码:
请求json响应json
页面代码:
引入 :jquery-1.4.4.min.js
测试:
编写需求2的代码:
请求key/value,响应的json
测试:
小结:
建议使用需求2方法,请求key/value,为了客户端方便解析结果,响应json。
12 拦截器
拦截器是针对handlerMapping的拦截器,由handlerMapping查找Handler后,将拦截器返回给前端控制器。
12.1 配置拦截器
针对某一个handlerMapping配置拦截器
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"> <property name="interceptors"> <list> <ref bean="handlerInterceptor1"/> <ref bean="handlerInterceptor2"/> </list> </property></bean> <bean id="handlerInterceptor1" class="springmvc.intercapter.HandlerInterceptor1"/> <bean id="handlerInterceptor2" class="springmvc.intercapter.HandlerInterceptor2"/>
间接配置全局拦截器:让springmvc框架自动向每个handlerMapping中注册拦截器
<!--拦截器 --><mvc:interceptors> <!--多个拦截器,顺序执行 --> <mvc:interceptor> <mvc:mapping path="/**"/>//拦截所有请求 <bean class="cn.itcast.springmvc.interceptor.HandlerInterceptor1"></bean> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="cn.itcast.springmvc.interceptor.HandlerInterceptor2"></bean> </mvc:interceptor></mvc:interceptors>
12.2 定义拦截器
实现HandlerInterceptor接口。
public class HandlerInterceptor1 implements HandlerInterceptor { //handler,springmvc根据url找到Handler(只有一个方法) //执行时机:进入Handler方法之前执行,如果返回false表示拦截,如果返回true表示放行 //使用场景:用于用户身份校验,用户权限拦截校验 @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("HandlerInterceptor1..preHandle"); return false; } //执行时机:进入Handler方法之后 ,在返回modelAndView之前 //使用场景:使用modelAndView,向页面传递通用数据,使用统一的view @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("HandlerInterceptor1..postHandle"); } //执行时机:Handler方法执行完成,(modelAndView已经返回) //使用场景:统一异常处理,统一记录系统日志,用于action方法执行监控(在preHandle记录一个时间点,在afterCompletion记录执行结束时间点,将结束时间点减去开始执行时间点,得到执行时长) @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("HandlerInterceptor1..afterCompletion"); }
12.3 测试
两个拦截器都放行
HandlerInterceptor1..preHandle
HandlerInterceptor2..preHandle
HandlerInterceptor2..postHandle
HandlerInterceptor1..postHandle
HandlerInterceptor2..afterCompletion
HandlerInterceptor1..afterCompletion
结论:
preHandle是按照拦截器定义顺序执行,
postHandle和afterCompletion是按照拦截器定义逆向执行。
12.3.2第一个放行第二个不放行
HandlerInterceptor1..preHandle
HandlerInterceptor2..preHandle
HandlerInterceptor1..afterCompletion
结论:
只要有一个拦截器不放行,action方法无法完成。
如果拦截器放行,afterCompletion才会执行。
只要有一个拦截器不放行,postHandle不执行。
两个都不放行
HandlerInterceptor1..preHandle
结论:
只要有一个拦截器不放行,action方法无法完成。
只要有一个拦截器不放行,postHandle不执行。
12.4 拦截器应用
案例:
用户身份认证拦截,用户登陆成功后,系统记录session(用户身份信息),用户去操作url时,拦截器需要校验用户身份是否合法(查看session中是否有用户身份信息,如果没有说明用户身份不合法,不合法重新登陆)
action
@Controllerpublic class LoginAction { //登陆页面 @RequestMapping("/login") public String login(Model model)throws Exception{ return "login"; } //登陆提交 //userid:用户账号,pwd:密码 @RequestMapping("/loginsubmit") public String loginsubmit(HttpSession session,String userid,String pwd)throws Exception{ //向session记录用户身份信息 session.setAttribute("activeUser", userid); return "redirect:stu/querystudent.action"; } //退出 public String logout(HttpSession session)throws Exception{ //session过期 session.invalidate(); return "redirect:stu/querystudent.action"; }}
页面
@Controllerpublic class LoginAction { //登陆页面 @RequestMapping("/login") public String login(Model model)throws Exception{ return "login"; } //登陆提交 //userid:用户账号,pwd:密码 @RequestMapping("/loginsubmit") public String loginsubmit(HttpSession session,String userid,String pwd)throws Exception{ //向session记录用户身份信息 session.setAttribute("activeUser", userid); return "redirect:stu/querystudent.action"; } //退出@RequestMapping("/logout") public String logout(HttpSession session)throws Exception{ //session过期 session.invalidate(); return "redirect:stu/querystudent.action"; }}
拦截器
拦截所有url(将公开地址排除(无需登陆即可操作的url)),校验用户身份是否合法(查看session中是否有用户身份信息,如果没有说明用户身份不合法,不合法重新登陆)
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //判断请求的url是否公开 地址(无需登陆即可操作url) //正常开发时,需要将公开地址配置在配置文件中。 //取出请求的url String url = request.getRequestURI(); if(url.indexOf("loginsubmit.action")>=0){ //说明 公开地址 //放行 return true; } //得到session HttpSession session = request.getSession(); //从 session取出用户身份信息 String userid = (String) session.getAttribute("activeUser"); if(userid!=null){ //说明 用户已登陆(用户身份合法) //放行 return true; } //执行到这里说明 用户身份不合法,拦截,跳转到登陆页面 request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response); return false; }
13<mvc:annotation-driven />
14 与hibernate整合
将spring和hibernate整合好,springmvc作为spring一个模块不用整合。
15 问题
前端控制器调用适配器执行Handler,执行完成后,返回view找不到。
前端控制器调用处理器映射器,找不到Handler
- day60_springMVC
- 策略模式使用的小技巧
- PRML读书笔记——连续潜在变量
- 洛谷 P3384 【模板】树链剖分
- 支持向量积-1
- Java链表之基础应用
- day60_springMVC
- NYOJ-274 正三角形外接圆面积
- 国内composer源(解决composer慢的方法)
- 基础知识—数据类型-第一个C++程序
- tomcat启动后,http://localhost:8080无法正常显示
- HDU 1867 A + B for you again(KMP)
- Spark RDD 创建
- maven下spring ClassPathXmlApplicationContext找不到xml配置文件的问题
- 算法导论(Exercise 4.1-2)