zoukankan      html  css  js  c++  java
  • 第5章 构建Spring Web应用程序


    1、SpringMVC请求:
    请求---->DispatcherServlet(请求的第一站,前端控制器,将请求委托给其他应用程序来处理)
    DispatcherServlet---->相应的控制器(通过查询处理器映射器来查询到底传递给那个控制器)
    控制器--(模型和视图名)-->DispatcherServlet---->视图解析器--(视图)-->相应
    2、配置DispatcherServlet
    1:传统的方法是讲DispatcherServlet配置在web.xml中。
    2:这里我们将DispatcherServlet配置在Servlet中。
    这种方法是传统的xml配置的替代,但是需要部署在支持Spring3.0的Web容器中。(Tomcat7或者更高)
    /**
            DispatcherServlet启动会引起Spring应用上下文的创建,应用上下文加载Web组件的bean(控制器、视图解析器、处理器)
            ContextLoaderListener的创建会加载其他bean(后端中间层、数据层的bean)
            AbstractAnnotationConfigDispatcherServletInitializer会同时创建 DispatcherServlet和ContextLoaderListener。
            getServletClasses()用于指定Spring应用上下文的bean的文件(包含@Configuration注解的java类)
            getRootConfigClasses()用于指定ContextLoaderListener创建的上下文加载的bean的配置文件(包含@Configuration注解的java类)
            */
            public class SpitterWebAppInitializer extends  AbstractAnnotationConfigDispatcherServletInitializer{
                @Override
                protected String[] getServletMappings(){
                    return new String[]{"/"};       //将DispatcherServlet映射到“/”,将会处理应用的所有请求。
                }
                //用来指定ContextLoaderListener上下文中需要加载的bean的配置文件。
                @Override
                protected Class<?>[] getRootConfigClasses(){
                    return new Class<?>[] {RootConfig.class};
                }
                //DispatcherServlet启动的时候会创建Spring应用上下文。并加载bean。此处要求加载定义在WebConfig中的bean。
                @Override
                protected Class<?>[] getServletConfigClasses(){
                    return new Class<?>[] {WebConfig.class};
                }
            }
    3、启用Spring MVC
    1:使用xml配置:
     <mvc:annotation-driven>
        2:使用java文件配置(@EnableWebMVC注解)
    注意如果只加@EnableWebMVC注解,这个配置文件不会配置视图解析器、没有启动组件扫描、等功能缺陷。
    解决上述问题的配置:
    @Configuration
            @EnableWebMvc       //启用SpringMVC
            @ComponentScan("spitter.web")
            public class WebConfig extends WebMvcConfigurerAdapter{
                @Bean
                public ViewResolver viewResolver(){     //配置jsp视图解析器
                    InternalResourceViewResolver resolver = new InternalResourceViewResolver();
                    resolver.setPrefix("/WEB-INF/views/");
                    resolver.setSuffix(".jsp");
                    resolver.setExposeContextBeansAsAttributes(true);
                    return resolver;
                }
                //配置静态资源处理(要求DispatcherServlet对静态资源的请求转发到Servlet容器中默认的Servlet上,而不是DispatcherServlet类来处理)
                @Override
                public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer){
                    configurer.enable();
                }
            }
          Spring应用上下文的已近随着DispatcherServlet的创建而创建了。接下来配置RootConfig。
          @Configuration
          @ComponentScan(basePackage={"spitter"},excludeFilters = {@Filter(type=FilterType.ANNOTATION,value=EnableWebMvc.class)})
          public class RootConfig{}
    4、编写基本的控制器
    例如:
       @Controller         //声明控制器
        public class HomeController{
            @RequestMapping(value="/",method = RequestMethod.GET)   //匹配“/”的GET请求
            public String home(){
                return "home";  //返回视图名(结合视图解析器:视图为:/WEB-INF/views/home.jsp)
            }
        }
    5、定义类级别的请求处理
    例如:
            @Controller
            @RequestMapping("/")
            public class HomeController{
                @RequestMapping(method = RequestMethod.GET)     //这个方法匹配的依然是"/"的GET请求。只不过将匹配路径的"/"放到了类级别。
                public String home(){
                    return "home";
                }
            }    
            //匹配多个路径
            @controller
            @RequestMapping("/","/homepage")        //可以同时匹配"/"和"/homepage"
            public class HomeController{...}
    6、传递模型数据到视图中(返回视图的同时给视图传递模型)
    1:首先我们定义一个用于访问数据的Repository:
            public interface SpittleRepository{
                List<Spittle> findSpittles(long max, int count);
            }
        2:编写控制器
            @Controller
            @RequestMapping("/spittles")
            public class SpittleController{
                private SpittleRepository spittleRepository;
                @Autowired
                public SpittleController(SpittleRepository spittleRepository){      //构造器中传入用于访问数据的属性
                    this.spittleRepository = spittleRepository;
                }
                @RequestMapping(method = RequestMethod.GET)
                public String spittles(Model model){        //Model其实就是一个Map,它会被传递给视图。
                    model.addAttribute(spittleRepository.findSpittles(Long.MAX , 20));  //没有写key,会根据类型自动判断,这里判断为spittleList。
                    //也可以明确key
                    //model.addAttribute("spittleList",spittleRepository.findSpittles(Long.MAX , 20));
                    return "spittles";
                }
            }
            //使用Map类型封装数据:
    例如:
            @RequestMapping(method = RequestMethod.GET)
            public String spittles(Map model){
                model.put("spittleList",spittleRepository.findSpittles(Long.MAX , 20));
                return "spittles";
            }
            //不写key不写返回视图的方法
            @RequestMapping(method = RequestMethod.GET)
            public List<Spittle> spittles(){
                return spittleList",spittleRepository.findSpittles(Long.MAX , 20);
            }
            //key:根据类型推断为:spittleList
            //视图名:因为这个方法匹配"/spittles",所以视图名为spittles。
    7、接收请求的输入
    SpringMVC从客户端中获取属性的方法:
    查询参数、表单参数、路径参数。
    7.1:处理查询参数:
    //实现翻页功能,需要传入两个值,max、count。
                @RequestMapping(method = RequestMethod.GET)
                public List<Spittle> spittles(@RequestParam("max") long max , @RequestParam("count") int count){
                    return spittleRepository.findSpittles(max , count);
                }
            //设点参数的默认值
                @RequestMapping(method = RequestMethod.GET)
                public List<Spittle> spittles(
                    @RequestParam(value = "max" , defaultValue = MAX_LONG_AS_STRING) long max ,
                    @RequestParam(value = "count" , defaultValue = 10) int count
                    ){
                    return spittleRepository.findSpittles(max , count);
                }
       7.2:通过路径参数接收输入:
    场景:我们需要一个名为SpittleID的参数查询指定的某一条记录:
                /**
                通过参数查询:
                下面这个类中的showPaittle方法将配“/spittles/show?spittle_id”的GET请求。(/spittles/show?spittle_id=123445)
                */
                @Controller
                @RequestMapping("/spittles")
                public class SpittleController{
                    @RequestMapping(value = "/show" , method = RequestMethod.GET)
                    public String showPaittle(
                        @RequestParam("spittle_id" long spittleId),
                        Model model
                    ){
                        model.addAttribute("key" , spittleRepository.findSpittles(spittleId));
                        return "spittle";
                    }
                }
                /**
                通过URL路径标识
                下面的方法可以匹配“/spittles/spittleId”URL路径(/spittles/234423)
                */
                @Controller
                @RequestMapping("/spittles")
                public class SpittleController{
                    @RequestMapping(value = "/{spittleId}" , method = RequestMethod.GET)        //{}为占位符
                    public String spittle(@PathVariable("spittleId") Long spittleId , Model model){ //无论占位符部分的值是什么都会传到处理方法中。
                        model.addAttribute("key" , spittleRepository.findSpittles(spittleId));
                        return "spittle";
                    }
                }
                //@PathVariable("spittleId" Long spittleId , Model model)由于方法参数名和占位符一直所以可以胜率为:
                //@PathVariable(Long spittleId , Model model)
                //如果@PathVariable中的Value属性没有的话,会假设方法参数名称和路径占位符名称相同。
    8、处理表单
    例如表单:
            <html>
                <head>
                    <title>Spittr</title>
                </head>
                <body>
                    <form>
                        First Name: <input type = "text" name firstName="firstName" />
                        Last Name : <input type = "text" name LastName = "lastName" />
                        UserName  : <input type = "text" name UserName = "userName" />
                        PassWord  : <input type = "password" name = "password" />
                        <input type = "submit" value = "Register">
                    </form>
                </body>
            </html>
        控制器:
            @Controller
            @RequestMapping("/spitter")
            public class SpitterController{
                private SpitterRepository spitterRepository;
                @Autowired
                public SpitterController(SpitterRepository spitterRepository){      //SpitterRepository是DAO层的类
                    this.spitterRepository = spitterRepository;
                }
                @RequestMapping(value = "/register" , method = GET)     //这个请求用于跳转到注册页面
                public String showRegisterFrom(){
                    return "register"
                }
                @RequestMapping(value = "/register" , method = POST)
                public String processRegister(Spitter spitter){
                    spitterRepository.save(spitter);        //Spitter类中的属性对应了表单中的属性。按照名称匹配。
                    return "redirect:/spitter/"+spitter.getUserName;    //重定向到别的页面。(redirect:会被解析为重定向。forward:是跳转)
                }
            }
        处理重定向的控制器:
            @RequestMapping(value ="/{username}" , method = GET)
            public String ShowSpitterProfile(@PathVariable String userName , Model model){
                Spitter spitter = spitterRepository.findByUserName(userName);
                model.addAttribute(spitter);
                return "profile";
            }
        表单验证:
    (表单中,填写的数据为空、数据太长等异常情况需要解决)
    1、一种比较初级的方法是,在控制其中添加一些校验代码。(校验代码污染了控制器)
    2、利用Spring对java校验API(JSR-303)的支持。(只需要在类路径下包含实现了Java校验API的类即可)
    java校验API提供的校验注解(只需放在属性上就可以限制属性的值,这些注解位于 javax.validation.constraints):
    注  解 描  述
    @AssertFalse 所注解的元素必须是 Boolean 类型,并且值为false
    @AssertTrue 所注解的元素必须是 Boolean 类型,并且值为true
    @DecimalMax 所注解的元素必须是数字,并且它的值要小于或等于给定的BigDecimalString值
    @DecimalMin 所注解的元素必须是数字,并且它的值要大于或等于给定的BigDecimalString值
    @Digits 所注解的元素必须是数字,并且它的值必须有指定的位数
    @Future 所注解的元素的值必须是一个将来的日期
    @Max 所注解的元素必须是数字,并且它的值要小于或等于给定的值
    @Min 所注解的元素必须是数字,并且它的值要大于或等于给定的值
    @NotNull 所注解元素的值必须不能为null
    @Null 所注解元素的值必须为null
    @Past 所注解的元素的值必须是一个已过去的日期
    @Pattern 所注解的元素的值必须匹配给定的正则表达式
    @Size 所注解的元素的值必须是String、集合或数组,并且它的长度要符合给定的范围
    在我们例子中只需要在Spittle类的属性上添加@NotNull和@Size注解即可
    1:添加校验注解
                        public class Spittle{
                            private Long id;
                            @NotNull
                            @Size(min = 5 , max = 6)
                            private String userName;
                            @NotNull
                            @Size(min = 5 , max = 6)
                            private String passWord;
                            @NotNull
                            @Size(min = 5 , max = 6)
                            private String firstName;
                            @NotNull
                            @Size(min = 5 , max = 6)
                            private String lastName;
                        }
                    2:启用校验功能(修改接收数据的控制器)
                        @RequestMapping(value = "/register" , method = POST)
                        public String processRegister(@Valid Spitter spitter , Errors errors){      //校验Spitter输入
                            if(errors.hasErrors){
                                return "registerForm"   //校验不通过,返回到注册页面
                            }
                            spitterRepository.save(spitter);
                            return "redirect:/spitter/"+spitter.getUserName;
                        }






  • 相关阅读:
    点滴积累【JS】---JS小功能(JS实现侧悬浮浮动)
    点滴积累【JS】---JS小功能(JS实现隐藏显示侧边栏,也就是分享栏的隐藏显示)
    点滴积累【JS】---JS小功能(JS实现排序)
    php修改排序,上移下移
    PHP获取上周、本周、上月、本月、本季度、上季度时间方法大全
    php简陋版实现微信公众号主动推送消息
    JQuery处理json与ajax返回JSON实例
    页面滚动动态加载数据,页面下拉自动加载内容 jquery
    CGI/FASTCGI/ISAPI区别
    CodeIgniter类库之Benchmarking Class ,计算代码的执行时间
  • 原文地址:https://www.cnblogs.com/Xmingzi/p/8926413.html
Copyright © 2011-2022 走看看