Spring MVC Controller单例陷阱

Spring MVC Controller默认是单例的:

单例的原因有二:
1、为了性能。
2、不需要多例。

1、这个不用废话了,单例不用每次都new,当然快了。
2、不需要实例会让很多人迷惑,因为spring mvc官方也没明确说不可以多例。
我这里说不需要的原因是看开发者怎么用了,如果你给controller中定义很多的属性,那么单例肯定会出现竞争访问了。
因此,只要controller中不定义属性,那么单例完全是安全的。下面给个例子说明下:

package com.lavasoft.demo.web.controller.lsh.ch5;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* Created by Administrator on 14-4-9.
*
* @author leizhimin 14-4-9 上午10:55
*/
@Controller
@RequestMapping("/demo/lsh/ch5")
@Scope("prototype")
public class MultViewController {
private static int st = 0; //静态的
private int index = 0; //非静态
@RequestMapping("/show")
public String toShow(ModelMap model) {
User user = new User();
user.setUserName("testuname");
user.setAge("23");
model.put("user", user);
return "/lsh/ch5/show";
}
@RequestMapping("/test")
public String test() {
System.out.println(st++ + " | " + index++);
return "/lsh/ch5/test";
}
}


0 | 0
1 | 1
2 | 2
3 | 3
4 | 4

改为单例的:
0 | 0
1 | 0
2 | 0
3 | 0
4 | 0


从此可见,单例是不安全的,会导致属性重复使用。

最佳实践:
1、不要在controller中定义成员变量。
2、万一必须要定义一个非静态成员变量时候,则通过注解@Scope("prototype"),将其设置为多例模式。
引自:http://lavasoft.blog.51cto.com/62575/1394669
<think>我们正在处理一个系统迁移问题:将PHP开发的网页转换为Java编写的网页。根据用户提供的引用,我们需要考虑以下几个方面: 1. **引用[1]**:提到PHP开发的标配是LAMP(Linux+Apache+MySQL+PHP),而Java通常使用不同的技术栈(如Spring框架)。 2. **引用[2]**:指出PHP7性能在某些方面可能优于Java,但Java在扩展性和高负载下处理能力更强(如连接池、中间件支持)。 3. **引用[3]**:比较了Java和PHP的安全性,指出Java是强类型语言,编码更严谨,重构方便,但开发节奏慢。 4. **引用[4]**:提到Spring框架在Java开发中的重要性,它是企业级开发的必备技能。 迁移步骤需要考虑: 1. **技术栈转换**: - PHP(LAMP) → Java(通常使用Spring Boot + Tomcat/Undertow + MySQL/Oracle等) - 前端部分(HTML5+JavaScript)可以保持不变,但后端逻辑需要重写。 2. **迁移步骤**: a. **分析现有PHP应用**: - 梳理所有功能模块(路由、业务逻辑、数据库操作等) - 特别关注PHP特有的特性(如动态变量、全局变量等)并设计Java替代方案 b. **设计Java架构**: - 选择Java框架(推荐Spring Boot,因其生态完善[^4]) - 设计MVC结构(Controller代替PHP脚本,Service处理业务逻辑) c. **数据库迁移**: - 数据库结构通常可以保持不变(MySQL表结构可以直接复用) - 将PHP的MySQLi/PDO操作转换为Java的JDBC或ORM(如Hibernate、MyBatis) d. **业务逻辑转换**: - 将PHP脚本逐功能转换为Java类和方法 - 注意处理类型差异(PHP弱类型 vs Java强类型[^3]) e. **部署环境调整**: - 从Apache+PHP模块改为Tomcat等Servlet容器 - 配置Java运行环境(JDK版本、应用服务器等) 3. **关键挑战**: - **性能调优**:Java在高负载下可通过连接池、缓存(如Redis)等优化[^2] - **安全性提升**:利用Java的强类型和Spring Security增强安全性[^3] - **开发效率**:使用Spring Initializr快速搭建项目,IDE(如IntelliJ IDEA)提供强大重构能力 4. **示代码对比**: **PHP连接MySQL**(原示): ```php <?php $conn = new mysqli("localhost", "user", "pass", "db"); if ($conn->connect_error) die("连接失败: " . $conn->connect_error); ?> ``` **Java等价实现(使用JDBC)**: ```java import java.sql.*; public class DBConnector { public static void main(String[] args) { try (Connection conn = DriverManager.getConnection( "jdbc:mysql://localhost:3306/db", "user", "pass")) { System.out.println("数据库连接成功"); } catch (SQLException e) { System.err.println("连接失败: " + e.getMessage()); } } } ``` **进阶方案(Spring Boot + JPA)**: ```yaml # application.yml spring: datasource: url: jdbc:mysql://localhost:3306/db username: user password: pass ``` ```java @Repository public interface UserRepository extends JpaRepository<User, Long> {} ``` 5. **迁移工具辅助**: - 数据库迁移:使用Flyway或Liquibase管理表结构变更 - 接口兼容:若需逐步迁移,可保留PHP接口并通过API与Java服务通信 > 迁移建议:优先迁移核心模块,逐步替换非核心功能,通过API网关实现新旧系统共存。 §§相关问题§§ 1. 如何设计Java Web应用的数据库连接池? 2. Spring Security如何配置防止SQL注入攻击? 3. 迁移过程中如何保持PHP和Java系统同时运行? 4. Java Web应用部署在Tomcat和Undertow有何性能差异? [^1]: PHP开发标配LAMP技术栈 [^2]: Java在高负载场景下的扩展能力优势 [^3]: Java强类型特性提升代码安全性和可维护性 [^4]: Spring框架是Java企业开发的行业标准</think>### 将PHP网页迁移到Java的完整方案 #### 一、迁移核心步骤 1. **架构转换** - PHP的LAMP架构 → Java的Spring Boot技术栈 - 组件映射关系: ```mermaid graph LR PHP[PHP] --> Java[Spring Boot] Apache[Apache] --> Tomcat[Tomcat/Undertow] MySQL[MySQL] --> JPA[Spring Data JPA] Linux[Linux] --> Docker[容器化部署] ``` 2. **代码迁移流程** ```mermaid graph TD A[分析PHP代码] --> B[设计Java结构] B --> C[数据库迁移] C --> D[业务逻辑重写] D --> E[前端适配] E --> F[安全加固] ``` #### 二、关键技术实现 1. **数据库迁移** - 保持MySQL数据库结构不变 - 使用JPA替代PHP的MySQLi操作: ```java // Spring Data JPA示 @Entity public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String username; // Getters & Setters } @Repository public interface UserRepository extends JpaRepository<User, Long> { User findByUsername(String username); } ``` 2. **业务逻辑转换** - PHP动态类型 → Java强类型系统 - 示对比: ```php // PHP动态变量 $total = $_POST['price'] * $_POST['quantity']; ``` ```java // Java强类型处理 @PostMapping("/calculate") public ResponseEntity<Double> calculateTotal( @RequestParam double price, @RequestParam int quantity) { return ResponseEntity.ok(price * quantity); } ``` 3. **前端适配方案** - 保留HTML/CSS/JS前端代码 - 模板引擎转换: | PHP模板 | Java替代方案 | |---------------|-------------------| | Blade | Thymeleaf | | Smarty | JSP/JSTL | | 原生PHP混合 | Spring MVC视图 | #### 三、性能与安全优化 1. **性能提升** - 引入连接池(如HikariCP)解决PHP无连接池缺陷[^2] - 添加缓存层(Redis/Ehcache) - 示配置: ```yaml # application.yml spring: datasource: hikari: maximum-pool-size: 20 connection-timeout: 3000 ``` 2. **安全加固** - 使用Spring Security替代PHP手动验证 - 关键防护措施: - CSRF防护(默认启用) - 参数校验注解(@Valid) - SQL注入防护(预编译语句) #### 四、迁移工具链 | 工具类型 | PHP工具 | Java替代方案 | |---------------|-----------------|--------------------------| | 依赖管理 | Composer | Maven/Gradle | | 元测试 | PHPUnit | JUnit + Mockito | | 持续集成 | Travis CI | Jenkins + GitLab CI | | 部署 | FTP/Shell | Docker + Kubernetes | #### 五、迁移注意事项 1. **渐进式迁移策略** - 优先迁移核心模块 - 通过API网关实现PHP/Java共存 - 方案: ``` 用户请求 --> API网关 --> [PHP服务 | Java新服务] ↑ 路由配置中心 ``` 2. **常见陷阱规避** - 会话管理:PHP session → Spring Session + Redis - 全局变量:改用SpringBean - 动态包含:重构为@Service组件 > **迁移收益**:Java的强类型系统和Spring框架可提升代码可维护性[^3],在高并发场景下通过连接池和集群扩展获得更好性能[^2]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值