Springmvc的基本使用

1. servlet

1.1配置servlet

  SpringMVC中, 只有一个servlet,就是DispatcherServlet, 所有的请求,都通过这个servlet转发到controller, 我们需要在web.xml中配置一个servlet指向DispatcherServlet。

	<servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <!-- 下面这个mvc.xml文件是我放在resources目录下的一个配置springmvc的文件-->
            <param-value>classpath:mvc.xml</param-value>
        </init-param>
    </servlet>
	<servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

1.1 设置url-pattern的三种方式

  从上面, 我们可以看到在servlet-mapping中有一个url-pattern, 这个属性的意思是,匹配什么规则的url进来执行springmvc的逻辑。那么设置规则,常用的有三种方式:

  • 设置为*.do``,*.action 访问以do或者action结尾的所有路径都可以进行映射,比如访问xxx.do,aaa.do
  • 设置为/ 这种就是匹配所有的路径,但是不会拦截jsp文件
  • 设置/**这种会匹配所有的路径

使用最后面2种,都会有一种问题, 那就是静态资源(css,js,html等)也会拦截,那么怎么解决了? 有如下2中方案:

  1. 在mvc.xml中配置默认的servlet处理器,让dispatcherServlet不处理静态资源,直接交给tomcat处理
<mvc:default-servlet-handler></mvc:default-servlet-handler>
  1. 在mvc.xml中配置resources,指定以某个字符串开头的都定位到某个目录下面去(资源目录)
<mvc:resources mapping="/resources/**" location="classpath:/"></mvc:resources>

2. 请求参数

 请求路径的映射需要使用到@RequestMapping注解, 这个注解可以标注在类上, 也可以标注在方法上,实际开发中, 一般是在类上和方法上同时使用, 在类上使用填写模块名, 方法上使用填写具体的方法名, 那么完整的请求路径就是类上的路径和方法上的路径拼接而成。

2.1 简单类型的绑定

  获取简单类型的数据, 只需要在方法的形参中,直接定义就可以接受,注意需要形参名前端传过来的参数名一致才可以接受得到。

	@RequestMapping("/test5")
    public void test5(String name) {
        System.out.println(name);
        return;
    }

如果说,前端是个比较有个性的小伙, 就是不按你的命名来, 但是你又想使用自己的命名规则, 你就可以使用@RequestParam注解在转换一下

	@RequestMapping("/test5")
	// 前端传过来的名为username, 用@RequestParam("username")接受后, 定义为name
    public void test5(@RequestParam("username") String name) {
        System.out.println(name);
        return;
    }

2.2 时间类型的绑定

 时间类型的转换, 不能像基础类型一样,直接定义为Date类型的变量就可以直接转换, 因为前端传过来的是一个字符串,那么我们需要做的是把字符串手动转换为Date类型。 怎么做了? SpringMVC为我们提供了Converter接口, 我们只需要实现这个接口,就可以完成字符串到Date的转化。

// Converter<String, Date> string表示需要被转化的变量类型, Date表示转化之后的类型
public class DateConverter implements Converter<String, Date> {
    @Override
    public Date convert(String s) {
    	// 转化逻辑
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        try {
            Date parse = simpleDateFormat.parse(s);
            return parse;
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }
}

配置完上面的转化器, 我们还需要在mvc.xml中配置一个格式转化器的bean,并把我们写的转换器通过赋值的形式传递进去。

<bean id="conversionServiceBean" 
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <bean class="com.sherlock.converter.DateConverter"></bean>
            </set>
        </property>
    </bean>

最后我们就可以在contorller中直接使用了

	@RequestMapping("/test7")
    public void test7(Date date) {
        System.out.println(date);
    }

2.3 POJO类型的绑定

 我们只需要在方法的形参上面, 直接定义为需要接受的POJO类型就可以了,比如我们有一个user的pojo类,我们需要接受一个user类型的数据,我们可以这样写

public class User {

    private String name;
    private Integer age;
    private Address address;
    
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
    
	public Address getAddress() {
        return address;
    }

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

	// controller中获取
	@RequestMapping("/test6")
    public void test6(User user) {
        System.out.println(user);
    }

2.4 POJO包装对象的绑定

 这个跟pojo对象一样, 需要注意的就是,前端传值的方式.

public class Address {

    private String city;

    @Override
    public String toString() {
        return "Address{" +
                "city='" + city + '\'' +
                '}';
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }
}
  • x-www-form-urlencode方式传值,以上面user对象为例, 需要传address.city这个字符串作为key,后台才能接受。
  • application/json方式储值,以上面对象为例,需要传{“address”:{“city”}}这样填写,后台才能正常接受并赋值

2.5 RESTFUL风格的参数绑定

 restful风格,最主要的路径特定就是,路径中会有可变的参数,比如/user/1,/user/2,那么后台如何获取这个1或者2了,可以使用@PathVariable这个注解来获取。 比如:

	 @RequestMapping("/user/{id}")
    public void test5(@PathVariable("id") Integer id) {
        System.out.println(id);

        return;
    }

3. 返回类型

3.1 返回视图

3.1.1 绑定ModelAndView

	@RequestMapping("/test1")
    public ModelAndView test1(ModelAndView modelAndView) {
    	//向model中放入数据
    	modelAndView.addObject("name", "sherlock");
        
        // 设置需要跳转的页面
        modelAndView.setViewName("test");
        return modelAndView;
    }

在上面为什么setViewName可以直接写test,而不写/WEB-INF/jsp/test.jsp,那是因为在mvc.xml中配置视图的前后缀,springmvc会自动帮我们拼接。

 <bean  class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>

3.1.2 绑定ModelMap

	@RequestMapping("/test2")
    public String test2(ModelMap modelMap) {
        modelMap.addAttribute("name", "sherlock");
        return "test";
    }

3.1.3 绑定Model

	@RequestMapping("/test4")
    public String test4(Model model) {
        model.addAttribute("name", "sherlock");
        return "test";
    }

3.1.4 绑定Map

	@RequestMapping("/test3")
    public String test3(Map<String, Object> map) {
        map.put("name", "sherlock");
        return "test";
    }

3.1.5 ModelAndView,ModelMap,Model,Map的联系

 上面的4种写法,都可以得到同样的结果。为什么可以得到同样的结果了,我们来分析一下。

1.ModelAndView这个类中,有两个属性,其中有一个就是ModelMap类型的。
2.ModelMap继承了LinkedHashMap, 而LinkedHashMap继承了HashMap,实现了map
3.ModelMap,Model,Map在运行中, 都是BindingAwareModelMap类型
4.BindingAwareModelMap继承了ExtendedModelMap, ExtendedModelMap继承了ModelMap实现了Model

3.2 返回json字符串

  需要返回json字符串,首先就需要引入json的依赖了, springmvc默认是使用jackson,所以使用引入jackson的依赖。

		<!-- 引入的依赖版本不能太高,我最开始是引入的最新的,后台编译的时候,
		报错了,报错的原因是因为jdk版本不匹配,所以就降低了版本号-->
 		<dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.9.0</version>
        </dependency>

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

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

然后需要在方法上或者类上@ResponseBody注解,然后返回的类型直接为POJO类型就可以了。

	 @ResponseBody
    @RequestMapping("/test9")
    public User test9() {
        User user = new User();
        user.setAge(12);
        user.setName("12");

        return user;
    }

4. 高级应用

4.1过滤器

 过滤器这个层面是再tomcat层的, 所以配置文件需要写在web.xml中。我们以一个实际的需求为例, 在post请求中,如果传递到后端的值有中文,使用默认的编码的话,会是乱码,所以我们需要转化编码为UTF-8,那么我们就可以使用过滤器来配置一下。

	<filter>
        <filter-name>encoding</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>
    </filter>
    <filter-mapping>
        <filter-name>encoding</filter-name>
        <url-pattern>/*</url-pattern> <!-- 拦截所有的路径-->
    </filter-mapping>

4.2拦截器

 拦截器是springmvc中的,会有三个时机可以拦截, 第一个是方法执行前, 第二个是方法执行后,第三个是视图完成之后。那么对于这三个时机,我们在时机项目中, 最常见的是使用第一个在方法执行前, 我们可以做一些权限校验。主要是实现HandlerInterceptor这个接口。

public class MyIntercept01 implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("01===>preHandle");
        // 实际开发中,我们再这里进行权限判断
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("01===>postHandle");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("01===>afterCompletion");
    }
}

然后我们还需要在mvc.xml中配置这个监听器才会生效

 <mvc:interceptors>
		<!-- 可以配置多个-->
        <mvc:interceptor>
            <mvc:mapping path="/**"/> <!-- 拦截的路径-->
            <mvc:exclude-mapping path="/test"/><!-- 排序的路径-->
            <bean class="com.sherlock.intercept.MyIntercept01"></bean> <!-- 自定义的拦截器-->
        </mvc:interceptor>

        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="com.sherlock.intercept.MyIntercept02"></bean>
        </mvc:interceptor>
    </mvc:interceptors>

当我们配置多个的时候,拦截器的执行顺序,跟配置的顺序相关. 具体方法执行的顺序为
MyIntercept01.preHandle->MyIntercept02.preHandle->MyIntercept02.postHandle->MyIntercept01.postHandle->MyIntercept02.afterCompletion->MyIntercept01.afterCompletion

preHandle方法为正序, postHandle,afterCompletion方法为倒叙

4.3统一异常处理

 异常处理我们可以统一处理,从而优雅的实现具体的逻辑代码。在业务层具体抛出不同类型的异常,我们可以定义多个自己想处理的异常来统一接受处理这些异常

定义一个类

@RestControllerAdvice // 这个注解必须要
public class MyException {

	// 这个注解必须要, 参数为需要处理的异常类型,可以捕获这个类型以及它的子类
    @ExceptionHandler(Exception.class) 
    public void dealException() {
        System.out.println("dealException");
    }
}

4.4multipart(文件上传)数据处理

&emsp;文件上传,我们首先需要引入一个依赖common-file,然后在方法的形参上使用MultipartFile类型来接受文件。

	<dependency>
       	<groupId>commons-fileupload</groupId>
         <artifactId>commons-fileupload</artifactId>
         <version>1.4</version>
     </dependency>
	@RequestMapping("/test8")
    public void test8(MultipartFile name) throws IOException {
    	// name这个变量里面就封装了文件的所有信息
    	// 比如获取文件的原始文件名
        String originalFilename = name.getOriginalFilename();
        // 下面这个方法,可以把当前的文件,复制到磁盘上去
        File finalFile = new File("/tmp");
        name.transferTo(finalFile);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值