SpringMVC学习(一)基础

1.SpringMVC执行流程

Spring的web框架围绕着DispatcherServlet设计.DispatcherServlet的作用是将请求分发到不同的处理器.

执行流程:

1.用户发送请求,DispatcherServlet接收并拦截. DispatcherServlet表示前置控制器,是整个SpringMVC的控制中心.
2. DispatcherServlet对请求URL进行解析,得到请求资源标识符(URI)。然后根据该URI,调用HandlerMapping获得该Handler配置的所有相关的对象(包括Handler对象以及Handler对象对应的拦截器),最后以HandlerExecutionChain对象的形式返回;
3. DispatcherServlet 根据获得的Handler,选择一个合适的HandlerAdapter。(附注:如果成功获得HandlerAdapter后,此时将开始执行拦截器的preHandler(…)方法)
4. 提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)。 在填充Handler的入参过程中,根据你的配置,Spring将帮你做一些额外的工作:
HttpMessageConveter: 将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息
数据转换:对请求消息进行数据转换。如String转换成Integer、Double等
数据根式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等
数据验证: 验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中
5. Handler 执行完成后,向DispatcherServlet 返回一个ModelAndView对象;
6. 根据返回的ModelAndView,选择一个适合的ViewResolver(必须是已经注册到Spring容器中的 ViewResolver)返回给DispatcherServlet ;
7. ViewResolver 结合Model和View,来渲染视图
8. 将渲染结果返回给客户端

配置SpringMVC(不使用注解)

1.配置web.xml , 注册DispatcherServlet


<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
        version="4.0">

   <!--1.注册DispatcherServlet-->
   <servlet>
       <servlet-name>springmvc</servlet-name>
       <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
       <!--关联一个springmvc的配置文件:【servlet-name】-servlet.xml-->
       <init-param>
           <param-name>contextConfigLocation</param-name>
           <param-value>classpath:springmvc-servlet.xml</param-value>
       </init-param>
       <!--启动级别-1-->
       <load-on-startup>1</load-on-startup>
   </servlet>

   <!--/ 匹配所有的请求;(不包括.jsp)-->
   <!--/* 匹配所有的请求;(包括.jsp)-->
   <servlet-mapping>
       <servlet-name>springmvc</servlet-name>
       <url-pattern>/</url-pattern>
   </servlet-mapping>

</web-app>

2.编写SpringMVC 的 配置文件!名称:springmvc-servlet.xml : [servletname]-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"
      xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

  <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>

<!--视图解析器:DispatcherServlet给他的ModelAndView-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
   <!--前缀-->
   <property name="prefix" value="/WEB-INF/jsp/"/>
   <!--后缀-->
   <property name="suffix" value=".jsp"/>
</bean>
</beans>

3.创建HelloController ,实现Controller 接口

public class HelloController implements Controller {

   public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
       //ModelAndView 模型和视图
       ModelAndView mv = new ModelAndView();

       //封装对象,放在ModelAndView中。Model
       mv.addObject("msg","HelloSpringMVC!");
       //封装要跳转的视图,放在ModelAndView中
       mv.setViewName("hello"); //: /WEB-INF/jsp/hello.jsp
       return mv;
  }
   
}

将HelloController 注入到spring中


<!--Handler-->
<bean id="/hello" class="com.abc.controller.HelloController"/>

就可以使用了

配置SpringMVC(使用注解)

开发之中还是使用注解的
1.第一步还是配置web.xml,内容也一样


<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
        version="4.0">

   <!--1.注册servlet-->
   <servlet>
       <servlet-name>SpringMVC</servlet-name>
       <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
       <!--通过初始化参数指定SpringMVC配置文件的位置,进行关联-->
       <init-param>
           <param-name>contextConfigLocation</param-name>
           <param-value>classpath:springmvc-servlet.xml</param-value>
       </init-param>
       <!-- 启动顺序,数字越小,启动越早 -->
       <load-on-startup>1</load-on-startup>
   </servlet>

   <!--所有请求都会被springmvc拦截 -->
   <servlet-mapping>
       <servlet-name>SpringMVC</servlet-name>
       <url-pattern>/</url-pattern>
   </servlet-mapping>

</web-app>

2.配置springmvc-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
       https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc
       https://www.springframework.org/schema/mvc/spring-mvc.xsd">

   <!-- 自动扫描包,让指定包下的注解生效,由IOC容器统一管理 -->
   <context:component-scan base-package="com.kuang.controller"/>
   <!-- 让Spring MVC不处理静态资源 -->
   <mvc:default-servlet-handler />
   <!--
   支持mvc注解驱动
       在spring中一般采用@RequestMapping注解来完成映射关系
       要想使@RequestMapping注解生效
       必须向上下文中注册DefaultAnnotationHandlerMapping
       和一个AnnotationMethodHandlerAdapter实例
       这两个实例分别在类级别和方法级别处理。
       而annotation-driven配置帮助我们自动完成上述两个实例的注入。
    -->
   <mvc:annotation-driven />

   <!-- 视图解析器 -->
   <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
         id="internalResourceViewResolver">
       <!-- 前缀 -->
       <property name="prefix" value="/WEB-INF/jsp/" />
       <!-- 后缀 -->
       <property name="suffix" value=".jsp" />
   </bean>

</beans>

3.创建Controller

@Controller
@RequestMapping("/HelloController")
public class HelloController {

   //真实访问地址 : 项目名/HelloController/hello
   @RequestMapping("/hello")
   public String sayHello(Model model){
       //向模型中添加属性msg与值,可以在JSP页面中取出并渲染
       model.addAttribute("msg","hello,SpringMVC");
       //web-inf/jsp/hello.jsp
       return "hello";
  }
}

@Controller是为了让Spring IOC容器初始化时自动扫描到;

@RequestMapping是为了映射请求路径,这里因为类与方法上都有映射所以访问时应该是/HelloController/hello;

方法中声明Model类型的参数是为了把Action中的数据带到视图中;

方法返回的结果是视图的名称hello,加上配置文件中的前后缀变成WEB-INF/jsp/hello.jsp。

然后就可以使用了.

通过设置ServletAPI , 不需要视图解析器

@Controller
public class ResultGo {

   @RequestMapping("/result/t1")
   public void test1(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
       rsp.getWriter().println("Hello,Spring BY servlet API");
  }

   @RequestMapping("/result/t2")
   public void test2(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
       rsp.sendRedirect("/index.jsp");
  }

   @RequestMapping("/result/t3")
   public void test3(HttpServletRequest req, HttpServletResponse rsp) throws Exception {
       //转发
       req.setAttribute("msg","/result/t3");
       req.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(req,rsp);
  }

}

通过SpringMVC来实现转发和重定向 - 无需视图解析器;

@Controller
public class ResultSpringMVC {
   @RequestMapping("/rsm/t1")
   public String test1(){
       //转发
       return "/index.jsp";
  }

   @RequestMapping("/rsm/t2")
   public String test2(){
       //转发二
       return "forward:/index.jsp";
  }

   @RequestMapping("/rsm/t3")
   public String test3(){
       //重定向
       return "redirect:/index.jsp";
  }
}

通过SpringMVC来实现转发和重定向 - 有视图解析器;

@Controller
public class ResultSpringMVC2 {
   @RequestMapping("/rsm2/t1")
   public String test1(){
       //转发
       return "test";
  }

   @RequestMapping("/rsm2/t2")
   public String test2(){
       //重定向
       return "redirect:/index.jsp";
       //return "redirect:hello.do"; //hello.do为另一个请求/
  }

}

Restful风格

如果使用普通访问localhost:8080/add?a=1&b=2 就能访问了

@Controller
public class RestFulController{  
  //映射路径
  @RequestMapping("/add")
  public String index(int a,int b,Model model){
   int sum = a+b;
   model.addAttribute("sum",sum);
   return "test";
  }
}

如果使用Restful,地址为localhost:8080/add/1/2
需要在参数上添加@PathVariable

@Controller
public class RestFulController{  
  //映射路径
  @RequestMapping("/add/{a}/{b}")
  public String index(@PathVariable int a,@PathVariable int b,Model model){
   int sum = a+b;
   model.addAttribute("sum",sum);
   return "test";
  }
}

Restful更加高效和安全

数据处理

处理提交数据

@PathVariable

@PathVariable可以将占位符绑定参数列表

@RequestMapping("/hello/{name}")
public String hello(@PathVariable("name") String name){
   System.out.println(name);
   return "hello";
}

1、提交的域名称和处理方法的参数名一致

@RequestMapping("/hello")
public String hello(String name){
   System.out.println(name);
   return "hello";
}

2、提交的域名称和处理方法的参数名不一致

@RequestParam 来映射请求参数 (request里的值)
属性:
1.value 值即为请求参数名
2.required 该参数是否必须,默认true 必须
3.defaultValue 请求参数的默认值

//@RequestParam("username") : username提交的域的名称 .
@RequestMapping("/hello")
public String hello(@RequestParam("username") String name){
   System.out.println(name);
   return "hello";
}

3、提交的是一个对象
名称写对,会自动匹配,支持级联属性

@RequestMapping("/user")
public String user(User user){
   System.out.println(user);
   return "hello";
}


4.请求头

@RequestHeader

@RequestHeader绑定请求头的属性值

@RequestMapping("/user")
public String user(@RequestHeader(value="Accept-Language") string a){
   System.out.println(a);//输出请求头里的数据
   return "hello";
}

@CookieValue

@CookieValue
可以处理方法入参绑定某个cookie值

@RequestMapping("/user")
public String user(@CookieValue(value="sessionId",required=false) string a){
   System.out.println(a);//输出sessionId
   return "hello";
}

数据显示到前端
第一种 : 通过ModelAndView

SpringMVC会把ModelAndView中的model放到request域中

public class ControllerTest1 implements Controller {

   public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
       //返回一个模型视图对象
       ModelAndView mv = new ModelAndView();
       mv.addObject("msg","ControllerTest1");
       mv.setViewName("test");
       return mv;
  }
}

第二种 : 通过ModelMap

@RequestMapping("/hello")
public String hello(@RequestParam("username") String name, ModelMap model){
   //封装要显示到视图中的数据
   //相当于req.setAttribute("name",name);
   model.addAttribute("name",name);
   System.out.println(name);
   return "hello";
}

第三种 : 通过Model (也可以说是Map,ModelMap类型)

@RequestMapping("/ct2/hello")
public String hello(@RequestParam("username") String name, Model model){
   //封装要显示到视图中的数据
   //相当于req.setAttribute("name",name);
   model.addAttribute("msg",name);
   System.out.println(name);
   return "test";
}
@RequestMapping("/ct2/hello")
public String hello(@RequestParam("username") String name, Map map){

   map.put("name","123");

   return "test";
}

Model 只有寥寥几个方法只适合用于储存数据,简化了新手对于Model对象的操作和理解;

ModelMap 继承了 LinkedMap ,除了实现了自身的一些方法,同样的继承 LinkedMap 的方法和特性;

ModelAndView 可以在储存数据的同时,可以进行设置返回的逻辑视图,进行控制展示层的跳转。

@SessionAttributes

只能放在类的上面,不能放在方法上面

@SessionAttributes(value={“name”} ,types={String.class})
value是根据名字放入session, types是根据数据类型放入session

@SessionAttributes(value={"name"})//name会被同时放入session域和request域
@Controller
public class SpringMvcController{

@RequestMapping("/ct2/hello")
public String hello( Map<Object,String> map){
   map.put("name","123");
   return "test";
}

}

@ModelAttributes

有 @ModelAttributes标记的方法,会在每个目标方法执行之前被SpringMVC调用

可以解决一些修改时的问题
运行流程:
1.执行@ModelAttributes注解表示的方法:从数据库抽取对象,把对象放入Map中
2.SpringMVC从Map中抽取对象,并且把前端表单发来的参数赋值给该对象
3.SpringMVC把上述对象传入目标方法的参数列表
注意:@ModelAttributes注解表示的方法中存入Map的对象的名字要和目标方法的参数类型的名称(第一个字母小写)一致,或者和目标方法的参数类型中有:@ModelAttribute(value="")的value值一致.

SpringMVC确定目标方法POJO类型入参的过程:
1.确定一个key:
(1)若目标方法的POJO类型的参数没有使用@ModelAttributes,则key为POJO类名第一个字母小写
(2)若目标方法的POJO类型的参数使用了@ModelAttributes,则key为@ModelAttributes的value属性值
2.在implicitModel中查找key对应的对象,若存在,则作为入参传入
(1)若在@ModelAttributes标记的方法中在map中保存过,且key和第一步确定的key一致,则会获取到.
3.若在implicitModel中不存在key对应的对象,则检查当前Handler是否使用@sessionAttributes注解修饰
(1)若使用@sessionAttributes注解修饰,且@sessionAttributes注解的value值包含了key,则会从httpsession中获取key所对应的value值,若存在则直接传入目标方法,若不存在则抛出异常.
4.若Handler没有表示@sessionAttributes或者@sessionAttributes中vlaue值不含key,则通过反射来创建POJO对象,传入目标方法参数
5.SpringMVC会把key和value保存到implicitModel中,进而会保存到request中

源码分析的流程:
1.调用@ModelAttribute注解修饰的方法,实际上把@ModelAttribute方法中Map中的数据放在了implicitModel中,
2.解析请求处理器的目标参数,实际上该目标参数来自于WebDataBinder对象的target属性
(1)创建WebDataBinder对象:
a.确定obejctName属性:
*.若目标使用了@ModelAttribute来修饰,则attrName为value值
*.若传入的attrName属性为"",则objectName为类名第一个字母小写
b.确定target属性:
*.在implicitModel中查找attrName对应的属性值,若存在就OK了,若不存在则验证当前Handler是否使用了@sessionAttributes进行修饰,若使用了,则尝试从session中获取attrName所对应的属性值,若session中没有对应的属性值就报错.
*.若Handler没有使用@sessionAttributes进行修饰,或者@sessionAttributes中没有使用value值指定key和attrName相匹配,则通过反射创建了POJO对象.
(2)SpringMVC把表单传过来的参数赋值给WebDataBinder的target对应的属性
(3)SpringMVC会把WebDataBinder的attrName和target给到implicitModel中,进而传到request域
(4)把WebDataBinder的target作为参数传递给目标方法的入参

@MultipartResolver 实现文件上传

springMVC默认没有装配MultipartResolver ,因此如果想使用文件上传功能,需要配置MultipartResolver
需要commons-fileupload.jar,commons-io.jar

springmvc.xml中配置MultipartResolver

<bean id="multipartResolver " class="org.springframework.web.mutipart.commons.CommonsMultipartResolver">
  <property name="defaultEncoding" value="UTF-8"></property>
  <property name="maxUploadSize" value="1024000"></property>
</bean>

Controller层代码,处理上传的文件

@RequestMapping("/MultipartResolverUpload")
public String test(@RequestParam("file") MultipartFile file){
     System.out.println("filename"+file.getOriginalFilename());    
     return "success";    
}

自定义拦截器

1.写实现类,实现HandlerInterceptor接口

public class FirstInterceptor implements HandlerInterceptor{}

2.配置文件中配置自定义拦截器


<mvc:interceptors>
<!--配置自定义拦截器-->
<bean class="com.abc.Controller.FirstInterceptor "></bean>
</mvc:interceptors>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值