SpringMVC框架学习笔记--更新中 JavaWeb开发(SSM框架第三部分)从介绍SpringMVC到使用,让你掌握核心知识

SpringMVC

服务器端三层架构

  • 表现层(SpringMVC)
  • 务层(Spring)
  • 持久层(Mybatis)
    表现层:拿到http请求的参数,传递给spring

在这里插入图片描述

MVC

SpringMVC:一种基于Java实现的MVC设计模型的请求驱动类型的轻量级框架

  • M(model):javaBean对象(将参数封装成JavaBean对象交给业务层处理)
  • V(view):jsp (向控制器提交数据,显示模型中的数据)
  • C(controller):servlet(根据视图提出的请求判断将请求交给那个模型处理,将处理后的结果交给对应的视图更新显示)

SpringMVC运行流程

在Spring MVC框架中,从“Request(请求)”开始,依次进入“DispatcherServlet(核心分发器)” —> “HandlerMapping(处理器映射)” —> “Controller(控制器)” —> “ModelAndView(模型和视图)” —> “ViewResolver(视图解析器)” —> “View(视图)” —> “Response(响应)”结束,其中DispatcherServlet、HandlerMapping和ViewResolver 只需要在XML文件中配置即可,从而大大提高了开发的效率,特别是对于 HandlerMapping 框架为其提供了默认的配置。

  • 1.HandlerMapping(处理器映射):通过映射找到哪个控制器执行哪个方法@RequestMapping(path=“”)再通过HandlerAdapter适配器执行方法
  • 2.ViewResolver(视图解析器):找到哪个视图的显示

在这里插入图片描述

SpringMVC和struct2区别

  • 共同:都是表现层框架,离不开ServletAPI, 请求的机制都是一个核心控制器
  • 不同:
    • 1.SpringMVC核心控制器是Servlet,Struct是Filter
    • 2.SpringMVC是基于方法设计的,Struct是基于类设计的,前者效率较高
    • 3.SpringMVC使用更简洁,支持JSR303,处理ajax请求更方便
    • 4.Struct的OGNL表达式比SpringMVC开发效率高,执行效率比JSTL低,尤其Struct的表单标签,没有html效率高

创建SpringMVC Web项目

使用maven构建webapp项目,maven添加archetypeCatalog=internal,国外服务器太慢

mvc:annotation-driven/打开注解(处理器映射器、处理器适配器、视图解析器配置)

请求参数绑定

当你以表当post提交参数时,RequestMapping可以根据HandlerMapping寻找指定controller携带的javabean类对象参数将参数封装成一个bean对象返回(jsp表单指定属性name值要与bean对象属性名相同,当参数时包装对象时,应使用包装对象里的对象名加属性)

<form action="params/userVoadd" method="post">
    username<input type="text" name="user.username"></br>
    password<input type="password" name="user.password"></br>
    money<input type="text" name="user.money"></br>
    UserVoName<input type="text" name="userVoname"></br>
    UserVoPassword<input type="text" name="userVopassword"></br>
    <input type="submit" value="submit">
</form>

请求时参数转换器

(1)首先定义一个类继承Converter或者formatter类,
前者可用泛型表达参数转换类型<String,Integer>,后者使用,formatter转换源类型必须是String,对于Web应用Http发送的数据都是以String类型存储,使用formatter更合适

public class Convertors implements Converter<String,Date> {

    @Override
    public Date convert(String s) {
        if(s==null){
            throw new RuntimeException("请你传入数据!");
        }
        DateFormat df=new SimpleDateFormat("yyyy-MM-dd");

        try {
            return df.parse(s);
        } catch (ParseException e) {
            throw new RuntimeException("转换出错");
        }
    }
}

(2)在主文件中配置装换器

<bean class="org.springframework.context.support.ConversionServiceFactoryBean" id="conversionServiceFactoryBean">
        <property name="converters">
            <set>
                <bean class="com.dingxiang.utils.DateConvertor.Convertors"/>
            </set>
        </property>
    </bean>

(3)在注解中打开转换器

<mvc:annotation-driven conversion-service="conversionServiceFactoryBean"/>

常用注解

RequestParam

(1)RequestParam=request.getParameter(“name”)(name和value属性基本等同,required表示是否必须)

//用s来获取参数username
public String testRequestParam(@RequestParam(name = "username")String s){
        System.out.println(s);
        return "start";
    }

RequestBody

(2)RequestBody(获取请求体的内容,得到key=value&keyvalue…,gei方式不适用)

//获取表单传递参数,用字符串接受
public String testRequestBody(@RequestBody String body){
        System.out.println(body);
        return "start";
    }

PathVarible

(3)PathVariable使用RESTful风格,即根据参数传递类型和参数数量选取不同的方法执行,

//使用占位符{}直接传入参数
@RequestMapping("/testPathVariable/{id}")
    public String testPathVariable(@PathVariable(value = "id") String body){
        System.out.println(body);
        return "start";
    }

静态方法发送请求

浏览器插件测试各种请求方式
(4)RequestHeader(少用)

@RequestHeader(value = "User-Agent")

(5)CookieValue(少用)

@CookieValue(value = "JSESSIONID")

ModelAttribute

(6)ModelAttribute(方法、参数)首先执行
用于将多个参数封装到一个实体对象,从而简化数据绑定流程,自动暴露为模型数据,在视图展示时使用
两种方法,返回bean对象或者通过把bean对象加入到集合使用注解来读取

 @RequestMapping("/testModelAttribute")
    public String testModelAttribute(@ModelAttribute("1") User user){
        System.out.println("testModelAttribute");
        System.out.println(user.toString());
        return "start";
    }
    @ModelAttribute
    public void modelattribute(Map<String,User> map){
        User user=new User();
        user.setDate(new Date());
        user.setMoney(12.212);
        map.put("1",user);
    }
@RequestMapping("/testModelAttribute")
    public String testModelAttribute(User user){
        System.out.println("testModelAttribute");
        System.out.println(user.toString());
        return "start";
    }
    @ModelAttribute
    public User modelattribute(){
        User user=new User();
        user.setDate(new Date());
        user.setMoney(12.212);
        return user;
    }

SessionAttribute

(7)SessionAttribute
使用HttpSession的话需要servletAPI支持,存在耦合
value代表我们需要把什么样的对象放入session

@SessionAttributes(value = {"name"})

前端控制器拦截资源文件

(8)不让前端控制器拦截资源文件
<mvc:resources mapping="/css/**" location="/css/**"/>

ResponseBody

(9)ResponseBody 使用到了json转换器jackson,添加maven依赖
核心包:jackson-databind jackson-annatation jackson-core

    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>2.8.1</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.8.1</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-annotations</artifactId>
      <version>2.8.1</version>
    </dependency>

Ajax前后端数据传输

jQuery Ajax实现前后台json数据传输并使用@RequestBody封装成对象传输到后台@ResponseBody封装成对象返回到jsp

$(function () {
            $('#ajax').click(function () {
                $.ajax({
                    url:'user/testAjax2',
                    contentType:'application/json; charset=UTF-8',
                    type:'post',
                    data:'{"username":"zoufuob","password":"12345"}',
                    dataType:'json',
                    error:function () {
                        alert("获取数据失败")
                    },
                    success:function (data) {
                        alert(data.username)
                        alert(data.password)
                    }
                })
            })
        })
//jackson把json String封装发哦user对象
@RequestMapping("/testAjax2")
    public @ResponseBody User testAjax2(@RequestBody User user){
        System.out.println("执行了testAjax2");
        System.out.println(user);
        //模拟查找修改数据库数据
        user.setUsername("wangdatao");
        user.setPassword("52zoufubo");
        return user;
    }

异常处理

  • (1)异常类 继承Exception
  • (2)异常解析类 实现接口HandlerExceptionResolver重写resolveException方法
public ModelAndView resolveException(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse, Object o, Exception e) {
        //获取异常对象
        SysException exception=null;
        if(e instanceof SysException){
            exception= (SysException) e;
        }else{
            exception = new SysException("error");
        }
        //创建modelandview
        ModelAndView modelAndView=new ModelAndView();
        modelAndView.addObject("errorMsg",exception.getMsg());
        modelAndView.setViewName("error");
        return modelAndView;
    }
  • (3)配置异常处理器(配置异常解析类对象到spring)

在这里插入图片描述

文件上传

表单 enctype=”multipart/form-data”

单服务器文件上传

用MultipartFile对象作为Controller参数接收表单传入数据,通过transferTo方法上传文件

public String testUpload2(HttpServletRequest request, MultipartFile upload2)throws Exception{
        System.out.println("文件上传");
        String path=request.getSession().getServletContext().getRealPath("/uploads/");
        File file=new File(path);
        if(!file.exists()){
            file.mkdir();
        }
        String name=upload2.getOriginalFilename();
        String uuid=UUID.randomUUID().toString().replace("-","");
        name=uuid+"_"+name;
        upload2.transferTo(new File(path,name));
        return "success";
    }

跨服务器上传文件

  • (1)创建客户端对象
  • (2)与服务器建立连接
  • (3)传入数据
@RequestMapping("testUpload3")
    public String testUpload3(MultipartFile upload3) throws IOException {
        System.out.println("跨服务器文件上传");
        String path="http://localhost:8090/uploads/";
        String name=upload3.getOriginalFilename();
        String uuid=UUID.randomUUID().toString().replace("-","");
        name=uuid+"_"+name;
        //创建客户端对象
        Client client=Client.create();
        //与服务器进行连接
        WebResource resource=client.resource(path+name);
        //传文件
        resource.put(upload3.getBytes());
        return "success";
    }

拦截器

功能与过滤器基本相同,但是拦截器只能对用户请求的方法进行拦截,用在权限验证,判断用户是否登录,记录请求信息的日志

  • 拦截器类 实现接口HandlerInterceptor 可重写
    • preHandle(返回true时执行下一个拦截器,没有拦截器时执行Controller)
    • postHandle(该方法在控制器请求方法调用之后,视图解析之前进行执行)
    • afterHandle(在视图解析后执行)
  • 配置拦截器
<mvc:interceptors>
        <mvc:interceptor>
            <!--要拦截的方法-->
            <mvc:mapping path="/user/testInterceptor"/>
            <bean class="com.dingxiang.Interceptor.MyInterceptor" id="myInterceptor"/>
        </mvc:interceptor>
        <mvc:interceptor>
            <!--要拦截的方法-->
            <mvc:mapping path="/user/testInterceptor"/>
            <bean class="com.dingxiang.Interceptor.MyInterceptor2" id="myInterceptor2"/>
        </mvc:interceptor>
        <mvc:interceptor>
            <mvc:mapping path="/login/main"/>
            <bean class="com.dingxiang.Interceptor.loginInterceptor.LoginInterceptor" id="loginInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>

数据验证

网页前端验证后还需要在服务器端对数据进行验证

Spring Validator接口

首先需要编写一个Vaidator类实现该接口,对数据进行验证的配置,相当于JSR303的注解配置验证信息;
然后再主配置文件中配置一个ReloadableResourceBundleMessageSource Bean并打开注解validator

<bean class="org.springframework.context.support.ReloadableResourceBundleMessageSource" id="messageSource">
        <property name="basename" value="classpath:errorMessege"/>
    </bean>
<mvc:annotation-driven validator="validator"/>

JSR303 JSR-303

Java EE 6 中的一项子规范,叫做 Bean Validation JSR 303 用于对 Java Bean 中的字段的值进行验证。

  1. Bean Validation 中内置的 constraint

    • @Null
      被注释的元素必须为 null
    • @NotNull
      被注释的元素必须不为 null
    • @AssertTrue
      被注释的元素必须为 true
    • @AssertFalse
      被注释的元素必须为 false
    • @Min(value)
      被注释的元素必须是一个数字,其值必须大于等于指定的最小值
    • @Max(value)
      被注释的元素必须是一个数字,其值必须小于等于指定的最大值
    • @DecimalMin(value)
      被注释的元素必须是一个数字,其值必须大于等于指定的最小值
    • @DecimalMax(value)
      被注释的元素必须是一个数字,其值必须小于等于指定的最大值
    • @Size(max, min)
      被注释的元素的大小必须在指定的范围内
    • @Digits (integer, fraction)
      被注释的元素必须是一个数字,其值必须在可接受的范围内
    • @Past
      被注释的元素必须是一个过去的日期
    • @Future
      被注释的元素必须是一个将来的日期
    • @Pattern(value)
      被注释的元素必须符合指定的正则表达式
  2. Hibernate Validator 附加的 constraint

    • @Email
      被注释的元素必须是电子邮箱地址
    • @Length
      被注释的字符串的大小必须在指定的范围内
    • @NotEmpty
      被注释的字符串的必须非空
    • @Range
      被注释的元素必须在合适的范围内

与Validator不同的是需要配置一个LocalValidatorFactoryBean

 <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
        <property name="providerClass" value="org.hibernate.validator.HibernateValidator"/>
        <property name="validationMessageSource" ref="messageSource"/>
    </bean>
  • 本文作者: dzou | 微信:17856530567
  • 本文链接: http://www.dzou.top/post/f3a4f54b.html
  • 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!
  • 并保留本声明和上方二维码。感谢您的阅读和支持!