SpringMVC--26
@Spring mvc基本概念 1,DispatcherServlet:前端控制器(分配功能:Model/View) 2,Controller:调用业务逻辑生成model的地方 3.HandlerAdapter:DispatcherServlet通过HandlerAdaprter调用controller 4.HandlerInterceptor:拦截器接口,该接口提供after postHandle perHandle 三个方法,调用controlller前后使用。 5.HandlerMapping:前端控制器与controller映射关系的类 6.HandlerExecutionChain:preHandle--->Controller method--->postHandle-->afterCompletion的执行链 7、ModelAndview:model的具体表现 8.viewResolver:视图解析器,决定需要用哪个视图来进行视图的呈现 9.view:界面

DispatcherServelet是前端控制器 HandlerAdapter相当于controller, DispatcherServelet调用各种HandlerAdapter来实现任务分发给相关的业务逻辑 HandlerInterceptor是一个接口,可以用来在Handler调用之前,之后,以及view呈现后可以做很多事情 HandlerMapping是负责确定DispatcherServelet与controller之间映射的类,告诉DispatcherServelet,在请求到来后,由哪个controller来响应这个请求

Maven是一个构建依赖管理的工具,主要三个方面:
POM:就是一个xml文件(pom.xml),包含很多信息,主要是依赖关系。通过配置完成我们的依赖管理。 Dependency:web应用程序中可能会依赖很多包,而引入的包可能还会依赖其他的包,这样依赖关系的层次会很深传递关系很长,导致lib下的包非常多。但开发人员往往不知道包之间的依赖层次关系,可能会耗费很大的精力去处理包间依赖的关系。maven为我们提管理了直接依赖关系和传递依赖关系,是透明的,不需要我们干预。 Coordinates(坐标):maven像一个仓库,各厂商都往里发布产品。通过groupId,atifactId,version,packaging(缺省为jar)可以确定一个项目的坐标,就可以唯一标识一个产品。
mvn archetype:generate -DgroupId=imooc-arthur -DartifactId=spring-mvc-study -DarchetypeArtifactId=maven-archetype-webapp
mvn调用maven的运行环境 archetype:generate 调用插件 groupId:坐标 artifactId:坐标的一个元素,目录结构的根目录名称 archetypeArtifactId:目录类型的一个类型,此为webapp的类型 使用 mvn archetype:generate -DgroupId=imooc-pegasus -DartifactId=spring-mvc-learning -DarchetypeArtifactId=maven-archetype-webapp 在运行到 Generating project in Interactive mode 这里会卡住 使用下面的这个就会成功 mvn archetype:generate -DarchetypeCatalog=internal -DgroupId=imooc-pegasus -DartifactId=spring-mvc-learning -DarchetypeArtifactId=maven-archetype-webapp
====================================================================================================================================
配置流程
web.xml 所有的web项目都要有最基本的配置文件,所有框架监听器、servlet都在这里配置;
mvc-dispatcher-servlet.xml:配置的是springmvc控制器层的相关配置,类似于struts2框架的struts.xml; applicattionContext.xml:这个是spring Bean容器的配置文件; Ioc:依赖注入AOP面向切面相关的配置,LOC主要是管理全局对象,如Session、Dao、Servlce之类的,
Aop:面向切面起到了过滤器的作用,一般用作事务管理1.配置web.xml
:是maven自动生成的使用的是2.3.dtd的标准,该标准默认关闭EL表达式,如果想使用EL表达式可以使用2.4及以上的标准<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <display-name>Spring MVC Study</display-name> <!-- Spring应用上下文, 理解层次化的ApplicationContext --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/configs/spring/applicationContext*.xml</param-value> </context-param> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <!-- DispatcherServlet, Spring MVC的核心 --> <servlet> <servlet-name>mvc-dispatcher</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- DispatcherServlet对应的上下文配置, 默认为/WEB-INF/$servlet-name$-servlet.xml --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/configs/spring/mvc-dispatcher-servlet.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>mvc-dispatcher</servlet-name> <!-- mvc-dispatcher拦截所有的请求--> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
2.配置mvc-dispatcher-servlet.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!-- 本配置文件是工名为mvc-dispatcher的DispatcherServlet使用, 提供其相关的Spring MVC配置 --> <!-- 启用Spring基于annotation的DI, 使用户可以在Spring MVC中使用Spring的强大功能。 激活 @Required @Autowired,JSR 250's @PostConstruct, @PreDestroy and @Resource 等标注 --> <context:annotation-config /> <!-- DispatcherServlet上下文, 只管理@Controller类型的bean, 忽略其他型的bean, 如@Service 交给Spring处理--> <context:component-scan base-package="com.imooc.mvcdemo"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" /> </context:component-scan> <!-- HandlerMapping, 无需配置, Spring MVC可以默认启动。 DefaultAnnotationHandlerMapping annotation-driven HandlerMapping --> <!-- 扩充了注解驱动,可以将请求参数绑定到控制器参数 --><!--可以将url中的参数,映射到方法的输入参数--> <mvc:annotation-driven /> <!-- 静态资源处理, css, js, imgs --> <mvc:resources mapping="/resources/**" location="/resources/" /> <!-- 配置ViewResolver。 可以用多个ViewResolver。 使用order属性排序。 InternalResourceViewResolver放在最后。 --> <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"> <property name="order" value="1" /> <property name="mediaTypes"> <map> <entry key="json" value="application/json" /> <entry key="xml" value="application/xml" /> <entry key="htm" value="text/html" /> </map> </property> <property name="defaultViews"> <list> <!-- JSON View --> <bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"> </bean> </list> </property> <property name="ignoreAcceptHeader" value="true" /> </bean> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" /> <property name="prefix" value="/WEB-INF/jsps/" /> <property name="suffix" value=".jsp" /> </bean> <!--200*1024*1024即200M resolveLazily属性启用是为了推迟文件解析,以便捕获文件大小异常 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="maxUploadSize" value="209715200" /> <property name="defaultEncoding" value="UTF-8" /> <property name="resolveLazily" value="true" /> </bean> </beans>
3.配置applicattionContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:annotation-config />
<context:component-scan base-package="com.imooc.mvcdemo">
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
</context:component-scan>
</beans>
====================================================================================================================Controller开发
通过Controller、Annotation声明了一个Controller。 通过RequestMapping(类级别和方法级别二者结合)映射了URl和方法。 通过URL template, 结合使用@PathVariable和@RequestParam两个标记,可以将URL路径之中的参数绑定到Controller的Method中的入参。 使用HttpServletRequest或HttpSession获取相关属性。
@Controller
@RequestMapping("/courses")
// /courses/**
public class CourseController {
private static Logger log = LoggerFactory.getLogger(CourseController.class);
//业务的依赖
private CourseService courseService;
@Autowired
public void setCourseService(CourseService courseService) {
this.courseService = courseService;
}
//本方法将处理 /courses/view?courseId=123 形式的URL
//Model是SpringMVC中特有的,可以添加模型对象。
//Integer courseId ==@RequestParam("courseId") Integer courseId
@RequestMapping(value="/view", method=RequestMethod.GET)
public String viewCourse(Integer courseId,
Model model) {
log.debug("In viewCourse, courseId1111 = {}", courseId);
Course course = courseService.getCoursebyId(courseId);
//放置到model中名字叫course,在jsp页面course.title引用属性
model.addAttribute(course);
return "course_overview";
}
//本方法将处理 /courses/view2/123 形式的URL
@RequestMapping("/view2/{courseId}")
public String viewCourse2(@PathVariable("courseId") Integer courseId,
Map<String, Object> model) {
log.debug("In viewCourse2, courseId2222 = {}", courseId);
Course course = courseService.getCoursebyId(courseId);
model.put("course",course);
return "course_overview";
}
//本方法将处理 /courses/view3?courseId=123 形式的URL
@RequestMapping("/view3")
public String viewCourse3(HttpServletRequest request) {
Integer courseId = Integer.valueOf(request.getParameter("courseId"));
Course course = courseService.getCoursebyId(courseId);
request.setAttribute("course",course);
return "course_overview";
}
====================================================================================================================================================
@RequestMapping(value="/admin", method = RequestMethod.GET, params = "add")
public String createCourse(){
return "course_admin/edit";
}
//可以把表单上的数据绑定到参数model上面(表单name要和bean 属性名一致)
@RequestMapping(value="/save", method = RequestMethod.POST)
public String doSave(@ModelAttribute Course course){
log.debug("Info of Course:");
//将对象转换为键值对的形式输出
log.debug(ReflectionToStringBuilder.toString(course));
//在此进行业务操作,比如数据库持久化
course.setCourseId(123);
//redirect/forward:url (请求重定向或请求转发)
return "redirect:view2/"+course.getCourseId();
}
@RequestMapping(value="/upload", method=RequestMethod.GET)
public String showUploadPage(@RequestParam(value= "multi", required = false) Boolean multi){
if(multi != null && multi){
return "course_admin/multifile";
}
return "course_admin/file";
}
@RequestMapping(value="/doUpload", method=RequestMethod.POST)
public String doUploadFile(@RequestParam("file") MultipartFile file) throws IOException{
if(!file.isEmpty()){
log.debug("Process file: {}", file.getOriginalFilename());
FileUtils.copyInputStreamToFile(file.getInputStream(), new File("c:\\temp\\imooc\\", System.currentTimeMillis()+ file.getOriginalFilename()));
}
return "success";
}
@RequestMapping(value="/doUpload2", method=RequestMethod.POST)
public String doUploadFile2(MultipartHttpServletRequest multiRequest) throws IOException{
Iterator<String> filesNames = multiRequest.getFileNames();
while(filesNames.hasNext()){
String fileName =filesNames.next();
MultipartFile file = multiRequest.getFile(fileName);
if(!file.isEmpty()){
log.debug("Process file: {}", file.getOriginalFilename());
FileUtils.copyInputStreamToFile(file.getInputStream(), new File("c:\\temp\\imooc\\", System.currentTimeMillis()+ file.getOriginalFilename()));
}
}
return "success";
}
@RequestMapping(value="/{courseId}",method=RequestMethod.GET)
public @ResponseBody Course getCourseInJson(@PathVariable Integer courseId){
return courseService.getCoursebyId(courseId);
}
@RequestMapping(value="/jsontype/{courseId}",method=RequestMethod.GET)
public ResponseEntity<Course> getCourseInJson2(@PathVariable Integer courseId){
Course course = courseService.getCoursebyId(courseId);
return new ResponseEntity<Course>(course, HttpStatus.OK);
}
}
@edit.jsp
<link rel="stylesheet"
href="<%=request.getContextPath()%>/resources/css/main.css"
type="text/css" />
</head>
<body>
<div id="main">
<div class="newcontainer" id="course_intro">
<form name="mainForm" action="<%= request.getContextPath()%>/courses/save" method="post">
<div>
<span>课程名称:</span><input type="text" id="title" name="title">
</div>
<div>
<span>课程时长:</span><input type="text" id="duration" name="duration"> 秒
</div>
<div>
<span>课程难度:</span>
<select id="level" name="level">
<option value="0">初级</option>
<option value="1" selected="selected">中级</option>
<option value="2">高级</option>
</select>
</div>
<div>
<span>课程介绍:</span>
<textarea id="descr" name="descr" rows="5" style="width:480px"></textarea>
</div>
<div>
<input type="submit" id="btnPass" value="提交" />
</div>
</form>
</div>
</div>
</body>
</html>
===========================================================================================================================
文件上传
@pom.xml
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
@mvc-dispatcher-servlet
<!--200*1024*1024即200M resolveLazily属性启用是为了推迟文件解析,以便捕获文件大小异常 -->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="209715200" />
<property name="defaultEncoding" value="UTF-8" />
<property name="resolveLazily" value="true" />
</bean>
@contrller
@RequestMapping(value="/upload", method=RequestMethod.GET)
public String showUploadPage(@RequestParam(value= "multi", required = false) Boolean multi){
if(multi != null && multi){
return "course_admin/multifile";
}
return "course_admin/file";
}
@RequestMapping(value="/doUpload", method=RequestMethod.POST)
public String doUploadFile(@RequestParam("file") MultipartFile file) throws IOException{
if(!file.isEmpty()){
log.debug("Process file: {}", file.getOriginalFilename());
FileUtils.copyInputStreamToFile(file.getInputStream(), new File("c:\\temp\\imooc\\", System.currentTimeMillis()+ file.getOriginalFilename()));
}
return "success";
}
@RequestMapping(value="/doUpload2", method=RequestMethod.POST)
public String doUploadFile2(MultipartHttpServletRequest multiRequest) throws IOException{
Iterator<String> filesNames = multiRequest.getFileNames();
while(filesNames.hasNext()){
String fileName =filesNames.next();
MultipartFile file = multiRequest.getFile(fileName);
if(!file.isEmpty()){
log.debug("Process file: {}", file.getOriginalFilename());
FileUtils.copyInputStreamToFile(file.getInputStream(), new File("c:\\temp\\imooc\\", System.currentTimeMillis()+ file.getOriginalFilename()));
}
}
return "success";
}
@file.jsp
<link rel="stylesheet" href="<%=request.getContextPath()%>/resources/css/main.css" type="text/css" />
</head>
<body>
<div align="center">
<h1>上传附件</h1>
<!-- enctype="multipart/form-data"文件上传必须有的属性 -->
<form method="post" action="/courses/doUpload" enctype="multipart/form-data">
<input type="file" name="file"/>
<input type="submit"/>
</form>
</div>
</body>
</html>
=============================================================================================================================
Json格式
在Spring中使用@ResponseBody注解标注业务方法,将业务方法的返回值做成json输出给页面。
@Responsebody与@RequestBody
@Responsebody表示该方法的返回结果直接写入HTTP response body中
一般在异步获取数据时使用,在使用@RequestMapping后,返回值通常解析为跳转路径,
比如异步获取json数据,加上@Responsebody后,会直接返回json数据。
加上@Responsebody后返回结果不会被解析为跳转路径,而是直接写入HTTP response body中。
扩展:@PathVariable获取请求路径中的变量
@controller
//json格式
@RequestMapping(value="/{courseId}",method=RequestMethod.GET)
public @ResponseBody Course getCourseInJson(@PathVariable Integer courseId){
return courseService.getCoursebyId(courseId);
}
@RequestMapping(value="/jsontype/{courseId}",method=RequestMethod.GET)
public ResponseEntity<Course> getCourseInJson2(@PathVariable Integer courseId){
Course course = courseService.getCoursebyId(courseId);
return new ResponseEntity<Course>(course, HttpStatus.OK);
}
@pom.xml
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
@mvc-dispatcher-servlet
<!-- 配置ViewResolver。 可以用多个ViewResolver。 使用order属性排序。 InternalResourceViewResolver放在最后。 -->
<bean
class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="order" value="1" />
<property name="mediaTypes">
<map>
<entry key="json" value="application/json" />
<entry key="xml" value="application/xml" />
<entry key="htm" value="text/html" />
</map>
</property>
<property name="defaultViews">
<list>
<!-- JSON View -->
<bean
class="org.springframework.web.servlet.view.json.MappingJackson2JsonView">
</bean>
</list>
</property>
<property name="ignoreAcceptHeader" value="true" />
</bean>
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsps/" />
<property name="suffix" value=".jsp" />
</bean>
在前端使用ajax异步处理,触发请求,在请求的url中传入id,到后台之后,后台根据url,分解出pathVariable ,调用service方法,获得数据对象,然后返回@ResponseBody,此时,前台的ajax正在监听服务端的状态,如果是成功状态,将触发回调函数,函数中封装了对数据的逻辑,也就是使用js技术把数据对号入座,并且美化,展示页面。 请求路径是一种restful风格。 @RequestMapping(“/xxx/{xxId}”) @PathVariable--Integer--xxId
@spingMVC通过使用ContentNegotiatingViewResover将相同格式的数据分发到不同的view请求中 @ResponseEntity/@ResponseBody将通过返回的数据转换为json @RequestBoby获取页面提交的json格式的数据
==============================================================================================================
学习springMVC:
1)宏观上要牢记springMVC思想就是将业务数据的抽取和业务数据的呈现相分离。 2)中观的层面要了解springMVC的流程以及流程中各个部分如何相互协作,在此基础上需要注意哪些是配置的哪些是需要编写的。 3)微观上就是能进行很好的开发,如基本controller的编写、数据绑定、文件上传、json协同。