Spring-MVC学习笔记

工作流程

控制器

public class MyController implements Controller {
    @Override
    public ModelAndView handleRequest(javax.servlet.http.HttpServletRequest httpServletRequest, javax.servlet.http.HttpServletResponse httpServletResponse) throws Exception {
        ModelAndView mv = new ModelAndView();
        mv.addObject("message", "Hello Vue");
        mv.setViewName("/WEB-INF/jsp/welcome.jsp");
        return mv;
    }
}

Dispatch配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="/my.do" class="com.xx.handlers.MyController"/>
</beans>

注册控制器

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">

<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:myDispatch.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>

URLPattern中用 / 出现的静态资源访问问题

解决办法1

<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.jpg</url-pattern>
</servlet-mapping>

解决办法2 (好用)要写在最上。

<mvc:default-servlet-handler/>

解决办法3

<mvc:resources mapping="/images/" location="/images/**"/>

映射器

默认使用的是BeanNameUrlHandlerMapping

使用SimpleUrlHandlerMapping, 可以实现多个url指向同一个Controller

<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    <property name="mappings">
        <props>
            <prop key="hello.do">myController</prop>  // key指定路由 
            <prop key="my">myController</prop>
            <prop key="xx">myControl ler</prop>
        </props>
    </property>
</bean>

适配器

SimpleControllerHandleAdapter

所有实现了Controller的Bean,均是通过该适配器进行适配,执行的。

HttpRequestHandlerAdapter

所有实现了HttpRequestHandler的Bean,均是通过该适配器进行适配,执行的。

处理器

AbstactController

继承自WebContentGenerator,它有setSupportedMethods方法,控制请求的方式,默认支持GET,POST

<bean id="/hello" class="com.xx.handlers.MyController">
    <property name="supportedMethods" value="GET"/>
</bean>

视图解析器

默认的视图解析器 internalResourceViewResolver 

该视图解析器用于完成对当前web应用内部资源的封装和跳转,而对于内部资源的查找规则是,将ModelAndView中指定的视图名与为视图解析器配置的前缀和后缀结合的方式,拼接成一个Web应用内部资源路径。拼接规则是前缀+视图名称+后缀。

缺陷:不能访问外部资源。对于内部资源的定义,只能定义一种格式的资源,存放在同一目录的同一文件类型的资源文件。

 

BeanNameViewResolver

将Bean名称与View绑定

<bean id="taobao" class="org.springframework.web.servlet.view.RedirectView">
    <property name="url" value="http://www.taobao.com"/>
</bean>
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
return new ModelAndView("welcome");

xmlViewResolver

将View视图专门抽取出来,单独定义为一个xml。可以使用xmlViewResolver

<bean class="org.springframework.web.servlet.view.XmlViewResolver">
    <property name="location" value="classpath:myViews.xml"/>
</bean>

ResourceBundleViewResolver

将视图写到,properties文件中

<bean class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
    <property name="basename" value="myViews"/>
</bean>
baidu.(class)=org.springframework.web.servlet.view.RedirectView
baidu.url=http://www.baidu/.com
welcome.(class)=rg.springframework.web.servlet.view.JstlView
welcome.url=/WEB-INF/jsp/welcome.jsp

视图解析器的优先级

视图解析器有一个order属性,专门用于设置多个视图解析器的优先级。数字越小,优先级越高,数字相同,先注册的优先注册。

注解式开发

基础

注册组件扫描器

<context:component-scan base-package="com.xx.handlers"/>
@Controller
@RequestMapping("/test") //请求uri命名空间的定义
public class MyController{
@RequestMapping(value = "/ok", method = RequestMethod.GET, params = {"name", "age"})
// method 请求方法的限定
// params 对请求参数的限定 !name 表示不能有name参数 age=23 表示参数必须带age其值必须为23 age!=25 必须带age其值不能为25
public ModelAndView getOk(){
return new ModelAndView("/WEB-INF/jsp/welcome.jsp");
}
}

接收请求中的参数

接收get post请求

@RequestMapping(value = "/pok", method = RequestMethod.POST)
public ModelAndView postOk(String name, Integer age){
    System.out.println(name);
    System.out.println(age);
    return new ModelAndView("/WEB-INF/jsp/welcome.jsp");
}

还可以像servlet中那样做,用HttpServeletRequest

中文乱码问题解决

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>
    <init-param>
        <param-name>forceResponseEncoding</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>

校正求情参数名

@RequestMapping(value = "/pok", method = RequestMethod.POST)
public ModelAndView postOk(@RequestParam(name = "rname") String name, Integer age){
    return new ModelAndView("/WEB-INF/jsp/welcome.jsp");
}

Object接收

<form action="/NewWeb/test/pok" method="post">
    <label>输入名称
        <input name="name" type="text">
    </label>
    <label>输入年龄
        <input name="age" type="number">
    </label>
    <label>输入学校
        <input name="school.name" type="text">
    </label>
    <label>输入地址
        <input name="school.address" type="text">
    </label>
    <input type="submit" value="提交">
</form>
@RequestMapping(value = "/pok", method = RequestMethod.POST)
public ModelAndView postOk(User user){
    System.out.println(user);
    return new ModelAndView("/WEB-INF/jsp/welcome.jsp");
}

路径变量

@RequestMapping(value = "/user/{name}", method = RequestMethod.GET)
public ModelAndView getOk(@PathVariable("name") String name){
    ModelAndView mv = new ModelAndView("/WEB-INF/jsp/welcome.jsp");
    return mv;
}

返回ModelAndView

返回string

内部资源

@RequestMapping(value = "/ok", method = RequestMethod.GET)
public String getOk(){
    return "/WEB-INF/jsp/welcome.jsp";
}

外部资源。 仍然要注册

@RequestMapping(value = "/ok02", method = RequestMethod.GET)
public String getOk02(){
    return "baidu";
}

返回Object

用 json 进行前后端交互。

将object数据转化为json数据,需要由http消息转换器httpmessageconverter完成。转换器的开启,需要注册

<mvc:annotation-driven/>

可以用map

@RequestMapping(value = "/do")
@ResponseBody
public Object getOk02(){
    Map<String, User> map = new HashMap<String, User>();
    map.put("user1", new User("张三", 23 ));
    map.put("user2", new User("李三", 21 ));
    return map;
}

或者list

@RequestMapping(value = "/do")
@ResponseBody
public Object getOk02(){
    List<User> list = new ArrayList<User>();
    list.add(new User("qqq",23));
    list.add(new User("vvv",21));
    return list;

核心技术

重定向

重定向携带参数

一般通过HttpSession,或者ModelAndView的addObject方法

@RequestMapping(value = "/ok", method = RequestMethod.GET)
public ModelAndView getOk(){
    ModelAndView mv = new ModelAndView();
    mv.addObject("user", "xxx");
    mv.setViewName("redirect:do");
    return mv;
}
@RequestMapping(value = "/do")
@ResponseBody
public Object getOk02(String user){
    System.out.println(user);
    return user;
}
@RequestMapping(value = "/ok", method = RequestMethod.GET)
public ModelAndView getOk(User user,HttpSession session){
    session.setAttribute("user", user);
    return new ModelAndView("redirect:do");
}
@RequestMapping(value = "/do")
@ResponseBody
public Object getOk02(HttpSession session){
    User user = (User) session.getAttribute("user");
    return user;
}

异常处理

<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="defaultErrorView" value="/WEB-INF/error/error-page.jsp"/>
<property name="exceptionAttribute" value="ex"/>
<property name="exceptionMappings">
<props>
<prop key="com.xx.exception.NameException">/error/name_error.jsp</prop>
<prop key="com.xx.exception.AgeException">age_error.jsp</prop>
</props>
</property>
</bean>

error-page

<body>
<div>
    error page
    ${ex.message }
</div>
</body>

自定异常处理器

public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
    ModelAndView mv = new ModelAndView();
    mv.addObject("ex", e);
    mv.setViewName("/erro/error-page.jsp");
    if(e instanceof NameException){
        System.out.println("name error");
    }
    if(e instanceof AgeException){
        System.out.println("age error");
    }
    return mv;
}
<bean class="com.xx.exception.resolver"/>

注解式自定义异常处理器

@ExceptionHandler(NameException.class)
public ModelAndView resolveException(Exception e) {
ModelAndView mv = new ModelAndView();
mv.addObject("ex", e);
System.out.println(e.getMessage());
return mv;
}

改代码写在 ExceptionResolverController中,继承自BaseController(即MyController)

类型转换器

 自定义类型转换器

public class MyDataConvert implements Converter<String, Date> {
@Override
public Date convert(String s) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
try {
return sdf.parse(s);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
}

注册类型转换器

<!--    注册类型转换器-->
<bean id="myDataConvert"  class="com.lh.handlers.MyDataConvert"/>
<!--    注册转换服务对象-->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
    <property name="converters" ref="myDataConvert"/>
</bean>
<mvc:annotation-driven conversion-service="conversionService"/>

文件上传

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="defaultEncoding" value="utf-8"/>
    <property name="maxUploadSize" value="1048576"/>
</bean> 
 @RequestMapping(value = "/test01", method = RequestMethod.POST)
 public ModelAndView doFile(MultipartFile photo, HttpSession session) throws IOException {
     if (!photo.isEmpty()){
         String path = session.getServletContext().getRealPath("/images");
         String fileName = photo.getOriginalFilename();
         System.out.println(path);
         assert fileName != null;
         if (fileName.endsWith(".jpg") || fileName.endsWith(".png")){
             File file = new File(path, fileName);
             photo.transferTo(file);
         }
     }else {
         return new ModelAndView("fail.jsp");
     }
     return new ModelAndView("success.jsp");
 }

拦截器

public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        
        return false; // 执行false表示被拦截
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}

注册拦截器

<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/**"/>
        <bean class="com.xx.interceptors.MyInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

猜你喜欢

转载自www.cnblogs.com/wrnmb/p/10741564.html