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>
共同学习,写下你的评论
评论加载中...
作者其他优质文章