SpringMVC框架

项目搭建流程

详见昨天笔记

请求参数传递及编码问题

SpringMVC框架可以丰常方便地接收用户的请求参数,而且也可以帮助我们自动封装成相应的对象

SpringMVC支持如下方式来获取用户的请求参数

  1. 直接在方法中,添加相关的实体类对象[PO, pojo]或是值对象[VO, Value Object]【比较常用】

//示例代码

   @Controller
   public class UserController {
       
       @RequestMapping("/user/register")
       /*****************
        * 此处要求,页面表单项中的name属性值要和User对象的属性名保持一致,这个是约定
        */
       public String register(User user,Model model) {
           //...再做进一步的业务处理
       }
   }
  1. 直接在方法中,添加单个表单项的参数【比较常用】

//示例代码

   @Controller
   public class UserController {
       
       @RequestMapping("/user/register")
       /*****************
        * 如果请求参数的名字与方法中的参数名不一样,我们有两种做法:
        * 1. 修改方法中的参数名与页面表单项中的name属性值一样
        * 2. 使用 @RequestParam 注解来修饰方法参数,使得名字与页面表单项中的name属性值一样
        */
       public String login(String username, String pwd, Model model) {
           //...再做进一步的业务处理
       }
   }
  1. 传统的代码,也就是原生的Servlet代码 【不可取,不建议使用】

//示例代码

   @Controller
   public class UserController {
       @RequestMapping("/user/register")
       public void register(HttpServletRequest req, HttpServletResponse resp) {
           //通过req对象来获取用户的请求参数
           String userName = req.getParameter("name");
           String pwd = req.getParameter("password");
           String realName = req.getParameter("realName");
           //还要进一步封装
           User user = new User();
           user.setUserName(userName);
           user.setPassword(pwd);
           user.setRealName(realName);
           //....再做进一步的业务处理
           ....
           //绑定信息到request范围
           req.setAttribute("key",xxxx);
           //转发或重定向
           String targetURL = "/jsp/xxx.jsp";
           req.getRequestDispatcher(targetURL).forward(req,resp);
       }
   }

编码问题

为什么会有乱码?

​ 数据的编码和解码不一致造成的。

​ 在WEB应用中,请求的数据会根据method的类型不同,采用不同的位置来传输,如果是get请求,则数据封装到请求头[Header]中传输,如果是post请求,则数据封装到请求体部[body]传输

​ 通过request.setCharacterEncoding方法,只能修改请求体部的编码,影响不了头部。

解决方案:

  1. 添加 编码过滤器, SpringMVC已经提供了一个编码过滤器 org.springframework.web.filter.CharacterEncodingFilter ,它只能影响POST请求

  2. 在容器中,修改相关的配置项,以Tomcat为例,在$CATALINA_HOME/conf/server.xml中的 标记中,增加一个 URIEncoding=“UTF-8” 属性。它会影响请求头的编码

  3. 如果你使用maven中Tomcat7插件的话,则只需要在 插件的配置中,添加一个属性:

   <plugin>
       <groupId>org.apache.tomcat.maven</groupId>
       <artifactId>tomcat7-maven-plugin</artifactId>
       <version>2.2</version>
           <configuration>
              <port>8888</port>
              <!-- 影响请求头的编码 -->
              <uriEncoding>utf-8</uriEncoding>
           </configuration>
   </plugin>

注:以上的2 和 3本质是一样的。

静态资源访问

在SpringMVC提供的前置控制器[大C],它有如下的匹配模式

  • 采用 *.xxx 来匹配,这种匹配模式叫扩展名匹配,它是基于后缀来匹配的,它的优点是不会拦截静态资源【像css, 图片,js之类的,只要大C的扩展名与静态资源扩展名不一样即可】,缺点是它不支持 Restful风格的URL。
  • 采用 / 来匹配,这种匹配模式叫通配匹配,它可以匹配一切,优点完全支持Restful风格的URL,缺点是所有的静态资源也会被拦截,性能差一点。现在是主流【推荐】

如何在采用/匹配模式下,不让大C去拦截静态资源呢? 有如下三种方式:

  1. 利用容器本身的Servlet处理器,也叫默认处理器,在web.xml中,要配置在大C之前,如下:
   <servlet-mapping>
    <servlet-name>default</servlet-name>
       <url-pattern>*.png</url-pattern>
   </servlet-mapping>

这种方式有两个缺点:

  • 配置比较冗长,每一段servlet-mapping,只能处理一个扩展名
  • 不同的WEB容器,这个默认的servlet-name是不一样的,如下:
    • Tomcat 对应的是 default
    • WebLogic 对应的是 FileServlet
    • Websphere 对应的是 xxx [可以自已去查]

所以,不建议大家使用

  1. 在 xxx-servlet.xml 配置文件中,添加一个 配置,如下:
   ....
   <mvc:default-servlet-handler/>

它会自动帮助我们选择一个默认的容器提供的 Servlet处理器

  1. 在 xxx-servlet.xml配置文件中,通过 <mvc:resources> 来添加静态资源
   ...
   <mvc:resources mapping="" location=""/>

注:以上三种方式都是基于 xml 配置的,下面我们可以通过注解达到相同的目的

  1. WebMvcConfig 配置类中,重写父类WebMvcConfigurerAdapter 中的addResourceHandlers方法,如下:
   @Override
   public void addResourceHandlers(ResourceHandlerRegistry registry) {
      LOGGER.debug("--- 进入addResourceHandlers方法...");
      //
     registry.addResourceHandler("/images/**").addResourceLocations("/images/");
   }

注:此方法需要注意一点:

​ 如果你的静态资源是放在 resources 目录下,则在addResourcelocations方法中,需要加上”classpath:” 前缀,如果放在 webapp目录下,则不需要添加 “classpath:” 前缀

  1. WebMvcConfig 配置类中,重写父类WebMvcConfigurerAdapter 中的configureDefaultServletHandling方法,如下:
   @Override
   public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
       LOGGER.debug("--- 进入configureDefaultServletHandling方法...");
       configurer.enable();
   }

注:相当于在xml中,添加了

   <mvc:default-servlet-handler/>

建议:使用第一种方案

视图解析器的配置

默认情况下,没有指定视图解析器时,我们在控制器的方法中,需要编写完整的目标资源路径. 当然,我们也可以为项目配置一个视图解析器,方便我们的开发

注解的配置步骤:

  1. WebMvcConfig 配置类中,添加一个 @Bean 方法,在这个方法中,创建一个InternalResourceViewResolver 对象,并设置相关的属性,如下:
   @Bean
   public InternalResourceViewResolver internalResourceViewResolver() {
     //创建InternalResourceViewResolver
     InternalResourceViewResolver irvr = new InternalResourceViewResolver();
     //设置属性
     irvr.setPrefix("/WEB-INF/jsp/");  //指定前缀
     irvr.setSuffix(".jsp");           //指定后缀
     //设置视图处理类 [可选,默认就是 JstlView.class ]
     irvr.setViewClass(JstlView.class);
     //
     return irvr;
   }
  1. 然后,在你的控制器的方法中,直接返回 目标jsp文件的名字即可,无需使用 全路径。

有关转发和重定向

有SpringMVC框架中,我们同样可以指定请求是转发[forward]还是重定向[redirect], 方法如下:

在 控制器方法的返回字符中中,添加两个前缀:

  1. forward: 表示 转发,默认就是这个, 但是,我们在返回值中,加与没有加 forward前缀是有很大差别的,如果加了 forward: 前缀,则会无视配置的视图解析器
  2. redirect: 表示重定向