天天看点

springmvc的简单总结

框架原理

springmvc的简单总结

web层的知识结构导图 

springmvc的简单总结

springmvc的简单总结

SpringMVC的各种参数绑定方式

1. 基本数据类型(以int为例,其他类似):

Controller代码:

@RequestMapping("saysth.do")
public void test(int count) {
}
           

表单代码:

<form action="saysth.do" method="post">
<input name="count" value="10" type="text"/>
......
</form>
           

表单中input的name值和Controller的参数变量名保持一致,就能完成数据绑定,如果不一致可以使用@RequestParam注解。需要注意的是,如果Controller方法参数中定义的是基本数据类型,但是从页面提交过来的数据为null或者”"的话,会出现数据转换的异常。也就是必须保证表单传递过来的数据不能为null或”",所以,在开发过程中,对可能为空的数据,最好将参数数据类型定义成包装类型,具体参见下面的例子。

2. 包装类型(以Integer为例,其他类似):

Controller代码:

@RequestMapping("saysth.do")
public void test(Integer count) {
}
           

表单代码:

<form action="saysth.do" method="post">
<input name="count" value="10" type="text"/>
......
</form>
           

和基本数据类型基本一样,不同之处在于,表单传递过来的数据可以为null或”",以上面代码为例,如果表单中num为”"或者表单中无num这个input,那么,Controller方法参数中的num值则为null。

3. 自定义对象类型:

Model代码:

public class User {
    private String firstName;
    private String lastName;

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

}
           

Controller代码:

@RequestMapping("saysth.do")
public void test(User user) {
}
           

表单代码:

<form action="saysth.do" method="post">
<input name="firstName" value="张" type="text"/>
<input name="lastName" value="三" type="text"/>
......
</form>
           

非常简单,只需将对象的属性名和input的name值一一匹配即可。

4. 自定义复合对象类型:

Model代码:

public class ContactInfo {
    private String tel;
    private String address;

    public String getTel() {
        return tel;
    }

    public void setTel(String tel) {
        this.tel = tel;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

}

public class User {
    private String firstName;
    private String lastName;
    private ContactInfo contactInfo;

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public ContactInfo getContactInfo() {
        return contactInfo;
    }

    public void setContactInfo(ContactInfo contactInfo) {
        this.contactInfo = contactInfo;
    }

}
           

Controller代码:

@RequestMapping("saysth.do")
public void test(User user) {
    System.out.println(user.getFirstName());
    System.out.println(user.getLastName());
    System.out.println(user.getContactInfo().getTel());
    System.out.println(user.getContactInfo().getAddress());
}
           

表单代码:

<form action="saysth.do" method="post">
<input name="firstName" value="张" /><br>
<input name="lastName" value="三" /><br>
<input name="contactInfo.tel" value="13809908909" /><br>
<input name="contactInfo.address" value="北京海淀" /><br>
<input type="submit" value="Save" />
</form>
           

User对象中有ContactInfo属性,Controller中的代码和第3点说的一致,但是,在表单代码中,需要使用“属性名(对象类型的属性).属性名”来命名input的name。

总结 :

   1.controller中的方法主要是用于参数  可以是简单类型,pojo,包装的pojo, 也可以是Httpsession,        HttpServletRequest,HttpServletResponse,Model

Controller方法返回值

返回void(和在servlet中一样)

在Controller方法形参上可以义request和response,使用request或response指定响应结果:

1、使用request转发页面,如下:

request.getRequestDispatcher("页面路径").forward(request, response);

request.getRequestDispatcher("/WEB-INF/jsp/success.jsp").forward(request, response);
           

2、可以通过response页面重定向:

response.sendRedirect("url")

response.sendRedirect("/springmvc-web2/itemEdit.action");
           
  1. 可以通过response指定响应结果,例如响应json数据如下:
response.getWriter().print("{\"abc\":123}");
           

返回字符串(转发或是重定向写在字符串中)

Redirect重定向

Contrller方法返回字符串可以重定向到一个url地址

如下商品修改提交后重定向到商品编辑页面。

/**

 * 更新商品

 *

 * @param item

 * @return

 */

@RequestMapping("updateItem")

public String updateItemById(Item item) {

// 更新商品

this.itemService.updateItemById(item);



// 修改商品成功后,重定向到商品编辑页面

// 重定向后浏览器地址栏变更为重定向的地址,

// 重定向相当于执行了新的request和response,所以之前的请求参数都会丢失

// 如果要指定请求参数,需要在重定向的url后面添加 ?itemId=1 这样的请求参数

return "redirect:/itemEdit.action?itemId=" + item.getId();

}
           

forward转发

Controller方法执行后继续执行另一个Controller方法

如下商品修改提交后转向到商品修改页面,修改商品的id参数可以带到商品修改方法中。

/**

 * 更新商品

 *

 * @param item

 * @return

 */

@RequestMapping("updateItem")

public String updateItemById(Item item) {

// 更新商品

this.itemService.updateItemById(item);



// 修改商品成功后,重定向到商品编辑页面

// 重定向后浏览器地址栏变更为重定向的地址,

// 重定向相当于执行了新的request和response,所以之前的请求参数都会丢失

// 如果要指定请求参数,需要在重定向的url后面添加 ?itemId=1 这样的请求参数

// return "redirect:/itemEdit.action?itemId=" + item.getId();



// 修改商品成功后,继续执行另一个方法

// 使用转发的方式实现。转发后浏览器地址栏还是原来的请求地址,

// 转发并没有执行新的request和response,所以之前的请求参数都存在

return "forward:/itemEdit.action";



}

//结果转发到editItem.action,request可以带过去

return "forward: /itemEdit.action";
           

异常处理器

springmvc在处理请求过程中出现异常信息交由异常处理器进行处理,自定义异常处理器可以实现一个系统的异常处理逻辑。

springmvc的简单总结
    1. 自定义异常类

为了区别不同的异常,通常根据异常类型进行区分,这里我们创建一个自定义系统异常。

如果controller、service、dao抛出此类异常说明是系统预期处理的异常信息。

    1. 自定义异常处理器
public class CustomHandleException implements HandlerExceptionResolver {

@Override

public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,

Exception exception) {

// 定义异常信息

String msg;

// 判断异常类型

if (exception instanceof MyException) {

// 如果是自定义异常,读取异常信息

msg = exception.getMessage();

} else {

// 如果是运行时异常,则取错误堆栈,从堆栈中获取异常信息

Writer out = new StringWriter();

PrintWriter s = new PrintWriter(out);

exception.printStackTrace(s);

msg = out.toString();



}



// 把错误信息发给相关人员,邮件,短信等方式

// TODO

// 返回错误页面,给用户友好页面显示错误信息

ModelAndView modelAndView = new ModelAndView();

modelAndView.addObject("msg", msg);

modelAndView.setViewName("error");这个view是自己需要写好的吗??



return modelAndView;

}

}
           
    1. 异常处理器配置

在springmvc.xml中添加:

<!-- 配置全局异常处理器 -->

<bean 

id="customHandleException"  class="cn.itcast.ssm.exception.CustomHandleException"/>

</bean>

异常测试

修改ItemController方法“queryItemList”,抛出异常:

/**

 * 查询商品列表

 *

 * @return

 * @throws Exception

 */

@RequestMapping(value = { "itemList", "itemListAll" })

public ModelAndView queryItemList() throws Exception {

// 自定义异常

if (true) {

throw new MyException("自定义异常出现了~");

}



// 运行时异常

int a = 1 / 0;



// 查询商品数据

List<Item> list = this.itemService.queryItemList();

// 创建ModelAndView,设置逻辑视图名

ModelAndView mv = new ModelAndView("itemList");

// 把商品数据放到模型中

mv.addObject("itemList", list);



return mv;

}
           

上传图片

在tomcat上配置图片虚拟目录

springmvc的简单总结

访问http://localhost:8080/pic图片名  测试效果

    1. 配置上传解析器

在springmvc.xml中配置文件上传解析器

<!-- 文件上传,id必须设置为multipartResolver -->

<bean id="multipartResolver"

class="org.springframework.web.multipart.commons.CommonsMultipartResolver">

<!-- 设置文件上传大小 -->

<property name="maxUploadSize" value="5000000" />

</bean>
           
springmvc的简单总结
    1. 图片上传

在更新商品方法中添加图片上传逻辑

    1. @RequestBody

作用:

@RequestBody注解用于读取http请求的内容(字符串),通过springmvc提供的HttpMessageConverter接口将读到的内容(json数据)转换为java对象并绑定到Controller方法的参数上。(之前传入的都是字符串的形式的json数据  这里一定要是json对象的数据)

    1. @ResponseBody

作用:

@ResponseBody注解用于将Controller的方法返回的对象,通过springmvc提供的HttpMessageConverter接口转换为指定格式的数据如:json,xml等,通过Response响应给客户端

      1. ItemController编写
/**

 * 测试json的交互

 * @param item

 * @return

 */

@RequestMapping("testJson")

// @ResponseBody

public @ResponseBody Item testJson(@RequestBody Item item) {

return item;

}
           

<mvc:annotation-driven />:解析:@RequestMapping("testJson")  @ResponseBody   @RequestBody 等注解

总结:

我们前台请求过去的json字符串,在使用@RequestBody注解后 被HttpMessageConverter,转换成对应的java对象,然后我们在用@ResponseBody注解,将java对象 以特定的格式(通常都是json)相应给浏览器。

关于@ResponseBody与@RequestBody注解的用法可以参考这篇博客:https://blog.csdn.net/weixin_43732955/article/details/92843116

拦截器

实现HandlerInterceptor接口,如下:

public class HandlerInterceptor1 implements HandlerInterceptor {

// controller执行后且视图返回后调用此方法

// 这里可得到执行controller时的异常信息

// 这里可记录操作日志

@Override

public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)

throws Exception {

System.out.println("HandlerInterceptor1....afterCompletion");

}



// controller执行后但未返回视图前调用此方法

// 这里可在返回用户前对模型数据进行加工处理,比如这里加入公用信息以便页面显示

@Override

public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)

throws Exception {

System.out.println("HandlerInterceptor1....postHandle");

}



// Controller执行前调用此方法

// 返回true表示继续执行,返回false中止执行

// 这里可以加入登录校验、权限拦截等

@Override

public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {

System.out.println("HandlerInterceptor1....preHandle");

// 设置为true,测试使用

return true;

}

}
           
    1. 拦截器配置

上面定义的拦截器再复制一份HandlerInterceptor2,注意新的拦截器修改代码:

System.out.println("HandlerInterceptor2....preHandle");

在springmvc.xml中配置拦截器

<!-- 配置拦截器 -->

<mvc:interceptors>

<mvc:interceptor>

<!-- 所有的请求都进入拦截器 -->

<mvc:mapping path="/**" />

<!-- 配置具体的拦截器 -->

<bean class="cn.itcast.ssm.interceptor.HandlerInterceptor1" />

</mvc:interceptor>

<mvc:interceptor>

<!-- 所有的请求都进入拦截器 -->

<mvc:mapping path="/**" />

<!-- 配置具体的拦截器 -->

<bean class="cn.itcast.ssm.interceptor.HandlerInterceptor2" />

</mvc:interceptor>

</mvc:interceptors>
           

日期转换问题

前端传过来是string类型   但是pojo中是date  如何进行对象映射

(一般pojo也会是string类型不会写成date)

由于日期数据有很多种格式,springmvc没办法把字符串转换成日期类型。所以需要自定义参数绑定。

前端控制器接收到请求后,找到注解形式的处理器适配器,对RequestMapping标记的方法进行适配,并对方法中的形参进行参数绑定。可以在springmvc处理器适配器上自定义转换器Converter进行参数绑定。

一般使用<mvc:annotation-driven/>注解驱动加载处理器适配器,可以在此标签上进行配置。

      1. 修改jsp页面

如下图修改itemEdit.jsp页面,显示时间

springmvc的简单总结
      1. 自定义Converter
//Converter<S, T>

//S:source,需要转换的源的类型

//T:target,需要转换的目标类型

public class DateConverter implements Converter<String, Date> {



@Override

public Date convert(String source) {

try {

// 把字符串转换为日期类型

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyy-MM-dd HH:mm:ss");

Date date = simpleDateFormat.parse(source);

return date;

} catch (ParseException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

// 如果转换异常则返回空

return null;

}

}

           
      1. 配置Converter

我们同时可以配置多个的转换器。

类似下图的usb设备,可以接入多个usb设备

<!-- 配置注解驱动 -->

<!-- 如果配置此标签,可以不用配置... -->

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



<!-- 转换器配置 -->

<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">

<property name="converters">

<set>

<bean class="cn.itcast.springmvc.converter.DateConverter" />

</set>

</property>

</bean>
           

继续阅读