为了账号安全,请及时绑定邮箱和手机立即绑定

MogonBook_Spring_SpringMVC

标签:
Java

1.SpringMVC接收Sting[]类型

由于SpringMVC接收数组类型参数需要定义数据类型,这样如果在前端直接传入一个数组则判断不出具体类型,假若传一个String类型的数组,则前端需要这样处理:

{
    "param":fujian.toString() 
}

将参数toString(),这样后端就可以辨别具体的数据类型,后端便可直接这样写:

public ModelAndView test(String[] param) {
    ModelAndView mnv = new ModelAndView();
    return mnv;
}

2.Spring MVC接收中文乱码问题

方法①:修改Tomcat的配置文件server.xml:

<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" />
中加入URIEncoding="UTF-8"//对URI使用UTF-8编码处理
userBodyEncodingForURI="true"//设置POST和GET使用相同编码

方法②:在web.xml中加入Spring的字符集过滤器

<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>forceEncoding</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>
    注意:此过滤器只对POST请求有效

3.Spring注解注入技巧
@Service:用于标注业务层<bean>
@Controller:用于标注控制层<bean>
@Repository:用于标注数据访问<bean>,即DAO<bean>
@Component:泛指<bean>,当<bean>不好归类的时候,我们可以使用这个注解进行标注

以上这几种注解从功能上来讲,其实是一样的,都是将类声明为一个<bean>,用法同@Component一样,只不过springMVC是基于三层架构来开发,所以通过这几种注解,更好区分这种层级关系,而也方便了spring后续对这几种注解加入新功能的研发。在使用上,这几种注解如果直接写在类的上面如下:

@Controller
public class LoginController(){
}

那么如果通过ApplicationContext的getBean()方法,则生成的<bean>的id为第一个字母小写的类名,此例中为loginController,如果按照以下方式来进行注解的话:

@Controller("loginController")
public class LoginController(){
}

则所生成的<bean>的id为注解中的value的值(由于value为这个注解类的唯一属性,所以"value="可以省略),此例中为loginController。注入时,如果注入的目标为非引用类型的话,如下所示:

@Controller("loginController")
public class LoginController(){
    @Value("小明")
    private String name;
}

则可以通过@Value注解来进行注入,而如果注入的类型为引用类型的话,如下所示:

@Controller("loginController")
public class LoginController(){
    @Autowired
    private LoginServiceInter loginService;
}

方法①:可以通过@Autowired注解来进行注入,但是@Autowired注解为type类型的注入方式,所以如果LoginServiceInter接口有多个实现类的话,就会报错,因为无法确定到底引用那个子类对象进行注入,所以最好通过与@Qualifier注解相配合使用,如下所示:

@Controller("loginController")
public class LoginController(){
    @Autowired
    @Qualifier("loginService")
    private LoginServiceInter loginService;
}

假如此LoginServiceInter有多个实现类加入@Service注解话,想要注入那个实现类的对象,就在那个实现类的@Service注解中传入一个参数,值为@Qualifier中的参数,如下所示:

@Service("loginService")
public class LoginServiceImpl implements LoginServiceInter(){
}
(注:当不能确定 Spring 容器中一定拥有某个类的 Bean 时,可以在需要自动注入该类 Bean 的地方可以使用 @Autowired(required = false),这等于告诉 Spring:在找不到匹配 Bean 时也不报错。)

方法②:可以通过@Resource注解,直接注入引用类型,如下所示:

@Controller("loginController")
public class LoginController(){
    @Resource(name="loginService")
    private LoginServiceInter loginService;
}
此时会从SpringContext中去寻找ID为loginService的bean并进行注入,如果没有找到的话,则会抛出异常。
@Controller("loginController")
public class LoginController(){
    @Resource(type="LoginServiceInter ")
    private LoginServiceInter loginService;
}
此时会从SpringContext中去寻找类型为LoginServiceInter的bean进行注入,但是可能会找到多个实现类,这样就会抛出异常,如果没有找到的话,同样会抛出异常。
@Controller("loginController")
public class LoginController(){
    @Resource(name="loginService",type="LoginServiceInter ")
    private LoginServiceInter loginService;
}
这样注入会更严谨一些,即会寻找ID为loginService的,同时又会寻找类型为LoginServiceInter 的bean进行注入,如果没有找到的话,则会抛出异常。
@Controller("loginController")
public class LoginController(){
    @Resource
    private LoginServiceInter loginService;
}
此时会先按照ID进行寻找,ID即为定义的变量名。
如果ID没有找到的话,则会根据类型继续寻找,如果都没有找到的话,则会抛出异常。

@Resource的作用相当于@Autowired,只不过@Autowired按照byType自动注入。


4.SpringMvc常用注解

@RequestMapping

@RequestMapping是用来映射请求的地址路径的,如下所示

@Controller
@RequestMapping("/Login")
public class LoginController {

    @Autowired
    private LoginServiceInter loginServiceImpl;

    @RequestMapping("/toLogin")
    public String toLogin(String username) {
        System.out.println(username);
        loginServiceImpl.toLogin();
        return "welcome";
    }
}

根据@RequestMapping中的参数,来配置前端访问的请求路径,如下所示:

<a href="Login/toLogin">登录</a>

这样既可找到对应要执行的方法。

@requestParam

@requestParam主要用于在SpringMVC后台控制层获取参数,类似一种是request.getParameter("name"),它有三个常用参数:defaultValue = "0", required = false, value = "type";defaultValue 表示设置默认值,required 通过boolean设置是否是必须要传入的参数false则为不是必须要传的,value 值表示接受的传入的参数类型。

@PathVariable

讲一部分请求路径作为参数传递,也可以理解成请求路径参数化,如下所示:

@Component
@RequestMapping("Common")
public class CommonDispatcher {

    @RequestMapping(value = "{folder}/{page}")
    public String gotoLogin(@PathVariable final String folder, @PathVariable final String page) {
        return folder+"/" + page;
    }
}

这样就可以通过请求路径来直接动态的跳转到对应文件夹下的页面。如下所示:

<a href="Common/home/main">登录</a>

根据试图解析器的配置,如下所示:

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

实际上请求的页面就是view文件夹下的home文件夹下的main.jsp页面,此注解的“{}”是在@RequestMapping注解参数中添加,包括修饰类名上的@RequestMapping中也可以加入“{}”。如下所示:

@Controller
@RequestMapping("/Common/{pathA}")
public class CommonDispatcher {

    @RequestMapping("/{pathB}/{page}")
    public String findPet(@PathVariable String pathA, @PathVariable String pathB,@PathVariable String page) {
        return pathA+"/"+pathB+"/"+page;
    }
}

这种方式有点类似于Struts2的通配符配置请求路径的过程。

@ResponseBody

当Controller中的方法返回的不是路径等,而是具体的数据时,则需要加入此标签。但是如果仅仅加入这个注解,当返回map或者list等类型时,会抛出ClassCast异常,因为无法将map或listd等转为json,所以还需要引入jackon相关依赖,如下所示:

图片描述

引入前还需要考虑到Jackson与Spring的版本兼容性的问题,否则会抛出类路径找不到的异常

@CrossOrigin

@CrossOrigin为跨域请求的注解,方法上加入了次注解,则该方法支持跨域访问,一般比较适合写接口,官方给出的解释如下:

图片描述

    This @CrossOrigin annotation enables cross-origin requests only for
    this specific method. By default, its allows all origins, all headers,
    the HTTP methods specified in the @RequestMapping annotation and a
    maxAge of 30 minutes is used. You can customize this behavior by
    specifying the value of one of the annotation attributes: origins,
    methods, allowedHeaders, exposedHeaders, allowCredentials or maxAge.
    In this xample, we only allow http://localhost:8081 to send
    cross-origin requests.

@RestController

@RestController注解等同于@ResponseBody与@Controller的结合,不过需要注意的是,单独使用@RestController注解时,就相当于在此Controller中所有的方法上都加入@ResponseBody,也就是说,所有的方法,返回参数都被当成数据返回,因此Controller中的方法,无法返回到指定页面,这个特性可以配合@CrossOrigin注解,专门来写跨域的接口。


5.Controller中方法返回值问题

对于SpringMvc中的方法返回值,如果在方法上加入@ResponseBody注解之后,则所返回的内容被当做数据处理,如下代码所示:

@Controller
@RequestMapping("/loginController")
public class LoginController {

    @RequestMapping("/login")
    @ResponseBody public Map<String,Object> login() {
        Map<String,Object> map = new HashMap<String,Object>();
        map.put("result", true); return map;
    }
}

此时返回的是Map类型,然而如果需要返回的内容能够正常显示,并且后端不报错,则需要在SpringMvc工程下引入Jackson的jar包,主要引入如下三个jar文件:

    jackson-annotations-2.8.2.jar
    jackson-core-2.8.2.jar
    jackson-databind-2.8.2.jar

而引入时还需要注意Spring的版本,此例中引入的Spring版本为:

    spring-core-4.3.7.RELEASE.jar

在spring 4.3以上,需要引入的jackson版本为2.6以上即可,否则会导致不兼容问题。


6.关于Js\Css等静态资源被拦截问题

想要让一些静态资源不被DispatcherServlet拦截,则需要在SpringMvc.xml中引入如下标签:

<mvc:resources location="/resources/" mapping="/resources/**"></mvc:resources>
其中location为想要放行的资源文件目录,mapping为资源目录下的内容,
*代表子目录,而**代表子目录下的全部,包括子目录中的子目录。
如果加入mvc:resources标签的话,还需要引入<mvc:annotation-driven/>标签,
否则,controller层的访问会失效,会抛出404

7.SpringMvc拦截器

Java部分需要实现HandlerInterceptor接口,并实现其方法

public class MogonInterceptor implements HandlerInterceptor{

    @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object object, Exception exception) throws Exception{
    }

    @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object object, ModelAndView mav) throws Exception{
    }

    @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception{
        return false;
    }
}

如果preHandle返回值为true,则继续当前访问,如果返回值为false,则当前访问被拦截掉。

SpringMvc.xml中配置如下:

<mvc:interceptors>
    <mvc:interceptor>
        <!-- 拦截路径 -->
        <mvc:mapping path="/loginController/login"/>
        <!-- 拦截器类 -->
        <bean class="com.mogon.framework.interceptor.MogonInterceptor"></bean>
    </mvc:interceptor>
</mvc:interceptors>

如果直接在<mvc:interceptors>标签根中配置一个

<bean class="com.mogon.framework.interceptor.MogonInterceptor"/>

而没有

<mvc:mapping path="/loginController/login"/>

则默认拦截全部请求,如下所示:

<mvc:interceptors>
    <bean class="com.mogon.framework.interceptor.MogonInterceptor"></bean>
</mvc:interceptors>

8.SpringMvc文件上传

首先SpringMvc文件上传需要依赖一下几个jar文件:

    commons-fileupload-1.3.1.jar
    commons-io-2.5.jar
    commons-logging-1.2.jar

SpringMvc.xml需要加入如下标签:

<!-- SpringMVC上传文件时,需要配置MultipartResolver处理器 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!-- 指定所上传文件的总大小不能超过1024KB。注意maxUploadSize属性的限制不是针对单个文件,而是所有文件的容量之和 -->
    <property name="maxUploadSize" value="102400000"/>
</bean>

前端页面写法:

<form action="file/upload" method="post" enctype="multipart/form-data">
    <input type="file" name="file">
    <input type="submit" value="上传">
</form>

后端代码:

@RequestMapping("/upload")
@ResponseBody
public String upload(@RequestParam("file") MultipartFile file) {
    try {
        if (!file.isEmpty()) {
            FileUtils.copyInputStreamToFile(file.getInputStream(), new File("F:\\" + file.getOriginalFilename()));
        }
    } catch (Exception e) {
        e.printStackTrace();
        return "false";
    }
    return "true";
}

9.SpringMvc文件下载

后端代码如下:

@RequestMapping("/download")
public ResponseEntity<byte[]> download() throws IOException {
    // 文件下载路径
    String path = "E:\\Java\\JavaDoc\\Java_NbBook\\jstl中文教程.pdf";
    // 加载文件到内存
    File file = new File(path);
    // 创建头信息
    HttpHeaders headers = new HttpHeaders();
    // 解决中文名称乱码问题
    String fileName = new String("未命名.pdf".getBytes("UTF-8"), "iso-8859-1");
    // 构建下载时的文件名
    headers.setContentDispositionFormData("attachment", fileName);
    // 转换成为二进制流
    headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
    // 返回下载文件实体
    return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file), headers, HttpStatus.CREATED);
}

前端代码如下:

<a href="loginController/download">下载</a>

点击查看更多内容
1人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
JAVA开发工程师
手记
粉丝
49
获赞与收藏
326

关注作者,订阅最新文章

阅读免费教程

感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消