当前位置:编程学习 > JAVA >>

spring mvc 知识

1. web.xml 配置

<servlet>
    <servlet-name>spring</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!-- 如果不配置配置文件的位置以及文件名,则会默认的在 WEB-INF/下寻找  <servlet-name>-servlet.xml  -->
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/classes/spring-servlet.xml</param-value>
        <!-- 
        如果含有多个配置文件,可同时配置,中间用分隔符隔开即可
        <param-value>/WEB-INF/classes/spring-servlet.xml,/WEB-INF/classes/spring-servlet2.xml</param-value>
   甚至可以利用通配符来完成
    <param-value>/WEB-INF/classes/*.xml</param-value>
    这样,即加载 /WEB-INF/classes/目录下的所有 xml文件
         -->
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>spring</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>

2.spring-servlet.xml 配置

<context:component-scan base-package="org.yao.controller"></context:component-scan>

<!-- inteceptor 的配置 -->
<mvc:interceptors>
<!--这样 MyInteceptor 就可拦截 以 /background/*的请求了 -->
<mvc:interceptor>
<mvc:mapping path="/background/*" />
<bean class="org.yao.controller.MyInteceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
<!-- 国际化的配置 -->
<!-- 注意:id 必须为messageResource,同时需配置 basename属性,value为属性配置文件的名称  -->
<bean id="messageResource" class="org.springframework.context.support.ResourceBundleMessageSource">
    <property name="basename" value="message"></property>
    <!-- 如果是多个 国际化配置文件,则可利用 basenames进行配置 -->
    <!-- <property name="basenames">
        <list>
            <value>message1</value>
            <value>message2</value>
        </list>
    </property> -->
</bean>


<!-- <bean class="org.springframework.web.servlet.view.UrlBasedViewResolver"> -->
<!-- InternalResourceViewResolver 与 UrlBasedViewResolver 的主要区别是 , InternalResourceViewResolver对UrlBasedViewResolver 
进行了封装,对jsp以及jstl技术进行了较好的支持 -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 因为InternalResourceViewResolver 默认含有了viewClass,其值就是:org.springframework.web.servlet.view.JstlView -->
<!-- 所以,下面这行,可以去除 -->
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView"></property>
<property name="prefix" value="/WEB-INF/view/"></property>
<property name="suffix" value=".jsp"></property>
</bean>

3. Interceptor

public class MyInteceptor implements HandlerInterceptor {
// 在页面生成后调用,主要用于释放资源
public void afterCompletion(HttpServletRequest arg0,
HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {

}
// 在controller处理请求之后,页面生成之前,进行调用
public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
Object handler, ModelAndView arg3) throws Exception {

}
// 在controller处理请求之前,进行调用
// handler 即为下一个处理对象的引用,如果下一个是 Inteceptor,则handler为 Inteceptor,如果是 controller,则 hanlder为 controller的引用

public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1,
Object handler) throws Exception {
return false;
}

}

4. Controller with REST

/*
原始风格
http://localhost:8080/example05_annotation/start.do?name=zhangsan
http://localhost:8080/example05_annotation/start.do?name=lisi
Rest风格:
http://localhost:8080/example05_annotation/start/zhangsan.do
http://localhost:8080/example05_annotation/start/lisi.do
*/
@Controller
public class StartContorllerForRest {
/* 
"/start/{name}" 为 url 模板,{} 内的值是可变的
同时,@PathVariable("name") String name 中的@PathVariable("name") name名称必须与 url模板中定义的变量相同
*/

//http://localhost:8080/example05_annotation/start/zhangsan.do
@RequestMapping("/start/{name}")
public String start(@PathVariable("name") String name){
System.out.println("name"+name);
return "start";
}

//http://localhost:8080/example05_annotation/start/zhangsan/20.do
@RequestMapping("/start/{name}/{age}")
public String startForMultiParam(@PathVariable("name") String name,@PathVariable("age") int age){
System.out.println("name="+name+"  age="+age);
return "start";
}
@InitBinder
public void initBinder(
WebRequestDataBinder binder) throws Exception {
// if true, 说明值可以为空,否则的话不能为空
binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM--dd"), true));
super.initBinder(request, binder);
}

}

5.Controler with redirct

@Controller
public class StartContorllerForRedirect {
// 为了实现 redirect效果,而不是dispatcher,可在返回的逻辑视图前面加入  "redirect:"
@RequestMapping("/start")
public String start(){
return "redirect:start";
}

} Spring MVC --------------------编程问答-------------------- 6. Controler for param

@Controller
public class StartContorllerForParam {
/*
 * 强大之处:参数的个数无限制,参数的顺序亦无限制
 */

@RequestMapping("/start1")
public String start1(){
return "start";
}
/*
 * 获取session的前提是当前session可用
 */
@RequestMapping("/start2")
public String start2(HttpServletRequest request,HttpServletResponse response,HttpSession session){
return "start";
}


// @PathVariable("name") @RequestParam  @CookieValue @RequestHeader 中的 String可以是任意类型,只是如果是Date等其他类型,需绑定属性编辑器
// 即通过 initBinder来实现
//http://localhost:8080/example05_annotation/start/zhangsan.do
@RequestMapping("/start/{name}")
public String start3(@PathVariable("name") String name,@RequestParam String password,@CookieValue String cookieValue,@RequestHeader String header){
return "start";
}

@RequestMapping("/start4")
public String start4(PrintWriter out){
out.write("user name is incorrect");
return "start";
}

// 通过这种方式,在jsp页面上依旧可以访问到这个model
@RequestMapping("/start5")
public String start5(Map<String,String[]> model){
model.put("dept", new String[]{"product","manage"});
return "start";
}

// 实现 Struts中的ModelDriver功能,也是spring的AbstractCommandController效果
// http://localhost:8080/example05_annotation/start6.do?name=zhangsan&password=123
@RequestMapping("/start6")
public String start6(Emp emp){
System.out.println(emp);
return "start";
}
/*
如果需要对绑定异常进行处理,可加入 BindingResult
public String start6(Emp emp,BindingResult result){
System.out.println(emp);
return "start";
}
*/
}

7. Controller for result

@Controller
@RequestMapping("/background")
public class StartContorllerForResult {
/*
 * 不返回任何值需注意:
 * 如果不调用 printWriter out来输出页面,则 会进行默认调整,跳转的视图是根据请求路径来处理:
 * 如:
@RequestMapping("/start")
public void start(){

}
则spirng处理器会根据请求路径 {appName}/background/start.do 默认生成的viewName="background/start"
即 寻找 WEB-INF/view/background/start.jsp
 */
@RequestMapping("/start")
public void start(PrintWriter out){
out.write("name is incorrect");
}

@RequestMapping("/start1")
public String start1(){
return "start";
}

//这种效果实际上是把 返回的emp放到了Model中,由jsp进行读取
// model中的 key为类名,本例为 emp,第一个字符会转换成 小写
@RequestMapping("/start2")
public Emp start2(){
Emp emp=new Emp();
emp.setEmpNo(1);
return emp;
}

//这种效果实际上是把 返回的List<Emp>放到了Model中,由jsp进行读取
// model中的 key为泛型类名+List,本例为 empList,第一个字符会转换成 小写
//Set的效果亦是这样,如 empSet
@RequestMapping("/start3")
public List<Emp> start3(){
return null;
}

// 此Map则将直接作为 model
@SuppressWarnings("rawtypes")
@RequestMapping("/start4")
public Map start4(){
return null;
}

@RequestMapping("/start5")
public ModelAndView start5(){
return null;
}
}
8 Handler Mapping 01

<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    <property name="mappings">
        <props>
            <prop key="controller01.do">Controller01</prop>
            <prop key="controller02.do">Controller02</prop> 
            <prop key="controller03.do">Controller03</prop>
            <prop key="controller04.do">Controller04</prop>
            <prop key="to_add.do">Controller05</prop>
            <prop key="add_emp.do">Controller05</prop>
        </props>
    </property>
</bean>
<!-- 第一种 controller,即实现 Controller类,或者AbstractController接口 -->
<bean id="Controller01" class="org.yao.controller.Controller01"></bean>

<!-- 第二种Controller,利用spring自有的 ParameterizableViewController来实现,其主要是用于处理直接跳转到view页面的请求,而不需要进行业务处理-->
<bean id="Controller02" class="org.springframework.web.servlet.mvc.ParameterizableViewController">
    <property name="viewName" value="controller02"></property>
</bean> 
<!-- 
第三种利用spring自有的 UrlFilenameViewController来实现,用途跟 ParameterizableViewController一样,只是省略 valueName的配置,
此类的根据url的前缀来寻找相关的视图,如controller03.do,则相当于 viewName=controller03
 -->
<bean id="Controller03" class="org.springframework.web.servlet.mvc.UrlFilenameViewController" /> 

<!-- 第四种, -->
<bean id="Controller04" class="org.yao.controller.Controller04">
    <property name="commandClass" value="org.yao.model.Emp">
    </property>
</bean>

<!-- 第五种, -->
<bean id="Controller05" class="org.yao.controller.Controller05">
    <property name="methodNameResolver">
        <bean class="org.springframework.web.servlet.mvc.multiaction.InternalPathMethodNameResolver"></bean> 
       <!--  <bean class="org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver"></bean>-->
       <!--  <bean class="org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver">
            <property name="paramName" value="function"></property>
        </bean>
        -->
    </property>
</bean>

public class Controller01 implements Controller {

public ModelAndView handleRequest(HttpServletRequest arg0,
HttpServletResponse arg1) throws Exception {
System.out.println("Controller01 is working");
// 返回一个逻辑view的字符串,可有viewResult来指定后缀,如jsp,html
//viewResult 主要作用是视图解析
return new ModelAndView("controller01");
}


}

/*
 * 能够封装请求参数到model的controller
 * 当然,也可利用SimpleFormController来实现这种请求,
 * AbstractCommandController 与  SimpleFormController区别:
 * 
 */
@SuppressWarnings("deprecation")
public class Controller04 extends AbstractCommandController {

@Override
protected ModelAndView handle(HttpServletRequest request,
HttpServletResponse response, Object command, BindException exception)
throws Exception {
Emp emp=(Emp)command;
System.out.println(emp);
return new ModelAndView("success");
}
// 在没有实现这个方法的时候: 输出 empNo1 namess passwordss hireDatenull
//说明 hireDate属性并没有注入值,为此,需要自己来实现string to date的绑定
@Override
protected void initBinder(HttpServletRequest request,
ServletRequestDataBinder binder) throws Exception {
binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true));
super.initBinder(request, binder);
}
}
/*
 * 继承AbstractCommandController的方式,与下面这种手动封装数据到model相比,快捷而且方便
 */
 class Controller04_compare implements Controller {

public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
Emp emp=new Emp();
emp.setEmpNo(Integer.parseInt((String)request.getAttribute("empNo")));
emp.setName((String)request.getAttribute("name"));
emp.setPassword((String)request.getAttribute("password"));
emp.setHireDate(new SimpleDateFormat("yyyy-MM-dd").parse((String)request.getAttribute("hireDate")));
System.out.println(emp);
return null;
}
}

public class Controller05 extends MultiActionController {
public ModelAndView to_add(HttpServletRequest request,HttpServletResponse response){
HashMap<String,String[]> model=new HashMap<String,String[]>();
model.put("detpList",new String[]{"produce","manage"});
return new ModelAndView("controller03",model);
}

public String add_emp(HttpServletRequest request,HttpServletResponse response,Object command){
/*
 * 对于如何绑定,现在还不知道
Emp emp=(Emp)command;
System.out.println(emp);*/
return ("success");
}
@Override
protected void initBinder(HttpServletRequest request,
ServletRequestDataBinder binder) throws Exception {
binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM--dd"), true));
super.initBinder(request, binder);
}
}

9.Handler Mapping 02

<!--
ControllerClassNameHandlerMapping 与   SimpleUrlHandlerMapping的区别:
不用配置 url到具体controller的映射
默认规则是 根据url的请求来完成,如 abc.do则会转发到AbcContoller控制器中去处理
而对于一个控制器处理多请求的,则可利用 MultiActionController,如利用InternalPathMethodNameResolver作为methodNameResolver时,
 需要注意 url的写法:即:muliteRequestController/to_add.do 或者 muliteRequestController/add_emp.do
-->

<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping">
</bean>

<!-- 
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    <property name="mappings">
        <props>
            <prop key="controller01.do">Controller01</prop>
            <prop key="controller02.do">Controller02</prop> 
            <prop key="controller03.do">Controller03</prop>
            <prop key="controller04.do">Controller04</prop>
            <prop key="to_add.do">Controller05</prop>
            <prop key="add_emp.do">Controller05</prop>
        </props>
    </property>
</bean> 
-->
<!-- 利用 ControllerClassNameHandlerMapping来进行映射,bean的id取值无所谓,或者不取 -->
<bean id="Controller01" class="org.yao.controller.AbcController"></bean>
<bean id="Controller05" class="org.yao.controller.MuliteRequestController">
    <property name="methodNameResolver">
        <bean class="org.springframework.web.servlet.mvc.multiaction.InternalPathMethodNameResolver"></bean> 
    </property>
</bean>

10 国际化

<%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<!-- text属性用于指定,如 国际化资源配置文件中没有 welcome的配置,则采用默认的 text作为显示输出 -->
<spring:message code="welcome" text="欢迎光临"></spring:message>

11 validation JSR-303

@RequestMapping
public String addUser(@Valid User user, BindingResult result){
if(result.hasErrors()){
return "fromView";
}
return "redirect:/user_list";
}

public class User{
@NotEmpty
private String name;
@Size(min=20,max=40)
}

jar hibernate-validator-version.jar
    validation-api-version.jar
    slf.jar
    log4j
--------------------编程问答-------------------- 12 REST

以资源为导向
list/useId/update
list/userId/delete

location = username/show?json
@ResponseBody
@RequestMapping(value="/{username}/show",param="json")
public void show(@PathVariable String username){

}

@pararm 相当于 在方法头部加入 @RequestParam String json

当然,使用这种方式需要导入相关的json包,以及配置 contentNegotiatingViewResolver

13 Session
在Controller中加入 @SessionAttribute(name="loginUser")

如果某个方法想在session中保存值,那么只需要 利用 model.addAttribute("loginUser",user) 即可向session中保存这个对象了

14 handler exception

在controller中加入
@ExceptionHandler(value={UserException,OtherException})
public String handlerException(Exception ex, HttpServletRequest request){
request.setAttribute("ex",ex);
return "error";
}
这样,只要在这个controller中发生了 UserException 或者 OtherException, 就会跳转到 error页面

15 sitemesh 学习

16 redirect 传值

public string redirect(RedirectAttribute re){
re.addFlushAttribute("ss","ss");
retrun "redirect:/user/list";
}
这样,就能够在 list页面中获取 ss,其实现方式也是通过session来session,只是在取完之后及时删除了。

17 文件上传

<input type="file" name="photos"/><br/>
<input type="file" name="photos"/><br/>
单个文件上传 MultipartFile photo
多个文件上传 MultipartFile[] photos
BindingResult一定要放在要验证对象的后面
@RequestMapping(value="/add",method=RequestMethod.POST)
public String add(@Valid User user,BindingResult binding,@RequestParam(required=false) MultipartFile[] photos,HttpServletRequest req) throws IOException {
if(binding.hasErrors()) {
return "user/add";
}
for(MultipartFile photo:photos) {
if(photo.isEmpty()) continue;
System.out.println(photo.getContentType()+","+photo.getName()+","+photo.getOriginalFilename());
String realpath = req.getSession().getServletContext().getRealPath("/resources/upload/");
System.out.println(realpath);
FileUtils.copyInputStreamToFile(photo.getInputStream(), new File(realpath+"/"+photo.getOriginalFilename()));
}
users.put(user.getUsername(), user);
return InternalResourceViewResolver.REDIRECT_URL_PREFIX+"/user/users";
}
补充:Java ,  非技术区
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,