@mvc的注意的地方

把@RequestMapping放在类级别上是合法的,这可令它与方法级别上的@RequestMapping注解协同工作,取得缩小选择范围的效果,下面是一些例子。

类级别:

RequestMapping("/accounts/*")方法级别:

@RequestMapping(value="delete", method=RequestMethod.POST)
@RequestMapping(value="index", method=RequestMethod.GET, params="type=checking")
@RequestMapping

第一个方法级的请求映射和类级别的映射结合,当HTTP方法是POST时与路径“/accounts/delete”匹配;第二个添加了一个要求,就是名为“type”的请求参数和其值“checking”都需要在请求中出现;第三个根本就没有指定路径,这个方法匹配所有的 HTTP方法,如果有必要的话可以用它的方法名。下面改写我们的方法,使它可以依靠方法名进行匹配,程序如下:

@Controller @RequestMapping("/accounts/*") public class AccountsController { @RequestMapping(method=RequestMethod.GET) public void show(@RequestParam("number") String number, Map<String, Object> model) { model.put("account", accountRepository.findAccount(number)); } ...方法匹配的请求是“/accounts/show”,依据的是类级别的@RequestMapping指定的匹配路径“/accounts/*”和方法名“show”。

消除类级别的请求映射
[color=red]Web层注解频遭诟病是有事实依据的,那就是嵌入源代码的URI路径。这个问题很好矫正,URI路径和控制器类之间的匹配关系用XML配置文件去管理,只在方法级的映射中使用@RequestMapping注解。[/color]
我们将配置一个ControllerClassNameHandlerMapping,它使用依赖控制器类名字的惯例,将URI映射到控制器:

<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"/>现在“/accounts/*”这样的请求都被匹配到AccountsController上,它与方法级别上的@RequestMapping注解协作的很好,只要添加上方法名就能够完成上述映射。此外,既然我们的方法并不会返回视图名称,我们现在就可以依据惯例匹配类名、方法名、URI路径和视图名。

当@Controller被完全转换为@MVC后,程序的写法如下:

@Controller public class AccountsController { private AccountRepository accountRepository; @Autowired public AccountsController(AccountRepository accountRepository) { this.accountRepository = accountRepository; } @RequestMapping(method=RequestMethod.GET) public void show(@RequestParam("number") String number, Map<String, Object> model) { model.put("account", accountRepository.findAccount(number)); } ...对应的XML配置文件如下:

<context:component-scan base-package="com.abc.accounts"/> <bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"/> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/" /> <property name="suffix" value=".jsp" /> </bean>你可以看出这是一个最精减的XML。程序里注解中没有嵌入URI路径,也没有显式指定视图名,请求处理方法也只有很简单的一行,方法签名与我们的需求精准匹配,其它的请求处理方法也很容易添加。不需要基类,也不需要XML(至少也是没有直接配置控制器),我们就能获得上述所有优势。

也许接下来你就可以看到,这种程序设计模型是多么有效了。

[[color=cyan]size=x-large]惯例优先原则(convention over configuration)
对于很多项目来说,遵从已有的惯例和使用合理的缺省选项大概是最合情合理的做法。现在Spring Web MVC框架也明确支持这种惯例优先的配置。具体来说,如果你在项目中遵守一定的惯例(比如命名规范),你可以显著地减少系统需要的配置(比如处理器映射,视图解析器配置,ModelAndView的声明,等等)。这对快速系统建模(rapid prototyping)是非常有利的。如果你打算进一步把模型完成为可以工作的系统,这样写出的代码也具有很好的一致性。

提示
Spring的开发包中有一个web应用的范例。这个范例演示了这一节提到的惯例优先原则。你可以在samples/showcases/mvc-convention目录中找到这个范例。

This convention over configuration support address the three core areas of MVC - namely, the models, views, and controllers.

Spring对惯例优先原则的支持体现在MVC的3个核心领域:模型、视图和控制器。

13.11.1. 对控制器的支持: ControllerClassNameHandlerMapping
ControllerClassNameHandlerMapping是HandlerMapping接口的一个实现。它检查请求的URL,然后通过惯例来决定与之相对应的控制器。

比如,下面有个非常简单的控制器实现,请特别注意这个类的名字。

public class ViewShoppingCartController implements Controller { public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) { // the implementation is not hugely important for this example... }}下文是从Spring Web MVC 框架的配置文件中选出来的一段:

<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping "/> <bean id="viewShoppingCart" class="x.y.z.ViewShoppingCartController"> <!-- inject dependencies as required... --></bean>ControllerClassNameHandlerMapping在应用的上下文中找出所有的请求处理器(handler)(或实现了Controller接口的)bean。把这些bean的名字中Controller后缀去掉,就得到了每个控制器所能处理的URL。

让我们通过举例来进一步解释这个映射的工作原理。

WelcomeController映射到'/welcome*'这个URL

HomeController映射到'/home*'这个URL

IndexController映射到'/index*'这个URL

RegisterController映射到'/register*'这个URL

DisplayShoppingCartController映射到'/displayshoppingcart*'这个URL

(注意字母的大小写。URL全部都用小写,但在Java类名中每个单词的第一个字母要大写。)

当控制器是MultiActionController的子类时,自动生成的映射就稍有点复杂,但应该还是比较好理解的。下面例子中这几个控制器都是MultiActionController。

AdminController映射到 '/admin/*' 这个URL。

CatalogController映射到 '/catalog/*' 这个URL。

如果你的控制器类遵守这些命名规范(xxxController),ControllerClassNameHandlerMapping可以自动生成映射,这样你就不必费劲的定义和维护一长串SimpleUrlHandlerMapping(或者类似的映射策略)。

ControllerClassNameHandlerMapping是AbstractHandlerMapping的子类,所以你仍旧可以像对待其他HandlerMapping实例一样来定义HandlerInterceptor的实例。

13.11.2. 对模型的支持:ModelMap (ModelAndView)
ModelMap是一个加强版的Map实现。在这个Map里,每个对象的键都遵守一个命名规范,然后这些对象就可以显示在视图中。这个类的使用其实很简单,不需要长篇大论。下面让我们看几个例子,然后我们结合例子进行讲解。

下面是一个Controller的实现。请注意当我们把对象加到ModelAndView时,我们不需要声明每个对象的键名。

public class DisplayShoppingCartController implements Controller { public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) { List cartItems = // get a List of CartItem objects User user = // get the User doing the shopping ModelAndView mav = new ModelAndView("displayShoppingCart"); <-- the logical view name mav.addObject(cartItems); <-- look ma, no name, just the object mav.addObject(user); <-- and a'ain ma! return mav; }}ModelAndView在内部使用了ModelMap。ModelMap是一个自定义的Map实现,它可以为加入其中的每个对象自动生成一个键名。这些键名是有规律的。当存入的对象是存储单值的对象(scalar object),比如User,生成的键名就是对象的类名(不包括包的名字)。下面几个例子详细解释了这个命名规范:

x.y.User这个类的实例对应user。

x.y.Registration 这个类的实例对应registration

x.y.Foo这个类的实例对应foo

java.util.HashMap的实例对应hashMap(在这种情况下你最好还是自己声明键名,hashMap这个名字不那么直观)

当你视图把null这个值加入Map时,你会得到IllegalArgumentException。 所以如果你的某个对象可能为null,你最好也自己声明键名。

什么?不能自动生成复数?

Spring Web MVC框架对惯例优先原则的支持不包括自动生成模型名字的复数。这意味着,当你把一个由Person对象组成的List加入ModelAndView时,不要指望Spring生成的键名会是people。

这是经过一系列讨论之后作出的决定。这样做符合“最少意外原则(Principle of Least Surprise)”。

当你加入ModelAndView中的对象是Set、List或者数组时,Spring会检查这个集合,取出这个集合中的第一个对象,然后用它的类名,加上List后缀,就是最终生成的名字。下面几个例子进一步解释了这个命名规则:

一个由 x.y.User组成的数组对应userList这个名字。

一个由x.y.Foo组成的数组对应fooList这个名字。

一个由x.y.User组成的java.util.ArrayList对应userList这个名字。

一个由x.y.Foo组成的java.util.HashSet对应fooList这个名字。

一个空的java.util.ArrayList根本不可能被加到这个Map中。(在这种情况下,adObject(..)其实什么都没做)。

13.11.3. 对视图的支持: RequestToViewNameTranslator
RequestToViewNameTranslator这个接口的功能是自动寻找请求所对应的视图名(当某个视图名没有明确配置的时候)。这个接口目前只有一个实现,类名为DefaultRequestToViewNameTranslator。

为了解释DefaultRequestToViewNameTranslator是如何将请求的URL映射到视图名,最好的方法就是举例说明。下面是一个Controller的实现,和它对应的配置文件。

public class RegistrationController implements Controller { public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) { // process the request... ModelAndView mav = new ModelAndView(); // add data as necessary to the model... return mav; // notice that no View or logical view name has been set }}<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd"><beans> <!-- this bean with the well known name generates view names for us --> <bean id="viewNameTranslator" class="org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator"/> <bean class="x.y.RegistrationControllerController"> <!-- inject dependencies as necessary --> </bean> <!-- maps request URLs to Controller names --> <bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"/> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver "> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> </bean></beans>请注意,在这个handleRequest(..)方法中,返回的ModelAndView实例不包含View的实例或者逻辑视图名。真正从请求的URL中分析出逻辑视图名(logical view name)的是DefaultRequestToViewNameTranslator。在上面这个例子中,RegistrationControllerController和ControllerClassNameHandlerMapping在一起使用,所有对http://localhost/registration.html这个URL的请求将会对应registration这个逻辑视图名。这个视图名正是由DefaultRequestToViewNameTranslator解析出来的。然后,InternalResourceViewResolver这个bean会将这个逻辑视图名进一步解析成/WEB-INF/jsp/registration.jsp这个视图。

提示
你甚至不需要配置类型为DefaultRequestToViewNameTranslator的bean。如果DefaultRequestToViewNameTranslator的缺省行为已经符合你的要求,你就可以使用这个类。当你没有明确声明时,Spring Web MVC 中DispatcherServlet这个类会自动生成一个DefaultRequestToViewNameTranslator的实例。

当然,如果你有自己特殊的要求,你就需要配置DefaultRequestToViewNameTranslator bean。如果你需要知道这个类有哪些可以设置的参数,请参阅DefaultRequestToViewNameTranslator的Javadoc[/color]。[/[/size]size][[/color]color=cyan]http://blog.youkuaiyun.com/dengqf/archive/2008/11/19/3333597.aspx[/color]
内容概要:该论文聚焦于T2WI核磁共振图像超分辨率问题,提出了一种利用T1WI模态作为辅助信息的跨模态解决方案。其主要贡献包括:提出基于高频信息约束的网络框架,通过主干特征提取分支和高频结构先验建模分支结合Transformer模块和注意力机制有效重建高频细节;设计渐进式特征匹配融合框架,采用多阶段相似特征匹配算法提高匹配鲁棒性;引入模型量化技术降低推理资源需求。实验结果表明,该方法不仅提高了超分辨率性能,还保持了图像质量。 适合人群:从事医学图像处理、计算机视觉领域的研究人员和工程师,尤其是对核磁共振图像超分辨率感兴趣的学者和技术开发者。 使用场景及目标:①适用于需要提升T2WI核磁共振图像分辨率的应用场景;②目标是通过跨模态信息融合提高图像质量,解决传统单模态方法难以克服的高频细节丢失问题;③为临床诊断提供更高质量的影像资料,帮助医生更准确地识别病灶。 其他说明:论文不仅提供了详细的网络架构设计与实现代码,还深入探讨了跨模态噪声的本质、高频信息约束的实现方式以及渐进式特征匹配的具体过程。此外,作者还对模型进行了量化处理,使得该方法可以在资源受限环境下高效运行。阅读时应重点关注论文中提到的技术创新点及其背后的原理,理解如何通过跨模态信息融合提升图像重建效果。
<think>好的,我现在需要回答用户关于基于Servlet的MVC模式开发的注意事项及最佳实践的问题。首先,我得回顾一下用户提供的引用内容,尤其是引用[1]、[2]和[3],因为它们提到了MVC模式在Servlet和JSP中的使用,以及集成Spring框架的情况。用户可能希望了解在纯Servlet环境下开发MVC应用时需要注意地方,而不仅仅是框架集成。 首先,我需要明确MVC的三个组件在Servlet中的角色。根据引用[1]和[2],Controller是Servlet,Model是POJO或数据库相关,View是JSP。因此,注意事项可能涉及如何正确分离这三层,避免逻辑混杂。比如,Servlet不应该处理数据持久化,而应该交给Model层。 接下来,用户提到的注意事项可能包括请求处理、数据传递、安全性等。比如,Servlet作为控制器,需要正确解析请求参数,调用适当的业务逻辑,然后转发到JSP。同时,需要避免在JSP中编写业务逻辑,保持视图的纯净。这点在引用[2]中也有提到,视图负责渲染数据,所以需要注意不要在JSP中使用过多的Java代码。 另外,异常处理也是一个重要点。用户可能想知道如何处理异常,比如在Servlet中捕获异常并转发到错误页面,保证用户体验。引用中没有直接提到异常处理,但根据最佳实践,这应该是需要考虑的。 还有,会话管理的问题。引用[1]提到会话管理作为安全实践的一部分,所以在MVC开发中需要注意会话的安全性,比如防止会话劫持,合理设置会话超时等。 性能优化也是一个方面。比如,Servlet是否是线程安全的,如何避免实例变量的使用导致线程问题。引用[3]提到集成Spring框架的优势,比如控制反转,但用户的问题是基于Servlet的,所以可能需要提到原生Servlet的线程安全问题,以及如何通过避免使用实例变量来保证线程安全。 数据验证也是需要注意的,用户输入的数据需要在Controller层进行验证,防止无效数据进入Model层。同时,防止XSS攻击等安全措施,比如在输出到视图时对数据进行转义,这在引用[1]中提到的安全实践相关。 还有配置方面的问题,比如web.xml中Servlet的配置是否正确,URL映射是否合理,避免直接访问JSP页面绕过Controller,这有助于维护MVC的结构。 然后,关于最佳实践,可能需要提到使用前端控制器模式,比如一个中央Servlet来处理所有请求,并根据参数分发到不同的处理程序。或者提到使用现有的MVC框架如Spring MVC,但用户的问题是基于Servlet的,所以可能更多是原生实现的最佳实践。 另外,引用[4]提到了项目配置和环境设置,比如数据库连接、Tomcat配置,这些在开发中需要注意,比如确保数据库连接正确,资源释放,避免内存泄漏。在Servlet中,数据库操作应该在Model层处理,并且使用连接池等技术优化性能。 最后,测试和可维护性也是需要考虑的。如何编写可测试的Servlet代码,比如将业务逻辑与Servlet分离,便于单元测试。引用[2]提到MVC提高可维护性,所以在注意事项中应该强调分层清晰,模块化设计。 可能还需要提到避免在Servlet中硬编码配置,比如使用初始化参数或外部配置文件,方便维护。同时,遵循RESTful设计原则,合理设计URL结构,提高应用的可读性和可维护性。 总结下来,注意事项可能包括: 1. 明确分层职责,避免代码混杂。 2. Servlet的线程安全问题。 3. 请求处理和参数解析的正确方法。 4. 数据验证和安全措施。 5. 异常处理和错误页面配置。 6. 会话管理和安全性。 7. 配置和部署注意事项。 8. 性能优化,如数据库连接池。 9. 可测试性和可维护性设计。 在回答时,需要将这些点组织成结构清晰的列表,每一点给出具体的建议,并结合引用中的内容,比如引用[1]提到的会话管理,引用[2]提到的MVC各层职责,引用[3]可能提到的配置和框架集成(但用户的问题是基于Servlet原生开发,所以可能不直接涉及Spring,但可以提到后续扩展的可能性)。 另外,用户的问题可能还涉及实际开发中的常见错误,比如在JSP中嵌入过多Java代码,导致视图层与业务逻辑混合,这需要避免。同时,转发和重定向的选择,比如使用RequestDispatcher转发到JSP,而不是直接重定向,以保持请求上下文。 最后,生成的相关问题需要围绕MVC开发的其他方面,比如如何优化性能,如何扩展应用,如何进行测试等。</think>### 基于 Servlet 的 MVC 模式开发注意事项及最佳实践 在基于 Servlet 的 MVC 模式开发中,需重点关注职责划分、安全性、性能及代码可维护性。以下是具体注意事项及实践建议: --- #### **1. 明确分层职责** - **Controller(Servlet)** - 仅处理请求解析、参数校验和流程控制,避免包含业务逻辑或数据操作[^2]。 - 示例:使用 `doGet()` 或 `doPost()` 方法接收请求,调用 Model 层处理数据,最后转发至 View。 ```java protected void doPost(HttpServletRequest request, HttpServletResponse response) { String username = request.getParameter("username"); UserService userService = new UserService(); // Model 层调用 User user = userService.getUser(username); request.setAttribute("user", user); request.getRequestDispatcher("/user.jsp").forward(request, response); // 转发至 View } ``` - **Model(POJO/Service)** - 封装业务逻辑和数据库操作(如 CRUD),与 Controller 解耦[^1]。 - 推荐使用 DAO(Data Access Object)模式管理数据库连接,避免在 Servlet 中直接操作 SQL。 - **View(JSP)** - **仅负责数据展示**,禁止在 JSP 中编写 Java 业务逻辑[^2]。 - 使用 EL 表达式 `${user.name}` 或 JSTL 标签替代 `<% %>` 脚本,提升可读性。 --- #### **2. 安全性注意事项** - **输入验证与过滤** - 在 Controller 层对用户输入进行严格校验(如格式、长度),防止 SQL 注入或 XSS 攻击[^1]。 - 示例:使用 `StringEscapeUtils.escapeHtml4()` 对输出内容转义。 - **会话管理** - 避免在 URL 中传递敏感信息,优先使用 `HttpSession` 存储会话状态。 - 设置合理的会话超时时间,并在用户登出时手动调用 `session.invalidate()`[^1]。 --- #### **3. 性能优化** - **线程安全** - Servlet 是单例多线程的,避免使用实例变量(如 `private int count;`),改用局部变量或同步控制[^3]。 - **数据库连接池** - 使用连接池(如 HikariCP)管理数据库连接,减少频繁创建/关闭连接的开销。 - **缓存策略** - 对静态资源(如 CSS、JS)配置浏览器缓存,减少重复请求。 --- #### **4. 异常处理** - **统一错误页面** - 在 `web.xml` 中配置 `<error-page>`,将异常转发至友好错误页。 ```xml <error-page> <exception-type>java.lang.Exception</exception-type> <location>/error.jsp</location> </error-page> ``` - **日志记录** - 使用 Log4j 或 SLF4J 记录异常详情,便于排查问题。 --- #### **5. 配置与维护** - **避免硬编码** - 将数据库连接参数等配置在 `web.xml` 或 `properties` 文件中,通过 `ServletContext` 读取。 - **模块化设计** - 按功能拆分多个 Servlet,并通过 `@WebServlet` 注解或 `web.xml` 配置路由。 --- #### **6. 扩展性与测试** - **依赖注入** - 可通过简单工厂模式解耦 Servlet 与 Model,提升可测试性[^3]。 - 示例:将 `UserService` 的创建交给工厂类。 - **单元测试** - 使用 Mock 工具(如 Mockito)模拟 `HttpServletRequest` 和 `HttpServletResponse`。 --- ### 示例代码结构 ``` src/ ├── main/ │ ├── java/ │ │ ├── com.example.controller/UserServlet.java // Controller │ │ ├── com.example.service/UserService.java // Model │ ├── webapp/ │ │ ├── WEB-INF/ │ │ │ ├── views/user.jsp // View │ │ ├── resources/ │ │ │ ├── db.properties // 配置文件 ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值