• Spring框架系列(一)--Spring MVC基础知识


      Web项目开发过程中一般都是使用MVC(Model-View-Controller)模式,早先的Struts2到Spring MVC,再到现在Spring Boot,都是相似的思

    路。Spring Boot用多了就真的不想回到SSM或者SSH框架(虽然公司还在用Spring MVC),写这篇随笔,算是自己对Spring MVC内容的复习吧。

    工作流程

    DispatchServlet的配置方式

    1、web.xml

    2、通过将其配置在Servlet容器中(Tomcat7+版本要求)

    /**
     * AbstractAnnotationConfigDispatcherServletInitializer的拓展类会自动配置DispatchServlet和
     * Spring ApplicationContext(应用上下文位于应用程序的Servlet上下文之中)
     */
    public class SpittrWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    
        /**
         * 返回带有@Configuration注解的类用来定义ContextLoaderListener创建的应用上下文中的bean
         * @return
         */
        @Override
        protected Class<?>[] getRootConfigClasses() {
            return new Class[]{RootConfig.class};
        }
    
        /**
         * 返回带有@Configuration注解的类用来定义DispatchServlet创建的应用上下文中的bean
         * @return
         */
        @Override
        protected Class<?>[] getServletConfigClasses() {
            return new Class[]{WebConfig.class};
        }
    
        /**
         * 将一个或多个路径映射到DispatchServlet上。"/"表示使用应用默认的Servlet,会理所有请求
         * @return
         */
        @Override
        protected String[] getServletMappings() {
            return new String[] {"/"};
        }
    }
    配置DispatchServlet
    public class WebConfig  extends WebMvcConfigurerAdapter{
    //通常包含视图解析器配置
    //静态资源处理
    //。。。。。
    }
    WebConfig

    DispatchServlet启动的时候,会创建Spring应用上下文,加载声明的bean,Spring Web应用中,通常还有另一个应用上下文,由

    ContextLoaderListener创建

    DispatchServlet:加载包含Web组件的bean,如控制器、视图解析器、处理器映射

    ContextLoaderListener:加载应用中的其他bean,通常是驱动应用后端的中间层和数据层组件

    常用注解

    以下URL测试都是使用restlet client,也可以使用postman等工具

    1、@EnableWebMvc:在配置类中开启Web MVC的配置支持,如一些ViewResolver或者MessageConverter等,不使用注解,需要重写

    WebMvcConfigurerAdapter方法用于对SpringMVC的配置。

    2、@RequestParam:

    参数:name、value、defaultValue、required

    分别代表:参数名、值、默认值(如果没有这个参数,给默认值),参数必须有,否则400错误(如果有defaultValue就不会有问题)

    请求URL:http://localhost:8080/test5?id=1001&name&sex1=1

    @RequestMapping(value = "/test5", method = RequestMethod.GET)
        public String test5(@RequestParam int id, @RequestParam(value = "name", defaultValue = "zhangsan", required = true) String name) {
            System.out.println("test2 id: " + id + " name: " + name );
            return "index";
        }
    test2 id: 1001 name: zhangsan

    name和value没有区别,value别名是name,name别名是value

    public @interface RequestParam {
        @AliasFor("name")
        String value() default "";
    
        @AliasFor("value")
        String name() default "";
    
        boolean required() default true;
    
        String defaultValue() default "
    		
    		
    ue000ue001ue002
    				
    ";
    }

    如果参数名一致,可以选择不使用@RequestParam

    URL:localhost:8080/test?name=sam

    public String test(HttpServletRequest request,  String name, ModelMap modelMap) {
        modelMap.put("name", "sam");
        log.info("param is {}", name);
        return "home";
    }

    PS:我们使用@RequestParam只是因为能够提供name,required、defaultValue属性,否则可以选择不使用

    3、@RequestMapping:

    包含参数:value、method、params、headers、consumes、produces

    1).直接使用默认:http://host:port/path?id=1001

    @RequestMapping("test1")
    public String test1(@RequestParam("id") String id) {
        System.out.println("test1 id: " + id);
        return "index";
    }
    test1 id: 1001

    2).value、method:

    value:指定请求的实际地址,或者使用URI Template模式

    method:请求的方法类型,支持以下类型,可选择多种

    public enum RequestMethod {
        GET,
        HEAD,
        POST,
        PUT,
        PATCH,
        DELETE,
        OPTIONS,
        TRACE;
    
        private RequestMethod() {
        }
    }
    @ResponseBody
    @RequestMapping(value = "/test1", method = RequestMethod.GET)
    //    @RequestMapping(value = "/test1", method = {RequestMethod.GET, RequestMethod.POST})
    public String test1(@RequestParam("id") String id) {
        System.out.println("test1 id: " + id);
        return "index";
    }

    3).params、headers:

    params: 指定request中必须包含某些参数值才能进入方法

    headers: 指定request中必须包含某些指定的header值才能进入方法

    @ResponseBody
    @RequestMapping(value = "/test3", method = RequestMethod.GET, params = {"id=1001", "name", "!sex"}, headers = {"Accept"}) 
    public String test3(@RequestParam int id, @RequestParam("name") String name, @RequestParam("abc") String addr) {
    System.out.println(
    "test2 id: " + id + " name: " + name + " addr: " + addr);
    return "index";
    }

    params={"id=1001", "name", "!sex"}表示参数中,id必须为1001,必须包含name,不能包含sex,否则返回400 Bad Request状态码

    headers = {"Accept"}表示请求头包含accept信息

    4).consumes、produces

    @RequestMapping(value = "/test1", method = RequestMethod.GET, params = {"!id", "name", "!sex"}
                        , headers = {"Accept"}, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
        @ResponseBody
        public String test1(HttpServletRequest request, @RequestParam(value = "name", required = false) String name, ModelMap modelMap) {
            modelMap.put("name", "sam");
            log.info("param is {}", name);
            return name;
        }

    consumes = MediaType.APPLICATION_JSON_VALUE表示request的content-type必须为application/json

    produces = MediaType.APPLICATION_JSON_UTF8_VALUE表示response的content-type为application/json,编码为utf-8

    4、@PathVariable:

    参数:name、value、required,没有了defaultValue

    请求URL:http://localhost:8080/test2/id/1001/name/sam

    @ResponseBody
    @RequestMapping(value = "/test2/id/{id}/name/{name}", method = RequestMethod.GET)
    public String test4(@PathVariable("id") int id, @PathVariable("name") String name) {
        System.out.println("test2 id: " + id + " name: " + name);
        return "index";
    }
    test2 id: 1001 name: sam

     到此时:我们可以看到@PathVariable和@RequestParam的区别

    @PathVariable会把URL template变量映射到参数中,而@RequestParam中相当于request.getParameter("name"),去获取请求中的参数

    5、表单验证@Valid:都在javax.validation.constraints包里面

    public class Login {
        @NotNull
        @IsMobile
        private String mobile;
        
        @NotNull
        @Length(min=32)
        private String password;
    }
    public Result<String> doLogin(HttpServletResponse response, @Valid LoginVo loginVo) {
        log.info(loginVo.toString());
        //登录
        String token = userService.login(response, loginVo);
        return Result.success(token);
    }

    6、@ResponseBody:支持将返回值放在response内,而不是一个页面,通常用户返回json/xml数据

    @ResponseBody
    public String test3() {
        return "id";//这时候返回到页面的是String,而不是解析到id.html等类似的页面
    }

    6、@RequestBody:允许request的参数在request体中,而不是在直接连接在地址后面。例如通过ajax传递的json参数

    @RequestMapping(value = "/test1", method = RequestMethod.GET, params = {"!id", "name", "!sex"}
                        , headers = {"Accept"}, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
        @ResponseBody
        public String test1(HttpServletRequest request, @RequestBody String addr, @RequestParam(value = "name", required = false) String name, ModelMap modelMap) {
            modelMap.put("name", "sam");
            log.info("param is {} and {}", name, addr);
            return name;
        }

    通过@RequestBody才能在get请求中得到Body中的参数,因为get请求默认只能读取URL中的参数

    7、@RestController:相当于@Controller和@ResponseBody的组合,注解在类上,该Controller的所有方法都默认加上了@ResponseBody。

    @Controller
    @ResponseBody
    public @interface RestController {
        String value() default "";
    }

    9、@RequestHeader:把Request请求header部分的值绑定到方法的参数上

    请求URL:http://localhost:8080/test6

    @ResponseBody
    @RequestMapping(value = "/test6", method = RequestMethod.GET)
    public String test6(@RequestHeader("Accept-Encoding") String encoding) {
        System.out.println("test2 contentType: " + encoding + " date: "  );
        return "index";
    }
    test2 contentType: gzip, deflate, br date: 

    10、@CookieValue

    @ResponseBody
    @RequestMapping(value = "/test7", method = RequestMethod.GET)
    public String test7(@CookieValue("JSESSIONID") String cookie) {
        System.out.println("test2 cookie: " + cookie + " date: "  );
        return "index";
    }
    test2 cookie: 3E3E78E5E977EDBAEA388D8829BA2764

    视图解析器

    Spring自带13个视图解析器,常用的有:

    InternalResourceViewResolver:一般用于JSP,在视图名称上面添加前缀和后缀,进而确定页面的物理地址,Prefix和suffix

    FreeMarkerViewResolver和VelocityViewResolver分别对应FreeMaker和Velocity模板视图

    注解部分参考:https://www.cnblogs.com/leskang/p/5445698.html

  • 相关阅读:
    C/S 架构和B/S架构的区别
    LoadRunner工作原理
    修改密码测试用例
    登录测试用例
    上传测试点
    avd 配置信息详解
    创建模拟器
    命令模式下启动模拟器,加载软件
    启动模拟器时出现Failed to create Context 0x3005
    SDK Manager更新时出现Failed to fectch URl https://dl-ssl.google.com/android/repository/addons_list.xml, reason: Connection to https://dl-ssl.google.com ref
  • 原文地址:https://www.cnblogs.com/huigelaile/p/10963320.html
Copyright © 2020-2023  润新知