MVC思想将一个应用部分分成三个基本部分,有输

2019-10-05 18:22栏目:美高梅开户送58元官网
TAG:

这一部分介绍一下我发现的在 Spring MVC 下进行输入处理以及验证信息反馈方面的一些思路。完整的示例代码见 GitHub。

一、MVC思想

  • MVC思想简介:

 MVC并不是java所特有的设计思想,也不是Web应用所特有的思想,它是所有面向对象程序设计语言都应该遵守的规范;MVC思想将一个应用部分分成三个基本部分:Model、View和Controller,这三个部分以最少的耦合协同工作,从而提高应用的可扩展性和可维护性;

MVC特点:

  • 多视图对应一个模型。按MVC模式,一个模型对应多个视图,可以减少代码的复制和维护量,这样一旦模式改变,易于维护;
  • 模型返回的数据和显示的逻辑分离。模型数据可以使用任何的显示技术,例如jsp、velocity模板或直接产生excel文档等;
  • 应用被分割为三层,降低了各层之间的耦合,提高了应用的可扩展性;
  • 控制层的概念很有效,他把不同的模型和不同的视图组合在一起,完成不同的请求。因此,控制层可以说包含了用户请求权限的概念;
  • MVC更符合软件工程化管理的精神,每一层的组件具有相似的特点,有利于通过工程化和工具化的方法产生管理程序代码;

spring mvc运行步骤:

  1. 首先用户发送请求

  2. DispatcherServlet——>BeanNameUrlHandlerMapping进行请求到处理的映射,BeanNameUrlHandlerMapping将“/hello”路径直接映射到名字为“/hello”的Bean进行处理,即HelloWorldController,BeanNameUrlHandlerMapping将其包装为HandlerExecutionChain(只包括HelloWorldController处理器,没有拦截器);

  3. DispatcherServlet——> SimpleControllerHandlerAdapter,SimpleControllerHandlerAdapter将HandlerExecutionChain中的处理器(HelloWorldController)适配为SimpleControllerHandlerAdapter;

  4. SimpleControllerHandlerAdapter——> HelloWorldController处理器功能处理方法的调用,SimpleControllerHandlerAdapter将会调用处理器的handleRequest方法进行功能处理,该处理方法返回一个ModelAndView给DispatcherServlet;

  5. 美高梅开户送58元官网 ,hello(ModelAndView的逻辑视图名)——>InternalResourceViewResolver, InternalResourceViewResolver使用FreeMarkerView,具体视图页面在classpath:/templates/hello.ftl;

  6. FreeMarkerView(classpath:/templates/hello.ftl)——>渲染,将在处理器传入的模型数据(message=HelloWorld!)在视图中展示出来;

  7. 返回控制权给DispatcherServlet,由DispatcherServlet返回响应给用户,到此一个流程结束。

到此HelloWorld就完成了,主要进行了如下配置:

  1. 前端控制器DispatcherServlet;

  2. HandlerMapping

  3. HandlerAdapter

  4. ViewResolver

  5. 处理器/页面控制器

  6. 视图

目前我所构建的 spring boot 的服务都是 REST 风格的 API 了,很多时候处理的都是 json 的数据。在获取的 HTTP 请求中,BODY 中所传的也都不再是表单而是一个 json 了。看了很多的例子发现在 demo 中喜欢直接把输入转化成一个实体对象。比如我要注册用户,那么我就直接把请求中的 json 映射成一个 User,多方便。但是很明显,它只能处理简单的情况,强行使用容易把真正的业务实体中加入很多诡异的功能,比如什么 password confirm,这都是以前很多代码中会出现的。实际上就算是处理表单型的数据,也早就有了 form object 的概念了,不能够说换成 json 就倒回去吧,说白了这依然是个表单而已。

二、SpringMvc的前端控制器DispatcherServlet

在许多的MVC框架中,都包含一个用于调度控制的Servlet。Spring MVC也提供了一个名为org.springframework.web.servlet.DispatcherServlet的Servlet充当前端控制器,所有的请求驱动都围绕这个DispatcherServlet来分派请求。

DispatcherServlet是一个Servlet(继承自httpServlet基类),在使用时需要把他配置到web.xml文件中,配置信息如下:

<servlet>    <!-- servlet的名称 -->    <servlet-name>springmvc</servlet-name>    <!-- servlet对应的java类 -->    <servlet-class>        org.springframework.web.servlet.DispatcherServlet    </servlet-class>        <!-- 当前Servlet的参数信息 -->    <init-param>        <!-- contextConfigLocation是参数名称,该参数的值包含SpringMVC的核心配置文件路径-->        <param-name>contextConfigLocation</param-name>        <param-value>/WEB-INF/springmvc-config.xml</param-value>    </init-param>    <!-- 在tomcat启动时立即加载servlet -->    <load-on-startup>1</load-on-startup></servlet><!-- servlet映射声明 --><servlet-mapping>    <!-- 请求对用的servlet名称 -->    <servlet-name>springmvc</servlet-name>    <!-- 监听当前所有请求 -->    <url-pattern>/</url-pattern></servlet-mapping>

web.xml配置

<servlet>
    <servlet-name>helloworld</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:config/spring-mvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>helloworld</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

美高梅网上游戏 ,load-on-startup:表示启动容器时初始化该Servlet; url-pattern:表示哪些请求交给Spring Web MVC处理, “/” 是用来定义默认servlet映射的。也可以如“*.html”表示拦截所有以html为扩展名的请求。 自此请求已交给Spring Web MVC框架处理,因此我们需要配置Spring的配置文件,默认DispatcherServlet会加载WEB-INF/[DispatcherServlet的Servlet名字]-servlet.xml配置文件。本示例为WEB-INF/helloworld-servlet.xml。

有输入就要有验证,表单验证一直是一个非常蛋疼的问题,一方面它有很多内容很无聊,比如检查非空呀,控制输入的类型呀,判断长度呀,需要一个标准的方法避免这种重复的代码。另一方面,有的时候验证中又存在业务逻辑,那到底把这个验证放到哪里以及用神马方法验证都是一个很容易让人犹豫不决的事情。

三、SpringMvc的后端控制器Handle

  • 实现Controller接口
  • 注解

   DispatcherServlet在Spring当中充当前端控制器的角色,他的核心功能是分发请求,请求会被分发给对应处理的java类,Spring MVC 中称为Handle;Controller接口的实现类只能处理一个单一请求动作,而Spring2.5之后新增的基于注解的控制器可以支持同时处理多个请求动作,并且无需实现任何接口,更加灵活

在Spring配置文件中配置HandlerMapping、HandlerAdapter

/src/main/resources/config/spring-mvc-by-manual.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
       ">
    <!-- 处理器 -->
    <bean name="/hello" class="com.tom.web.controller.HelloWorldController"/>

    <!-- HandlerMapping -->
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>

    <!-- HandlerAdapter -->
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
</beans>

BeanNameUrlHandlerMapping:表示将请求的URL和Bean名字映射,如URL为 “上下文/hello”,则Spring配置文件必须有一个名字为“/hello”的Bean,上下文默认忽略。 SimpleControllerHandlerAdapter:表示所有实现了org.springframework.web.servlet.mvc.Controller接口的Bean可以作为Spring Web MVC中的处理器。如果需要其他类型的处理器可以通过实现HadlerAdapter来解决。

要解决这个,最好的办法就是明确的区分那种和业务逻辑关系不大的格式的验证以及业务逻辑中的验证。对于长度、必选、枚举、是不是电子邮箱、是不是 URL 用 Bean Validation 解决。对于有关业务逻辑的,比如是不是合法的产品型号、是不是重复的注册名等都在 Controller 中进行处理。下面分别对两种验证方式进行说明。

四、Spring MVC注解

在Spring配置文件中配置ViewResolver

Spring MVC 中对异常的处理基本都是在 Controller 中抛出一个具体的 Runtime 异常(比如 ProductNotFoundException,然后通过 ExceptionHandler 的方式去捕捉并转换为具体的报错请求。具体的示例见这里,我就不再重复了,我们在这里会使用 ControllerAdvice 的方式处理这种比较通用的情况,对于某些特殊处理的情况在 Controller 加 ExceptionHandler 即可。这里想强调的是如何把一个报错转化成一个格式良好的、便于 RESTful API 消费方处理的 JSON 的。

- @Controller注解

org.springframework.stereotype.Controller注解类型用于指示Spring类的实例是一个控制器,@Controller用于标记一个类,使用它标记的类就是一个SpringMVC Controller对象,即一个控制器类Spring使用扫描机制查找应用程序中所有基于注解的控制器类。分发处理器会扫描使用了该注解的类的方法,并检测该方法是否使用了@RequestMapping注解,使用了的方法才是真正处理请求的处理器。 保证spring能找到控制器,需完成两件事:

  • 在SpringMVC核心配置文件头文件引入spring-context;
  • 使用<context:component-scan/>开启注解扫描(扫描被@Controller、@Service、@repository、@component等注解的类);

支持JSP

<!-- 定义视图解析器 -->
<bean id="viewResolver"
      class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="classpath:/templates/"></property>
    <property name="suffix" value=".jsp"></property>
    <property name="order" value="1"/>
</bean>
  • InternalResourceViewResolver:用于支持Servlet、JSP视图解析;

  • viewClass:JstlView表示JSP模板页面需要使用JSTL标签库,classpath中必须包含jstl的相关jar包;

  • prefix和suffix:查找视图页面的前缀和后缀(前缀[逻辑视图名]后缀),比如传进来的逻辑视图名为hello,则该该jsp视图页面应该存放在“classpath:/templates/hello.jsp”;

首先,有一个 UsersApi 用于创建用户的方法:

@RequestMapping注解

   org.springframework.web.bind.annotation.RequestMapping注解类型指示Spring用哪一个类或方法来请求动作,该注解可用于类或方法 @RequestMapping可以用来注释一个控制器类,在这种情况下,所有方法都将映射为相对于类级别的请求,如下:

@Controller@RequestMapping(value="/user")public class UserController{       @RequestMapping(value="/register")        public String register(){            return "register";        }        @RequestMapping(value="/login")        public String login(){            return "login";        }}   

由于UserController类中加了value="/user"的@RequestMapping注解,因此所有相关路径都要加上“/user”,此时方法被映射到如下请求:

    • @RequestMapping注解支持的常用属性
      • value属性:是@RequestMapping注解默认属性,若只有唯一属性,则可省略属性名

   @RequestMapping(value="/hello")=@RequestMapping

      • method属性:表明该方法仅处理的HTTP请求方式

   @RequestMapping(value="/hello",method=RequestMethod.POST),只支持post;如果没有指定method属性,则方法可以处理任意HTTP请求方式

    • consumes属性:表明处理请求的提交内容类型;
    • produces属性:表明返回的内容类型;
    • params属性:指定request中必须包含某些参数时,才让该方法处理;
    • headers属性:指定request中必须包含某些指定的header值,才让该方法处理请求;
  • 请求处理方法可以出现的参数类型(SpringMVC默认支持的参数,可出现可不出现,取决于是否用到)_Spring+Mybatis企业应用实战P30
    • HttpServletRequest对象
    • HttpServletResponse对象
    • HttpSession对象
    • Model对象
    • ModelMap对象
    • ......

支持Freemarker

<!-- 配置freeMarker的模板路径 -->
<bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
    <property name="templateLoaderPath" value="classpath:/templates/" />
    <property name="defaultEncoding" value="UTF-8" />
</bean>
<!-- freemarker视图解析器 -->
<bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
    <property name="suffix" value=".ftl" />
    <property name="order" value="0"/>
    <property name="contentType" value="text/html;charset=UTF-8" />
    <!-- 此变量值为pageContext.request, 页面使用方法:rc.contextPath -->
    <property name="requestContextAttribute" value="rc" />
</bean>

order决定视图的优先级,本例中首先查找classpath:/templates/xxx.ftl再试着找classpath:/templates/xxx.jsp

@RestController@RequestMappingpublic class UsersApi { private UserRepository userRepository; @Autowired public UsersApi(UserRepository userRepository) { this.userRepository = userRepository; } @RequestMapping(method = POST) public ResponseEntity createUser(@Valid @RequestBody CreateUser createUser, BindingResult bindingResult) { if (bindingResult.hasErrors { throw new InvalidRequestException("Error in create user", bindingResult); } User user = new User(UUID.randomUUID().toString(), createUser.getUsername; userRepository.save; return new ResponseEntity(HttpStatus.CREATED); }}

- @RequestParam注解

org.springframework.web.bind.annotation.RequestParam注解类型用于将指定的请求参数赋值给方法中的形参

    • @RequestParam注解支持的常用属性
      • name:String类型;指定请求头绑定的名称
      • value:String类型;name属性的别名
      • required:boolean类型;指定参数是否必须绑定;
      • defaultValue:String类型;如果没有传递参数而是用的默认值
@RequestMapping(value="/login")public ModelAndView login(@RequestParam("loginname") String loginname,                          @RequestParam("password") String password){        return ......;}

支持返回json

可以看到,上面的 createUser 方法中,有两个参数 CreateUserBindingResult。其中 CreateUser 是一个 Form Object 用于处理创建用户的输入,它通过 Bean Validation 的方式定义输入的一些要求,通过 @Valid 的注解可是让 java 自动帮我们进行表单验证,表单验证的结果就被放在 BindingResult 中了。在这里处理报错的好处在于可以附上在当前 Controller 中特有的 message (Error in create user)CreateUser 类如下所示。

- @PathVariable注解

org.springframework.web.bind.annotation.PathVariable注解类型可以非常方便地获得请求URL的中的动态参数;

    • @PathVariable注解支持属性
      • value:String类型,表示绑定的名称,若省略则默认绑定同名参数
@RequestMapping(value="/pathVariableTest/{userId}")public void pathVariableTest(@PathVariable Integer userId)

假如请求的URL为“

配置方法1

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.12</version>
</dependency>

<mvc:annotation-driven>
    <mvc:message-converters register-defaults="true">
        <!-- 配置Fastjson支持 -->
        <bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
            <property name="supportedMediaTypes">
                <list>
                    <value>text/html;charset=UTF-8</value>
                    <value>application/json</value>
                </list>
            </property>
            <property name="features">
                <list>
                    <value>WriteMapNullValue</value>
                    <value>QuoteFieldNames</value>
                </list>
            </property>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>
@Getter // lombok 注解public class CreateUser { @NotBlank // hibernate.validator 注解 private String username;}

- @RequestHeader注解

org.springframework.web.bind.annotation.RequestHeader注解类型用于将请求的头信息区数据映射到功能处理方法的参数上

    • @RequestHeader注解支持的属性
      • name:String类型;指定请求头绑定的名称
      • value:String类型;name属性的别名
      • required:boolean类型;指定参数是否必须绑定;
      • defaultValue:String类型;如果没有传递参数而是用的默认值
@RequestMapping(value="/requestHeaderTest")public void requestHeaderTest(@RequestHeader("User-Agent") String userAgent,                              @RequestHeader(value="Accept") String[] accepts)

以上配置自动将请求头“User-Agent”的值赋到userAgent变量上,并将“Accept”请求头的值赋到accepts参数上

配置方法2

仅有以下配置有乱码

 <mvc:view-resolvers>
        <mvc:content-negotiation>
            <mvc:default-views>
                <bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView">
                    <property name="jsonpParameterNames">
                        <set>
                            <value>jsonp</value>
                            <value>callback</value>
                        </set>
                    </property>
                </bean>
            </mvc:default-views>
        </mvc:content-negotiation>
        <mvc:freemarker cache-views="false"  suffix=".ftl"/>
    </mvc:view-resolvers>

必须加上

<filter>
<filter-name>CharacterEncodingFilter</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>CharacterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

接着,我们有一个测试用例覆盖错误输入的情况。可以看到 should_400_with_wrong_parameter 通过 rest assured 方法对我们想要获得的结果格式进行了测试,setUp 方法以及 rest assured 内容见 [在 Spring Boot 1.5.3 中进行 Spring MVC 测试]({% post_url 2017-05-04-spring-mvc-and-test %})。

- @CookieValue注解

org.springframework.web.bind.annotation.CookieValue用于将请求的Cookie数据映射到功能处理方法的参数上

    • @CookieValue注解支持的属性
      • name:String类型;指定请求头绑定的名称
      • value:String类型;name属性的别名
      • required:boolean类型;指定参数是否必须绑定;
      • defaultValue:String类型;如果没有传递参数而是用的默认值
@RequestMapping(value="/cookieValueTest")public void cookieValueTest(@CookieValue(value="JSESSIONID",defaultValue="") String sessionId)

以上配置会自动将JSESSIONID值设置到sessionId参数上,defaultValue表示Cookie中没有JSESSIONID时默认为空

配置方法3,@RestController注解,自动转化json对象

@RestController
public class MessageController {
    Logger logger = LoggerFactory.getLogger(MessageController.class);
    @RequestMapping(value = "/message", method = RequestMethod.POST)
    public @ResponseBody JSONObject message(@RequestParam String message) {
        logger.debug("{}", message);
        JSONObject item = new JSONObject();
        item.put("name", "我是tomLuo");
        return item;
    }
}
@RunWith(SpringRunner.class)public class UsersApiTest { private UserRepository userRepository; @Before public void setUp() throws Exception { userRepository = mock(UserRepository.class); MockMvc mockMvc = MockMvcBuilders.standaloneSetup(new UsersApi(userRepository)) .setControllerAdvice( new CustomizeExceptionHandler.build(); RestAssuredMockMvc.mockMvc; } @Test public void should_400_with_wrong_parameter() throws Exception { Map<String, Object> wrongParameter = new HashMap<String, Object>() {{ put("name", "aisensiy"); }}; given() .contentType("application/json") .body(wrongParameter) .when().post .then().statusCode .body("fieldErrors[0].field", equalTo("username")) .body("fieldErrors.size()", equalTo; }}

- @SessionAttributes注解(只能声明类,不能声明方法)

org.springframework.web.bind.annotation.SessionAttributes注解类型允许我们有选择的指定Model中的哪些属性需要转存到HttpSession当中

    • @SessionAttributes注解支持的属性
      • names属性:String[]类型,Model中属性名称,即存储在HttpSession当中的属性名称;
      • value属性:String[]类型,names属性的别名;
      • types属性:Class<?>[]类型,用来指定放入HttpSession当中的对象类型
@Controller//将Model中属性名为user的属性放入HttpSession对象当中@SessionAttributes("user")public class SessionAttributesController{        @RequestMapping(value="/login")    public String login(@RequestParam("loginname") String loginname,                        @RequestParam("password") String password,                        Model model){         //创建User对象,装载用户信息         User user = new User();         user.setLoginname(loginname);         user.setPassword;         //将user对象添加到Model当中         model.addAttribute("user",user);         return "welcome";    }}

JSP页面测试以上@SessionAttributes注解:

${requestScope.user.username}//页面显示admin${sessionScope.user.username}//页面显示admin

结论:User对象被成功设置到了HttpSession对象当中

@SessionAttributes注解如下写法:@SessionAttributes(types={User.class},value="user")

还可以设置多个对象到HttpSession当中:

配置方法4,produces="application/json"

@Controller
public class MessageController {
    Logger logger = LoggerFactory.getLogger(MessageController.class);

    @RequestMapping(value = "/message", method = RequestMethod.POST,produces="application/json") (1)
    public @ResponseBody JSONObject message(@RequestParam String message) {
        logger.debug("{}", message);
        JSONObject item = new JSONObject();
        item.put("name", "我是tomLuo");
        return item;
    }
}
  1. 见下面 Spring3.1新特性 === 开发处理器/页面控制器

/src/main/java/com/tom/web/controller/HelloWorldController.java

package com.tom.web.controller; /**
 * Created by tom on 2016/5/24.
 */

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HelloWorldController implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest req, HttpServletResponse resp) throws Exception {
        //1、收集参数、验证参数
        //2、绑定参数到命令对象
        //3、将命令对象传入业务对象进行业务处理
        //4、选择下一个页面
        ModelAndView mv = new ModelAndView();
        //添加模型数据 可以是任意的POJO对象
        mv.addObject("message", "Hello World!");
        mv.addObject("message2", "我是tomLuo!");
        //设置逻辑视图名,视图解析器会根据该名字解析到具体的视图页面
        mv.setViewName("hello");
        return mv;
    }
}
  • org.springframework.web.servlet.mvc.Controller:页面控制器/处理器必须实现Controller接口,注意别选错了;后边我们会学习其他的处理器实现方式;

  • public ModelAndView handleRequest(HttpServletRequest req, HttpServletResponse resp) :功能处理方法,实现相应的功能处理,比如收集参数、验证参数、绑定参数到命令对象、将命令对象传入业务对象进行业务处理、最后返回ModelAndView对象;

  • ModelAndView:包含了视图要实现的模型数据和逻辑视图名;“mv.addObject("message", "Hello World!");

  • "Hello World!"表示添加模型数据,此处可以是任意POJO对象;“mv.setViewName("hello");”表示设置逻辑视图名为“hello”,视图解析器会将其解析为具体的视图,如前边的视图解析器InternalResourceVi。wResolver会将其解析为“classpath:/templates/hello.ftl”。

  • name="/hello":前边配置的BeanNameUrlHandlerMapping,表示如过请求的URL为 “上下文/hello”,则将会交给该Bean进行处理。

> 以上Spring2.5之前,我们都是通过实现Controller接口或其实现来定义我们的处理器类

错误情况下 Api 的 Response 大概是这个样子:

- @ModelAttribute注解

org.springframe.web.bind.annotation.ModelAttribute注解类型将请求参数绑定到Model对象

    • @ModelAttribute注解支持的属性
      • value属性:String类型,表示绑定的属性名称

   Notice:被@ModelAttribute注释的方法会在Cobtroller每个方法执行前被执行,因此在一个Controller映射到多个URL时,要谨慎使用!   @ModelAttribute注解使用情况:

    • @ModelAttribute注释返回具体类的方法@ModelAttribute("loginname") public String userModel1(@RequestParam("logginname") String loginname){ return loginname; }
    • @ModelAttribute注释void返回值的方法

      @ModelAttributepublic void userModel2(@RequestParam("loginname") String loginname,                       @RequestParam("password") String password,                       Model model){    model.addAttribute("loginname",loginname);    model.addAttribute("password",password);}
      
    • @ModelAttribute注释返回具体类的方法

      @ModelAttributepublic User userModel3(@RequestParam("loginname") String loginname,                       @RequestParam("password") String password){     return new User(loginname,password);}
      
    • @ModelAttribute和@RequestMapping同时注释一个方法@RequestMapping(value="/login") @ModelAttribute(value="username") public String login4(){ return "admin"; }

    • @ModelAttribute注释一个方法的参数

      @ModelAttribute("user")public User userModel5(@RequestParam("loginname") String loginname,                       @RequestParam("password") String password){    User user = new User();    user.setLoginname(loginname);    user.setPassword;    return user;}@RequestMapping(value="/login5")public String login5(@ModelAttribute("user") User user){    user.setUsername("管理员");    return "result5";}
      

      不管@ModelAttribute注解在什么情况下使用,model对象中的属性名都是@ModelAttribute的属性value值(有value存在情况下)或返回类型对象名(没有value存在情况下);model对象中的值是方法返回值或自己填充model

注解式处理器支持

{ "code": "InvalidRequest", "message": "Error in create user", "fieldErrors": [ { "resource": "createUser", "field": "username", "code": "NotBlank", "message": "may not be empty" } ]}

五、SpringMVC框架乱码解决方案

Spring2.5: 注解式处理器

Spring2.5引入注解式处理器支持,通过@Controller 和 @RequestMapping注解定义我们的处理器类

需要通过处理器映射DefaultAnnotationHandlerMapping和处理器适配器AnnotationMethodHandlerAdapter来开启支持@Controller 和 @RequestMapping注解的处理器。

  • @Controller:用于标识是处理器类;

  • @RequestMapping:请求到处理器功能方法的映射规则;

  • @RequestParam:请求参数到处理器功能处理方法的方法参数上的绑定;

  • @ModelAttribute:请求参数到命令对象的绑定;

  • @SessionAttributes:用于声明session级别存储的属性,放置在处理器类上,通常列出模型属性(如@ModelAttribute)对应的名称,则这些属性会透明的保存到session中;

  • @InitBinder:自定义数据绑定注册支持,用于将请求参数转换到命令对象属性的对应类型;

这里我们重点看 InvalidRequestException 的处理。

- POST提交中文乱码解决

  在web.xml中添加过滤器:

<filter>    <filter-name>CharacterEncodingFilter</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>CharacterEncodingFilter</filter-name>     <url-pattern>/*</url-pattern></filter-mapping>

开启注解

<context:component-scan base-package="com.tom.web.controller" use-default-filters="false">
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!-- 开启注解 -->
<mvc:annotation-driven/>

只扫描com.tom.web.controller.*, 仅有@Controller的处理类

版权声明:本文由美高梅开户送58元官网发布于美高梅开户送58元官网,转载请注明出处:MVC思想将一个应用部分分成三个基本部分,有输