SpringMVC--26

本文深入讲解SpringMVC的工作原理,包括DispatcherServlet的功能、Controller的开发、HandlerAdapter的作用、HandlerInterceptor的使用、HandlerMapping的配置、ModelAndView的数据封装、ViewResolver的解析流程、以及Maven在项目构建中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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.xmlapplicattionContext.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协同。








































评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值