Spring MVC

Spring MVC的五大核心组件

  DispatcherServlet     控制器    请求的入口 
  HandlerMapping        控制器    派发请求  让请求和控制器建立一一对应的关联关系 
  Controller            控制器    真正的请求的处理者
  ModelAndView          模型和视图   封装了数据信息和视图信息
  ViewResolver          视图处理器  

Spring MVC 的编程步骤

  1 建立一个项目 导入jar包(ioc mvc)  拷贝Spring 配置文件到src下 
     在WEB-INF下建立 hello.jsp 

  2 在web.xml 中 配置DispatcherServlet   并通过初始化参数 contextConfigLocation  
	来指定spring配置文件的位置

  3 在Spring 配置文件中  配置HandlerMapping的实现类SimpleUrlHandlerMapping  
     并通过mappings 属性让请求和控制器建立一一对应的关联关系

	<!--  配置HandlerMapping的实现类   通过mappings 属性 建立请求和控制器的对应关系 -->
	<bean id="handlerMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
		<property name="mappings">
			<props>
				<prop key="/login.do">loginController</prop>
			</props>
		</property>
	</bean>
	<!--  配置Controller 对象  -->	
	<bean id="loginController" class="com.xdl.controller.LoginController"></bean>		

  4 编写一个java 类  实现 Controller 接口    覆盖接口方法  返回 ModelAndView  
     同时在Spring 容器中创建 Controller 的实现类的对象 

	public class LoginController implements Controller {

		@Override
		public ModelAndView handleRequest(HttpServletRequest arg0, HttpServletResponse arg1) throws Exception {
			ModelAndView mav = new ModelAndView();
			mav.setViewName("login");
			return mav;
		}
	
	}		

  5 在Spring 配置文件中 配置ViewResolver的实现类  InternalResourceViewResolver 
     需要配置 前缀 和  后缀 

基于标注的SpringMVC

   1.建立一个项目 导入jar包(ioc aop mvc) 拷贝到配置文件到src下 并在WEB-INF下建立一个login.jsp

	<form action="login4.do">
		账号:<input type="text" name="name"/><br>
		密码:<input type="password" name="pass"/><br>
			<input type="submit" value="登录"/>
	</form>

   2.在web.xml 中配置DispathcherServlet 通过contextConfigLocation 关联spring 配置文件

	<!-- 配置DispathcherServlet -->
	<servlet>
		<servlet-name>SpringMvc</servlet-name>
	  	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
	  	<init-param>
	  		<param-name>contextConfigLocation</param-name>
	  		<param-value>classpath:applicationContext.xml</param-value>
	  	</init-param>
	</servlet>
	<servlet-mapping>
	  	<servlet-name>SpringMvc</servlet-name>
	  	<url-pattern>*.do</url-pattern>
	</servlet-mapping>

   3.开启组件扫描 和 标注形式mvc

   <context:component-scan base-package="包名"/>
   <mvc:annotation-driven />
   (这句配置帮你在spring 容器中创建一个 RequestMappingHandlerMapping对象)

	<context:component-scan base-package="com.xdl"></context:component-scan>
	<mvc:annotation-driven></mvc:annotation-driven>

   4.编写一个控制器类 不用实现Controller 接口 使用@Controller 把普通的Java类转换成控制器
	使用 @RequestMapping("请求路径") 设置请求地址
    返回值可以是String 也可以是ModelAndView 方法名自由(参数自由)

	public class LoginController {

		@RequestMapping("/tologin.do")
		public String tologin() {
			return "login";
		}
	}

   5.配置视图处理器 配置前缀 和 后缀

	<!--  配置ViewResolver --> 
	<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/"></property>
		<property name="suffix" value=".jsp"></property>
	</bean>	

Spring MVC 控制器中如何接收请求的参数

   1.之前的方式依然可以使用 就是通过request 来获取
	request.getParameter("name")

	@RequestMapping("/login.do")
	public String login(HttpServletRequest request) {
		String name=  request.getParameter("name");
		String pass = request.getParameter("pass");
		System.out.println(name+" 1 "+pass);
		return "main";
	}

   2.直接定义和页面参数 同名的控制器参数

	@RequestMapping("/login2.do")
	public String login2(String name,String pass) {
		
		System.out.println(name+" 2 "+pass);
		return "main";
	}

   3.页面参数 和 控制器参数不一致
	@RequestPrarm("页面参数名")控制器参数上

	@RequestMapping("/login3.do")
	public String login3(@RequestParam("name")String ssname,
							@RequestParam("pass")String safdasgdpass) {
		
		System.out.println(ssname+" 3 "+safdasgdpass);
		return "main";
	}

   4.定义对象类型的控制器参数 (要求属性 和 请求的参数对应)

	@RequestMapping("/login4.do")
	public String login2(Bank bank) {
		
		System.out.println(bank);
		return "main";
	}

如何把控制器的数据传递给页面

  1.1 使用域对象传递数据 
     request   session  ServletContext

	  request.setAttribute("name", name);
	  request.getSession().setAttribute("name", name);

  1.2 使用ModelAndView 传递数据 
      //mav.getModel().put("acc_no", acc_no);
	  //mav.getModelMap().put(key, value)

	  mav.getModelMap().addAttribute("acc_no", acc_no);

  1.3 使用Model 传递数据 

      m.addAttribute("key",value)

  1.4 使用ModelMap 传递数据    

      mm.addAttribute("key",value)
  	  mm.put("key",value)

  1.5 使用自定义类型的控制器参数 直接进行传递 
      @ModelAttribute("account")  可以改变默认传递的名字 
	  默认为类型首字母小写

Spring MVC 中如何实现重定向

  2.1 当控制器方法返回String 时
      使用redirect: 完成重定向
	  使用forward:  完成转发

	@RequestMapping("/register7.do")
	public String regiest7(Bank bank) {
		if(!"qqq".equals(bank.getName()) && bank.getPass().equals("123")) {
			
			//return "redirect:toLogin.do";
			return "forward:toLogin.do";
		}
		return "register";
	}

	需要配置一个中间商
	@RequestMapping("/toLogin.do")
	public String tologin() {
		return "login";
	}

  2.2 当控制器方法返回ModelAndView时
  RedirectView  重定向的view

	@RequestMapping("/register8.do")
	public ModelAndView regiest8(Bank bank, ModelAndView mav) {
		if(!"qqq".equals(bank.getName()) && bank.getPass().equals("123")) {
			
			RedirectView rv = new RedirectView("toLogin.do");
			mav.setView(rv);
			return mav;
			
		}
		else {
			
			mav.setViewName("register");;
			return mav;
		}
	}

中文参数乱码问题

  tomcat8   get 方式没有乱码

  3.1 之前的解决方案依然可用    但必须完全遵守之前的方式 
   request.setCharacterEncoding("utf-8")

  3.2 编码过滤器 
   <!--  配置一个编码过滤器  -->

  <filter>
       <filter-name>CharacterEncoding</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>CharacterEncoding</filter-name>
       <url-pattern>*.do</url-pattern>
  </filter-mapping>

拦截器

  4.1  拦截器接口的三个方法   实现HandlerInterceptor  
  	preHandle    在HandlerMapping 之后    Controller 之前调用   这个方法返回 false
  				 代表终止后续调用  如果返回true 代表继续后续调用。
  	postHandle   控制器之后   视图处理器之前
	afterCompletion   视图处理器之后 响应之前 

  4.2 拦截器的使用步骤 

    a.搭建一个基于标注的 spring MVC(让用户发起登录  如果账号不是 abc 密码是123 
      则登录成功   登录成功就把账号放入session中  重定向到 main.jsp。如果登录失败则提示用户
      登录失败。)
    b.写一个拦截器  实现HandlerInterceptor 接口   

	public class MyCheckLoginInterceptor implements HandlerInterceptor {

		@Override
		public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
				throws Exception {
			System.out.println("afterCompletion");
	
		}
	
		@Override
		public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
				throws Exception {
			System.out.println("postHandle");
	
		}
	
		@Override
		public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object method) throws Exception {
			String name = request.getParameter("name");
			String pass = request.getParameter("pass");
			Object sname =request.getSession().getAttribute("name");
			Object spass =request.getSession().getAttribute("pass");
			System.out.println(name+" ."+pass+" ."+sname+" ."+spass );
			
			if(sname != null) {
				return true;
			}
			return false;
		}
	
	}

    c.在Spring 配置文件中   配置拦截器  

    <!--  配置拦截器  -->
    <mvc:interceptors>
      <mvc:interceptor>
          //拦截的路径  比如 /*  拦截所有的一级请求   /** 拦截所有请求
 	      <mvc:mapping path=""/>
 	      //不拦截的请求    可以有多个
          <mvc:exclude-mapping path=""/>
          //拦截器对象
          <bean></bean>
      </mvc:interceptor>
     </mvc:interceptors>	

	<mvc:interceptors>
		<mvc:interceptor> 
			<mvc:mapping path="/**" />
			<mvc:exclude-mapping path="/toregister.do" />
			<mvc:exclude-mapping path="/tologin.do" />
			<mvc:exclude-mapping path="/login.do" />
			<mvc:exclude-mapping path="/register.do" />
			<bean class="com.xdl.interceptor.MyCheckLoginInterceptor"/>
		</mvc:interceptor>
	</mvc:interceptors> 

Spring 的异常处理

1 配置一个系统提供的异常处理器  
出现什么异常  就跳转到对应的页面

@RequestMapping("/toLogin2.do")
public String toLogin2() throws Exception {
	
	  if(1 == 1) throw new Exception("兄嘚!崩了....");
	 
	return "login";
}

<!--  配置系统提供的异常处理器  -->
<bean  id="exceptionResolver"  
    class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    <property name="exceptionMappings">
        <props>
            <prop key="java.lang.Exception">error2</prop> 
            <prop key="java.lang.RuntimeException">error</prop> 
        </props>
    </property>
</bean>

2 全局处理 ---- 自定义异常处理器 
实现HandlerExceptionResolver   
让对应的异常 跳转到对应的页面 

@Controller
public class resolveException implements HandlerExceptionResolver {

	@Override
	public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object method,
			Exception e) {
		ModelAndView mav = new ModelAndView();
		if(e instanceof RuntimeException) {
			mav.setViewName("error");
		}else if(e instanceof Exception) {
			mav.setViewName("error2");
		}
		
		return mav;
	}

}

3 局部异常处理   ---  只针对一个具体的控制器起作用    (异常方法中Exception的参数必须有)

@ExceptionHandler
public  String  foo(Exception  e) {
	System.out.println(e.getMessage());
	return  "error3";
}   

文件上传

1 写一个文件上传的页面    注意三点  第一必须以post 提交    enctype="multipart/form-data"
type="file" 

<form action="Upload.do" method="post" enctype="multipart/form-data"> 
	账号:<input type="text" name="name" /><br/>
	头像:<input type="file" name="head_img" /><br/>
	<input type="submit" value="上传"><br/>
</form>

2 编写一个文件上传的控制器   接收文件数据 和 非文件数据 
这个控制器 需要依赖于文件解析器     文件解析器依赖于文件上传的jar 

bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
 	<property name="maxUploadSize" value="10240"></property>
 	<!-- 推迟全局异常的抛出 -->
 	<property name="resolveLazily" value="true"></property>
 </bean>  

Spring MVC的控制器方法 如何返回 JSON

1 搭建一个基于标注的MVC

2 在控制器中 编写一个控制器方法     
@RequestMapping("/请求的路径")
public  要转换成JSON的数据类型    方法名任意(参数任意){

}

3 为了处理返回的数据为JSON  需要加一个@ResponseBody
(把数据转换成JSON 同时告知mvc 返回值不要经过视图处理器) 
这个标注要依赖于  JSON的转换包  

@RequestMapping("/login2.do")
@ResponseBody
public Bank login2(Bank bank) {
	if("abc".equals(bank.getName()) && "123".equals(bank.getPass()) ) {
		
		return bank;
	}
	return null;
	
}

什么rest

REST即表述性状态传递(英文:Representational State Transfer,简称REST)
是Roy Fielding博士在2000年他的博士论文中提出来的一种软件架构风格。
这个软件架构基于http 协议 
它可以提高系统的可伸缩性   降低应用之间的耦合度   便于分布式应用程序的开发。

rest 的两个核心规范

定位资源的URL做了限定 
把原来基于操作的设计   改成了基于资源的设计 
对资源的操作的做了限定
Http 协议的请求方式上   Get 用来查询  Post 增加     Put  更新    Delete  删除 

什么是restful

符合rest 风格和约束的应用程序 叫restful

Spring MVC 对rest 的支持

1 搭建一个基于标注的 MVC

2 在控制器方法上   支持对应的请求方式
@RequestMapping(value="/account/{变量名}",method=RequestMethod.GET)

3 获取路径变量上的值 

@PathVariable("路径变量名")  加在控制器参数上 
@RequestMapping(value="/login.do/{id}",method=RequestMethod.GET)
@ResponseBody
public Bank login(@PathVariable("id")int id, Bank bank) {
	bank = new Bank(id,"aa","123",123);
	return bank;
}

4 rest 请求的路径 是没有后缀的  
所以需要把DispatcherServlet 中的 url-parttern  改成  支持所有请求的   /

5 如果 改成 /  则所有的静态资源被拦截 

<mvc:default-servlet-handler/> 这段表示静态资源放行
原文地址:https://www.cnblogs.com/lzy1212/p/13609048.html